2010-09-03 59 views
0

我想參與一些C -preprocessor-only模板的努力,以便鍵入一些代碼專用。我試圖將它簡化一點,所以這個例子看起來微不足道,毫無意義,但真正的挑戰是獲得「包含」阻止。基於預處理器生成的「東西」可能#if或#ifdef

假設我有一個「模板」文件,它在包含模板之前從定義T_ELEMENT_TYPE的其他源文件中獲得#include。

// Template file... 
#ifndef T_ELEMENT_TYPE 
#error #define T_ELEMENT_TYPE 
#endif 

#define PASTER(x,y) x ## y 
#define EVALUATOR(x,y) PASTER(x,y) 
#define SYMBOLNAME EVALUATOR(SymbolFor, T_ELEMENT_TYPE) 

#ifndef SYMBOLNAMEISDEFINED 
#define SYMBOLNAMEISDEFINED EVALUTOR(DEFINEDFOR, T_ELEMENT_TYPE) 

int SYMBOLNAME(T_ELEMENT_TYPE arg) 
{ 
    // do something with arg 
    return 0; 
} 

#endif // Guard #ifdef 

然後我想包括來自多個實例站點模板,但我只希望每個獨特T_ELEMENT_TYPE一次生成模板函數(以免創建重複的符號。)像,這樣說:

// Template-using file...  
#define T_ELEMENT_TYPE int 
#include "Template.c" 
#undef T_ELEMENT_TYPE 

#define T_ELEMENT_TYPE float 
#include "Template.c" 
#undef T_ELEMENT_TYPE 

#define T_ELEMENT_TYPE int 
#include "Template.c" 
#undef T_ELEMENT_TYPE 

int someOtherFunc() 
{ 
    int foo = 42; 
    foo = SymbolForint(foo); 
    float bar = 42.0; 
    bar = SymbolForfloat(bar); 
    return foo; 
} 

所以我正在尋找我可以在模板代碼中使用的東西。我想象它會是這個樣子(雖然這不工作):模板的

// Template file... 
#ifndef T_ELEMENT_TYPE 
#error #define T_ELEMENT_TYPE 
#endif 

#define PASTER(x,y) x ## y 
#define EVALUATOR(x,y) PASTER(x,y) 
#define SYMBOLNAME EVALUATOR(SymbolFor, T_ELEMENT_TYPE) 

#ifndef SYMBOLNAMEISDEFINED 
#define SYMBOLNAMEISDEFINED EVALUTOR(DEFINEDFOR, T_ELEMENT_TYPE) 

int SYMBOLNAME(T_ELEMENT_TYPE arg) 
{ 
    // do something with arg 
    return 0; 
} 

#endif // Guard #ifdef 

這個特殊的咒語阻止所有多個實例,不只是T_ELEMENT_TYPE的不同值。

是否有一招我可以用來獲得這種效果?或者我剛剛關閉了C-預處理器保留,可以這麼說嗎?

回答

1

我認爲你不在預訂。對#define宏名稱的第一個「參數」不受宏擴展的限制。所以我不認爲預處理器可以根據T_ELEMENT_TYPE的值定義不同的符號。預處理器也不能構建已經看到的類型的「列表」並檢查其中的存在。

所以我認爲,包括後衛將成爲文件外:

#ifndef included_mytemplatefile_h_int 
    #undef T_ELEMENT_TYPE 
    #define T_ELEMENT_TYPE int 
    #include "mytemplatefile.h" 
    #define included_mytemplatefile_h_int 
#endif 

另外,如果您的模板文件頭只聲明函數SymbolFor_int,而不是定義它,然後多次包含不有害。您可以在不依賴於T_ELEMENT_TYPE的當前值(包括PASTER,EVALUATOR,SYMBOLNAME的定義)的文件各部分周圍包含一個正常的守護。你需要一個單獨的模板文件包含了定義,其中程序(而不是每個翻譯單元)都需要有恰好一次:

template_%.c : 
    echo "#define T_ELEMENT_TYPE $*" > [email protected] 
    echo "#include \"mytemplatedefinitions.c\"" >> [email protected] 

然後template_int.o添加到鏈接到您的程序文件的列表。

+0

絕對不是保留。 #ifdef /#ifndef/defined的規則是謹慎措詞的,這樣就不可能對正在測試的標識符執行宏擴展,而這正是您從OP開始工作所需的想法。 – 2010-09-08 09:02:09