在C / C ++中,是否有类似于#ifndef的指令用于typedef?

时间:2011-07-21 07:44:13

标签: c++ c

如果我想仅在未定义值时定义值,我会执行以下操作:

#ifndef THING
#define THING OTHER_THING
#endif

如果THINGtypedef'标识符,并且未定义,该怎么办?我想做这样的事情:

#ifntypedef thing_type
typedef uint32_t thing_type
#endif

问题出现了,因为我想检查外部库是否已经定义了boolean类型,但我愿意听一个更通用的解决方案。

12 个答案:

答案 0 :(得分:26)

语言中没有这样的东西,也不需要。在单个项目中,您不应该使用相同的typedef别名来引用不同类型,因为这违反了ODR,如果您要为同一类型创建相同的别名,那么就这样做。该语言允许您根据需要多次执行相同的typedef,并且通常会捕获该特定ODR(在同一个翻译单元中):

typedef int myint;
typedef int myint;       // OK: myint is still an alias to int
//typedef double myint;  // Error: myint already defined as alias to int

如果您打算通过使用typedef来确定使用哪种功能来实现不同类型的功能,那么您应该查看模板而不是typedef。

答案 1 :(得分:20)

C ++没有为代码提供任何机制来测试typedef的存在,你可以拥有的最好的东西是这样的:

#ifndef THING_TYPE_DEFINED
#define THING_TYPE_DEFINED
typedef uint32_t thing_type 
#endif

修改
作为@David,在他的评论中是正确的,这回答了如何?部分,但重要的是错过了为什么?它可以通过上面的方式完成,如果你想要做到这一切,但重要的是你可能不需要这样做,@ David的回答&评论解释了细节,我认为这正确地回答了问题。

答案 2 :(得分:7)

在预处理阶段,C ++中没有这样的工具。最大可以做的是

#ifndef thing_type
#define thing_type uint32_t 
#endif

虽然这不是一个好的编码实践,但我不建议。

答案 3 :(得分:6)

预处理程序指令(如#define)是粗略的文本替换工具,它们对编程语言一无所知,因此它们不能对任何语言级别的定义起作用。

有两种方法可以确保只定义一次类型:

  • 构造代码,以便每个定义都有其位置,并且不需要多个定义
  • #define预处理器宏以及类型,并在定义类型之前使用#ifndef检查宏定义。

第一个选项通常会导致更易维护的代码。如果你不小心在一个程序中得到不同的类型定义,第二个可能会导致细微的错误。

答案 4 :(得分:2)

这可能无法直接回答问题,但可以作为解决问题的方法。

为什么不尝试这样的事情?

#define DEFAULT_TYPE int // just for argument's sake
#ifndef MY_COOL_TYPE
     #define MY_COOL_TYPE DEFAULT_TYPE
#endif
typedef MY_COOL_TYPE My_Cool_Datatype_t;

然后,如果要自定义类型,可以在此之上的某处定义MY_COOL_TYPE(例如在" configure"包含在此标题顶部的标题)或将其作为命令行传递编译时的参数(据我所知,你可以用GCC和LLVM,也许其他人也这样做)。

答案 5 :(得分:2)

问题实际上是真正的PITA,因为一些API或SDK重新定义了常用的东西。我有问题,地图处理软件(GIS)的头文件重新定义TRUE和FALSE(通常由Windows SDK使用)关键字到整数文字,而不是真假关键字(显然,这可能打破SOMETHING)。是的,着名的笑话" #define true false"是相关的。

define永远不会感觉在C \ C ++代码中声明的typedef或常量,因为预处理器不分析代码,它只扫描#语句。它会在将代码提供给语法分析器之前修改代码。因此,一般来说,这是不可能的。

https://msdn.microsoft.com/en-us/library/5xkf423c.aspx?f=255&MSPPError=-2147217396  到目前为止,这个是不可移植的,尽管已知有在GCC中实现它的请求。我认为,它也算作"扩展"在MSVC。它是一个编译器语句,而不是一个预处理器语句,所以它不会感觉到#34;定义的宏,它只会检测函数体外的typedef。 "完整类型"这意味着它将对完整定义做出反应,忽略类似于"类SomeClass;"等语句。自担风险使用它。

编辑:显然它现在也支持MacOS,英特尔编译器也支持-fms-dialect标志(AIX \ Linux?)

答案 6 :(得分:1)

正如其他人已经说过的那样,没有这样的东西,但是如果你尝试为不同的类型创建一个别名,你会得到一个编译错误:

typedef int myInt;
typedef int myInt;    // ok, same alias
typedef float myInt;  // error

但是,有一个名为ctag的东西,用于查找定义typedef的位置。

答案 7 :(得分:0)

如前所述,这不包含在C ++标准中,但您可以使用autotools来获得相同的功能。

您可以使用ac_cxx_bool宏来确保定义bool(或针对不同数据类型的不同例程)。

答案 8 :(得分:0)

它不透明,但您可以尝试编译一次而不使用typedef(只使用别名),看看它是否编译。

答案 9 :(得分:0)

我最终使用的解决方案包括stdbool.h。我知道这并没有解决如何检查是否已定义typedef的问题,但它确实让我确保定义了布尔类型。

答案 10 :(得分:-1)

无需使用宏,您可以通过检查编译是否失败来确定是否定义了命名空间范围typedef。如果它是嵌套在结构中的typedef,则可以使用SFINAE。

对于命名空间范围typedef,您可以同时执行这两项操作:

typedef int some_type
#define some_type some_type

然后:

#ifdef some_type
    some_type some_var;
#endif

some_type既是预处理器宏又是typedef。

答案 11 :(得分:-1)

没有这种东西。 可以取消激活此 duplicate_typedef 编译器错误。 “typedef 名称已被声明(具有相同的类型)”

另一方面,对于一些标准化的 typedef 定义,通常会定义一个预处理器宏,例如 __bool_true_false_are_defined for bool 可以使用。