在C / C ++中,是否有类似于#ifndef的typedefs指令?
如果我想定义一个值,只要它没有被定义,我做这样的事情:
#ifndef THING #define THING OTHER_THING #endif
如果THING
是一个typedef
的标识符,而没有定义呢? 我想要做这样的事情:
#ifntypedef thing_type typedef uint32_t thing_type #endif
出现这个问题的原因是我想检查一下外部库是否已经定义了boolean
types,但是我打算听一个更一般的解决scheme。
不,在预处理阶段,C ++没有这样的设施。 在最大可以做的是
#ifndef thing_type #define thing_type uint32_t #endif
虽然这不是一个好的编码习惯,我不build议这样做。
语言中没有这样的东西,也没有必要。 在一个项目中,不应该有相同的typedef别名引用不同的types,因为这是对ODR的违反,如果你要创build同一个types的同一个别名,那么就这样做。 该语言允许您根据需要多次执行相同的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来确定使用哪一种function来实现不同types的function,那么你应该看看模板而不是typedef。
C ++没有提供任何代码来testingtypedef
存在机制,最好的可能是这样的:
#ifndef THING_TYPE_DEFINED #define THING_TYPE_DEFINED typedef uint32_t thing_type #endif
编辑:
至于@David,在他的评论中是正确的,这个答案如何? 部分,但重要的是错过了为什么? 这可以按照上面的方式来完成,如果你想要做所有的事情,但重要的是,你可能不需要做任何事情,@大卫的回答和评论解释了细节,我认为这正确地回答了这个问题。
预处理指令(如#define
)是粗略的文本replace工具,对编程语言一无所知,所以它们不能在任何语言级定义上运行。
有两种方法可以确保只定义一次types:
- 构build代码,使每个定义都有其位置,而且不需要多个定义
-
#ifndef
在types旁边定义一个预处理macros,在定义types之前使用#ifndef
检查macros定义。
第一个选项通常会导致更易维护的代码。 第二个可能会导致微妙的错误,如果你不小心结束在一个程序中的types的不同定义。
问题实际上是真正的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中的“扩展”。 这是一个编译器语句,而不是预处理器语句,所以它不会“感觉”定义的macros,它只会检测函数体外的typedef。 那么“完整types”就意味着它会对完整的定义做出反应,忽略像“class SomeClass”这样的语句。 使用它自担风险。
编辑:显然它也支持MacOS现在和英特尔comiler与-fms-dialect标志(AIX \ Linux的?)
这可能不会直接回答这个问题,但可以作为解决您的问题的可能scheme。
为什么不尝试这样的事情?
#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;
然后,如果你想定制types,你可以定义MY_COOL_TYPE在这个上面(比如在头文件头部的“configure”头文件中),或者在编译时把它作为命令行parameter passing(就我而言知道你可以做GCC和LLVM,也可能是其他人)。
正如其他人已经说过,没有这样的事情,但如果你尝试创build一个别名到不同的types,你会得到一个编译错误:
typedef int myInt; typedef int myInt; // ok, same alias typedef float myInt; // error
然而,有一个叫做ctag的东西来findtypedef的定义。
不,没有什么是你想要的。 我已经有了与库相同的问题,包括他们自己的typedefs
,如bool
。 当他们只是不关心你用什么bool
或者其他库可能做同样的事情时,它会成为一个问题!
所以这就是我所做的。 我编辑这样做的库的头文件,findtypedef bool
并添加一些代码:
#ifdef USE_LIBNAME_BOOL typedef unsigned char bool; // This is the lib's bool implementation #else #include <stdbool.h> #endif
请注意,如果我不想使用libs自己的bool typdef
,那么我包含了bool typdef
。 这意味着您需要C99支持或更高版本。
如前所述,这不包含在C ++标准中,但是您可以使用autotools来获得相同的function。
您可以使用ac_cxx_bool
macros来确保bool被定义(或针对不同数据types的不同例程)。
它不是透明的,但你可以尝试编译它一次没有typedef(只使用别名),看看它是否编译或不。
我最终使用的解决scheme是包含stdbool.h。 我知道这并不能解决如何检查typedef是否已经定义的问题,但它确实让我确保定义了布尔types。
无需使用macros,您可以通过检查编译是否失败来确定是否定义了命名空间范围typedef。 如果它是嵌套在一个结构中的typedef,可以使用SFINAE。
对于命名空间范围typedef,您可以同时执行这两个操作:
typedef int some_type #define some_type some_type
接着:
#ifdef some_type some_type some_var; #endif
那就是some_type
既是预处理器macros也是typedef。