[英]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.