[英]Can `#ifdef` be used inside a macro?
我只找到了这个相关的问题,这不是我想要的。
我曾经在#ifdef
语句中定义了宏:
#ifdef DEBUG
# define PRINT_IF_DEBUGGING(format) printf(format);
# define PRINTF_IF_DEBUGGING(format, ...) printf(format, __VA_ARGS__);
#else
# define PRINT_IF_DEBUGGING(...)
# define PRINTF_IF_DEBUGGING(...)
#endif
现在,我想做相反的事情,在宏中包含#ifdef
语句。 像这样的东西:
#define PRINT_IF_DEBUGGING(format, ...) \
#if defined(DEBUG) print(format); #endif
#define PRINTF_IF_DEBUGGING(format, ...) \
#if defined(DEBUG) printf(format, __VA_ARGS__); #endif
但是,我在#ifdef defined
中使用__VA_ARGS__
时遇到问题。
error: '#' is not followed by a macro parameter
#define PRINT_IF_DEBUGGING(format, ...)
error: '#' is not followed by a macro parameter
#define PRINTF_IF_DEBUGGING(format, ...)
warning: __VA_ARGS__ can only appear in the expansion of a C++11 variadic macro
#if defined(DEBUG) printf(format, __VA_ARGS__); #endif
这可能吗?
这确实应该是一个评论,但我无法以一种允许我说出我想说的话的方式来格式化它,所以我正在回答。
无论如何,只要改变这个:
#if defined(DEBUG) print(format); #endif
对此:
#if defined(DEBUG)
print(format);
#endif
等等,这应该可以解决它。
您不能在#define
中使用#ifdef
,所以不,这是不可能的。 您显示的第一个代码是正确的解决方案。
在#define
中使用#ifdef
是不可能的。 但是仍有一些方法可以检测宏定义中是否定义了宏。
#define CAT(a, b) CAT_IMPL(a, b)
#define CAT_IMPL(a, b) a ## b
#define IS_DEBUG_DEFINED() CHECK((CAT(CHECK_,DEBUG), 0, 1))
#define CHECK_DEBUG ~,~
#define CHECK(tup) CHECK_IMPL tup
#define CHECK_IMPL(a, b, c, ...) c
#define IIF(condition, true_value, false_value) CAT(IIF_,condition)(true_value, false_value)
#define IIF_0(true_value, false_value) false_value
#define IIF_1(true_value, false_value) true_value
#define PRINT_IF_DEBUGGING(format) IIF(IS_DEBUG_DEFINED(), PRINT_DEBUGGING, PRINT_NOT_DEBUGGING)(format)
// this will be used if DEBUG is defined:
#define PRINT_DEBUGGING(format) debugPrint(format)
// this will be used if DEBUG is NOT defined:
#define PRINT_NOT_DEBUGGING(format) print(format)
PRINT_IF_DEBUGGING(foo)
将扩展为:
DEBUG
: debugPrint(foo)
DEBUG
: print(foo)
例子:
PRINT_IF_DEBUGGING("test1");
#define DEBUG
PRINT_IF_DEBUGGING("test2");
#undef DEBUG
PRINT_IF_DEBUGGING("test3");
会导致:
print("test1");
debugPrint("test2");
print("test3");
IS_DEBUG_DEFINED()
是如何工作的这背后的基本技巧是使用连接- 如果定义了宏,它将被扩展,否则预处理器不会修改标记:
#define CAT(a, b) CAT_IMPL(a, b)
#define CAT_IMPL(a, b) a ## b
// DEBUG NOT DEFINED:
CAT(CHECK_,DEBUG) // will expand to CHECK_DEBUG
// DEBUG DEFINED:
#define DEBUG 1234
CAT(CHECK_,DEBUG) // will expand to CHECK_1234
CAT
将扩展为CHECK_DEBUG
,因为未定义DEBUG
。CAT
将扩展为CHECK_1234
,因为DEBUG
在与CHECK_
连接之前已定义并扩展为1234
。 通过定义一个名为CHECK_DEBUG
的宏,如果未定义该宏,我们可以更改结果,例如:
#define TEST CAT(CHECK_,DEBUG), 0, 1
#define CHECK_DEBUG ~,~
DEBUG
,则结果将为~, ~, 0, 1
( 4 个逗号分隔的标记)DEBUG
,则结果将为CHECK_, 0, 1
( 3 个逗号分隔的标记)注意我们在第一种情况下是如何得到 4 个令牌的,但在第二种情况下只有 3 个令牌。
现在我们需要做的就是从该序列中获取第三个标记(如果未定义DEBUG
,则为0
,否则为1
),例如使用始终返回第三个参数的简单宏:
#define CHECK(a, b, c, ...) c
综上所述,这就是完整的IS_DEBUG_DEFINED()
的样子:
#define CAT(a, b) CAT_IMPL(a, b)
#define CAT_IMPL(a, b) a ## b
#define IS_DEBUG_DEFINED() CHECK((CAT(CHECK_,DEBUG), 0, 1))
#define CHECK_DEBUG ~,~
#define CHECK(tup) CHECK_IMPL tup
#define CHECK_IMPL(a, b, c, ...) c
如果未定义DEBUG
, IS_DEBUG_DEFINED()
将扩展为0
,如果是,则扩展为1
,例如:
IS_DEBUG_DEFINED() // -> 0
#define DEBUG
IS_DEBUG_DEFINED() // -> 1
#undef DEBUG
IS_DEBUG_DEFINED() // -> 0
使用IS_DEBUG_DEFINED()
,您可以使用标准预处理器IIF
来更改宏的行为,具体取决于是否定义了DEBUG
。
示例:神螺栓
#define IIF(condition, true_value, false_value) CAT(IIF_,condition)(true_value, false_value)
#define IIF_0(true_value, false_value) false_value
#define IIF_1(true_value, false_value) true_value
#define PRINT_IF_DEBUGGING(format) IIF(IS_DEBUG_DEFINED(), PRINT_DEBUGGING, PRINT_NOT_DEBUGGING)(format)
// this will be used if DEBUG is defined:
#define PRINT_DEBUGGING(format) debugPrint(format)
// this will be used if DEBUG is NOT defined:
#define PRINT_NOT_DEBUGGING(format) print(format)
PRINT_IF_DEBUGGING("test"); // -> print("test");
#define DEBUG
PRINT_IF_DEBUGGING("test"); // -> debugPrint("test");
#undef DEBUG
PRINT_IF_DEBUGGING("test"); // -> print("test");
对此的一个小警告是,如果定义了DEBUG
,它必须扩展为有效的预处理标记(因此它必须只包含字母、数字和下划线)——否则连接将导致错误。
所以这行不通:
#define DEBUG ()
#define DEBUG +
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.