在C++中如何取消typedef定义?

20
我正在处理一个庞大的项目,其中有一个文件A.h,其代码中有一行。
typedef unsigned __int16   Elf64_Half;

由于我正在Linux上构建并使用dlinfo函数,因此必须在我的项目中包含link.h文件。这就创建了一个冲突,因为我有两个具有相同名称Elf64_Half的typedef(Linux的link.h包含elftypes.h,它也具有:typedef unsigned short Elf64_Half;)。

在这种情况下,我该怎么办?我唯一的选择是更改a.h中的typedef吗?请记住,这并不容易,因为该项目非常庞大,我需要在多个地方进行更改。

是否有一种方法可以取消typedef或类似的操作?


9
我所知道的唯一方法是将它们放入不同的命名空间中。 - Mark Ransom
5
我正在等待看谁会首先建议一个涉及宏的解决方案... - Mysticial
1
把 A.h 中的 typedef 替换为 #include <link.h>,这样不是更简单吗?你只需要修改一个文件,所有内容都会自动变成一致的类型。 - Rob Kennedy
可能是重复的问题,参考 如何(临时)取消类型定义? - Chen Li
https://bytes.com/topic/c/answers/215239-how-remove-type-defined-typedef-thx - Chen Li
显示剩余4条评论
3个回答

27

为了澄清,Rahul Manne提供了一个简单的解决方案。执行以下操作:

#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.
 *
 */

这将用The_Elf64_Half_I_dont_care替换link.h中的每个Elf64_Half,因此您不会与A.h发生冲突。只要您不想显式使用link.h中的Elf64_Half,那么就没有问题。您只需要记住,在必须在此文件中显式使用link.h中的Elf64_Half时,link.h中的Elf64_Half现在称为The_Elf64_Half_I_dont_care


8
在这种情况下,我该怎么做?
一种常见的解决方法是将需要最少可见性的文件放在“编译防火墙”后面。也就是说,创建自己的抽象/接口,提供所需的功能,然后将包含文件的可见性限制为仅限于*.cpp文件。当然,该*.cpp文件也不允许包含具有其他typedef定义的头文件。
然后,声明不会引起冲突,因为它们永远不会对同一翻译单元可见。
在您的示例中,您可能会创建一个包装器来覆盖所需的dlinfo()功能。举个例子: 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() {
 ...
}

...

7

我想分享一个小技巧:如果您首先将其定义为其他内容,然后稍后可以对其进行 typedef。在这个例子中可以看到(我使用的是OS X和g++):

#import <iostream>
using namespace std;

typedef unsigned int uint32;

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

这个程序的输出结果是:
4

现在考虑这个修改过的程序:
#import <iostream>
using namespace std;

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

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

该程序的输出为:
8

因此,要回答您的问题,您需要在您的代码中添加一行:
#define Elf64_Half Elf64_Half_custom

为了更清晰,这是因为你基本上重命名了所有文件,但是只需使用一个命令即可完成,而不必更改所有自己的名称。

不起作用。我收到一个错误,说“Elf64_Half_custom不是一种类型”。我认为这是因为#define被作为预处理器指令处理,而在typedef处理之前进行处理。 - voidMainReturn
1
在你的情况下,它工作是因为uint32实际上是一种类型。尝试这样做就会失败: typedef unsigned int xxxxx; #define xxxxx blah typedef unsigned long xxxxx; - voidMainReturn
我真不太清楚为什么这个对你不起作用,这是我的更新:https://dl.dropboxusercontent.com/u/9074436/Screen%20Shot%202014-12-12%20at%203.12.15%20PM.png另外,uint32也不是一种类型。uint32_t才是一种类型。如果这是一个预处理器指令,那么我的当前程序就不应该编译,因为它仍然有两个typedefs。但它并没有。相反,在编译期间顺序执行。你在哪里添加了这行代码?应该在你的typedef之前添加它。 - Rahul Manne
我找到了为什么这不起作用的原因...这是因为当我执行 #define Elf64_Half Elf64_Half_custom 时,它会替换像这样的语句:Elf64_Half Type; 这是有效的代码,但现在它将其替换为 Elf64_Half_Custom Type; 然后编译器抱怨 Elf64_Half_custom 不是一种类型。所以这个解决方案就像我在问题中提到的重命名一样好。 - voidMainReturn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接