2011-05-10 61 views
10

我的猜測是這個問題的答案是否定的,但如果有一種方法,它會很棒。爲了澄清,假設我有以下宏:有沒有辦法在variadic宏參數上使用C++預處理器字符串化?

#define MY_VARIADIC_MACRO(X...) // Does some stuff here in the macro definition 

我想要做的就是以某種方式將它傳遞給一個可變參數函數之前,X的所有變量進行字符串化;這裏的關鍵字是之前。我意識到無法從宏定義中真正訪問各個參數,但是有沒有辦法將所有參數串聯起來,可能類似於以下內容?

#define MY_VARIADIC_MACRO(X...) some_variadic_function("some string", #X) 

回答

8

好的,我不是故意在這裏回答我自己的問題,但是我想出了一個體面的解決方案,它有點像Mark Wilkins答案和我在問題中給出的例子。

可以將整個集合可變集合串聯起來,然後在字符串中包含分隔逗號。這裏有一個簡單的例子:

#define MY_VARIADIC_MACRO(X...) printf(#X) 

使用上面的宏向您顯示的傳遞給宏參數整組被字符串化。

然後你可以再定義一個函數使用可變參數的宏來標記使用分隔逗號,從而獲得組記號化字符串的這些論點:

#define MY_VARIADIC_MACRO(X...) tokenize_my_arguments(#X) 

再就是實際上是不再具有的相關性variadic宏調用一個可變參數函數,我可以很好地遍歷我的常量C字符串數組,而不是遍歷va_arg。

*新的東西從編輯遵循*

每Tim的評論,這裏的解決方案的詳細信息。請原諒任何錯誤,因爲它是在匆忙中完成的,我不得不從我的工作中移植。此外,它並不意味着是複製/粘貼解決方案,因爲它只輸出參數的字符串化以演示POC,但應足以證明功能。

儘管此解決方案需要一些運行時間計算,但可變宏常常調用可變參數函數並需要迭代va_args,因此迭代發生在找到令牌,儘管可能會犧牲一些性能。然而,可維護性,靈活性和易於實施的,這似乎是目前最佳的選擇:

#define VARIADIC_STRINGIFY(_ARGUMENTS_TO_STRINGIFY...) Variadic_Stringification_Without_Variadic_Function(#_ARGUMENTS_TO_STRINGIFY) 

void Variadic_Stringification_Without_Variadic_Function (const char* _stringified_arguments) 
{ 
    strcpy(converted_arguments, _stringified_arguments); 

    for(char* token = strtok(converted_arguments, ","); token != 0x0; token = strtok(0x0, ",")) 
     std::cout << token << std::endl; 
} 
+0

此外,這樣做的另一個很好的功能是,我可以很容易地找到參數的數量,而不必具有某種類型的通過宏傳遞到確定在列表中的參數結束的信息。 – Hazok 2011-05-11 00:04:48

+0

有趣,但你紀念這個作爲一個解決方案之前,張貼解決了這個實際代碼。我相信它會派上用場。 – Tim 2011-05-11 00:49:04

+0

@Tim將會這樣做,我已經測試了一個簡單的案例,並且將使它成爲一個更好的例子......有一些截止日期,並會在明天(2011年5月11日)或第二天發佈。 – Hazok 2011-05-11 01:14:24

2

這可能不是非常接近你想要什麼,但像下面這樣可能讓你有:

#define MY_VARIADIC_MACRO(X) printf("%s\n", #X) 

然後使用它像下面這樣。將參數包含在parens中,以便它作爲宏的一個參數出現。

MY_VARIADIC_MACRO((var1,var2,「string」));

然後,您可以讓宏調用某個函數去除外部零部件或者可能解析給定的字符串。

+0

這是幾乎沒有,但這個想法是緩解ŧ他需要附上括號......快速返回加評論,需要記住shift-return。 我認爲上述方法非常接近我正在努力的解決方案。我會投了這個答案,因爲它幾乎是有,但不能將其標記爲主體的答案,因爲它並不能完全滿足要求。 – Hazok 2011-05-10 23:53:05

+0

@Zach:我猜到了。我很想看看如何做到這一點。我的理解是,這是不可能的,但我希望有不同的表現。 – 2011-05-10 23:54:11

+0

我張貼以上,我要去一起去,很火上澆油關於它的答案,解決了我面臨的問題很多。 – Hazok 2011-05-11 00:05:40

18

您可以使用各種遞歸宏技術做的事情與複雜的宏。例如,你可以定義一個NUM_ARGS宏統計參數個數的可變參數宏:

#define _NUM_ARGS(X100, X99, X98, X97, X96, X95, X94, X93, X92, X91, X90, X89, X88, X87, X86, X85, X84, X83, X82, X81, X80, X79, X78, X77, X76, X75, X74, X73, X72, X71, X70, X69, X68, X67, X66, X65, X64, X63, X62, X61, X60, X59, X58, X57, X56, X55, X54, X53, X52, X51, X50, X49, X48, X47, X46, X45, X44, X43, X42, X41, X40, X39, X38, X37, X36, X35, X34, X33, X32, X31, X30, X29, X28, X27, X26, X25, X24, X23, X22, X21, X20, X19, X18, X17, X16, X15, X14, X13, X12, X11, X10, X9, X8, X7, X6, X5, X4, X3, X2, X1, N, ...) N 

#define NUM_ARGS(...) _NUM_ARGS(__VA_ARGS__, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) 

然後,你可以寫一個FOREACH宏,展開另一宏列表中的每個元素:

#define EXPAND(X)  X 
#define FIRSTARG(X, ...) (X) 
#define RESTARGS(X, ...) (__VA_ARGS__) 
#define FOREACH(MACRO, LIST) FOREACH_(NUM_ARGS LIST, MACRO, LIST) 
#define FOREACH_(N, M, LIST) FOREACH__(N, M, LIST) 
#define FOREACH__(N, M, LIST) FOREACH_##N(M, LIST) 
#define FOREACH_1(M, LIST) M LIST 
#define FOREACH_2(M, LIST) EXPAND(M FIRSTARG LIST) FOREACH_1(M, RESTARGS LIST) 
#define FOREACH_3(M, LIST) EXPAND(M FIRSTARG LIST) FOREACH_2(M, RESTARGS LIST) 
     : 

這將反過來讓你定義你的宏stringifies每個參數:

#define STRINGIFY(X) #X 
#define MY_VARIADIC_MACRO(...) FOREACH(STRINGIFY, (__VA_ARGS__)) 
+0

我知道這些遞歸技術,但是從上面可以看出,它們很乏味,而且它們還有一個不幸的限制,那就是你只能在編譯時考慮到參數的數量。我也有解決方案,是不是乏味的實施和不限於預定最大值是易於維護的細節很快更新我的答案。這可能是所有情況下的最佳解決方案,但對於我所需要的,這是比上述更好的答案。感謝您的輸入! – Hazok 2011-05-11 05:03:43

相關問題