20

I am working on a huge project which has one file A.h whose code has a line

typedef unsigned __int16   Elf64_Half;

Also since I am building on Linux and using dlinfo function, I have to include link.h file in my project. And this is where it creates a conflict because I have two typedefs having the same name Elf64_Half. (Linux link.h includes elftypes.h and it too has: typedef unsigned short Elf64_Half;).

What do I do in such a case? Is the only option I have, to change my typedef in a.h? Remember it is not too easy because the project is huge and I will have to make a change in several places.

Is there a way to undef a typedef or something?

Chen Li
  • 4,824
  • 3
  • 28
  • 55
voidMainReturn
  • 3,339
  • 6
  • 38
  • 66
  • 9
    The only way I know is to put them into different namespaces. – Mark Ransom Dec 12 '14 at 01:44
  • 5
    I'm waiting to see who will be the first to suggest a solution involving macros... – Mysticial Dec 12 '14 at 01:46
  • 1
    Wouldn't it be simple to remove the typedef from A.h and replace it with `#include `? You'd only have to change that one file, and everything would automatically get the single consistent type. – Rob Kennedy Dec 12 '14 at 02:49
  • @RobKennedy : No. The problem is that I need both of them. – voidMainReturn Dec 12 '14 at 17:49
  • I don't understand. They have the same name and essentially the same type. Why do you need two distinct types for that? (And you don't even need them distinct since you're talking about *undefining* one of them. Why not just undefine one of them permanently?) – Rob Kennedy Dec 12 '14 at 17:53
  • First of both the files are out of my control..I didn't define them..but the use case is that my project's A.h 's definition is used elsewhere in the project. I am not even using typedef from link.h but since I have to include it for using dlinfo() I am stuck with this problem. Hope this makes it clearer – voidMainReturn Dec 12 '14 at 18:48
  • Possible duplicate of [How could I (temporarily) un-typedef something?](https://stackoverflow.com/questions/25867905/how-could-i-temporarily-un-typedef-something) – Chen Li Jun 05 '18 at 04:26
  • https://bytes.com/topic/c/answers/215239-how-remove-type-defined-typedef-thx – Chen Li Jun 05 '18 at 04:47
  • Conditionally define your own `Elf64_Half` if not building on Linux, otherwise `#include `. Redefining third party types with macros is not a good idea. – n. m. could be an AI Jun 05 '18 at 05:44

3 Answers3

26

For clarification, Rahul Manne gave an easy solution. Do

#define Elf64_Half The_Elf64_Half_I_dont_care
#include<link.h>
#undef Elf64_Half
#include<A.h>

/*
 * Code here and use Elf64_Half from A.h as you like.
 * However, you can't use Elf64_Half from link.h here
 * or you have to call it The_Elf64_Half_I_dont_care.
 *
 */

This will substitute each Elf64_Half in link.h with The_Elf64_Half_I_dont_care and thus you get no conflicts with A.h. As long as you don't want to use Elf64_Half of link.h explicitly that will work with no problems. You just have to remember that Elf64_Half from link.h is now called The_Elf64_Half_I_dont_care in case you ever have to use it explicitly in this file.

Chen Li
  • 4,824
  • 3
  • 28
  • 55
imix
  • 1,231
  • 11
  • 13
8

What do I do in such a case?

A common remedy is to put the one which needs the least visibility behind a "compilation firewall". That is, to create your own abstraction/interface which provides the functionality you need, and then to limit the visibility of the included file to the *.cpp by including it in that *.cpp only. Of course, that *.cpp file would also not be permitted to include the header which has the other definition of the typedef.

Then the declarations won't cause conflict because they will never be visible to the same translation unit.

In your example, you'd likely create a wrapper over the dlinfo() functionalities you need. To illustrate:

DLInfo.hpp

namespace MON {
class DLInfo {
 public:
 /* ...declare the necessary public/client functionality here... */
 int foo();
 ...
};
}

DLInfo.cpp

#include "DLInfo.hpp"

// include the headers for dlinfo() here.
// these includes should not be in your project's headers
#include <link.h>
#include <dlfcn.h>

// and define your MON::DLInfo implementation here, with full
// ability to use dlinfo():

int MON::DLInfo::foo() {
 ...
}

...
Chen Li
  • 4,824
  • 3
  • 28
  • 55
justin
  • 104,054
  • 14
  • 179
  • 226
7

Here's a little work around I figured out: If you define it as something else first, then you can typedef it later. See here in the example (I'm on OS X using g++):

#import <iostream>
using namespace std;

typedef unsigned int uint32;

int main() {
  cout << sizeof(uint32) << endl;
}

The output of this program is

4

Now consider this modified program:

#import <iostream>
using namespace std;

typedef unsigned int uint32;
#define uint32 blah
typedef unsigned long uint32;

int main() {
  cout << sizeof(uint32) << endl;
}

The output of this program is

8

So to answer your question, you would add a line to your code:

#define Elf64_Half Elf64_Half_custom

For clarity, this works because you are basically renaming them all, but doing so with a single command instead of having to change all of your own names.

Rahul Manne
  • 1,229
  • 10
  • 20
  • Doen't work. I get an error saying "Elf64_Half_custom doesn't name a type". And I think that's because #defines being preprocessor directive, is processed before typedefs are processed.. – voidMainReturn Dec 12 '14 at 19:23
  • 1
    in your case it worked because uint32 is actually a type..Try doing this and it fails : typedef unsigned int xxxxx; #define xxxxx blah typedef unsigned long xxxxx; – voidMainReturn Dec 12 '14 at 19:30
  • I'm not really sure why that's not working for you, here's my update: https://dl.dropboxusercontent.com/u/9074436/Screen%20Shot%202014-12-12%20at%203.12.15%20PM.png As a side-note, uint32 is not a type either. uint32_t is a type. And if it was a preprocessor directive, then my current program should not compile because it would still be two typedefs. But it is not. Rather, it is done sequentially during the compile. Where did you add the line? You should add it right before your typedef. – Rahul Manne Dec 12 '14 at 20:13
  • I figured out why this is not working...it's because when I do a #define Elf64_Half Elf64_Half_custom then it replaces statements like this : Elf64_Half Type; Which was a valid code but now it replaces it with Elf64_Half_Custom Type; and then compiler complains that Elf64_Half_custom is not a type..So this solution is as good as renaming which I have mentioned in the question. – voidMainReturn Dec 13 '14 at 00:34