如果我想仅在未定义值时定义值,我会执行以下操作:
#ifndef THING
#define THING OTHER_THING
#endif
如果THING
是typedef
'标识符,并且未定义,该怎么办?我想做这样的事情:
#ifntypedef thing_type
typedef uint32_t thing_type
#endif
问题出现了,因为我想检查外部库是否已经定义了boolean
类型,但我愿意听一个更通用的解决方案。
答案 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 可以使用。