2011-04-19 85 views
16

這是可以使用模板嗎?編譯時聲明字符串相等

有兩個字符串常量。它們來自不同模塊中的定義。它們必須是平等的,否則如果不相等,我會提出編譯時錯誤。我可以使用模板做到這一點嗎?

#define MY_STRING "foo" 
CompileAssertIfStringsNotEqual(MY_STRING, HIS_STRING); 

P.S.假設「abc」[0]是不變的表達式,我被迷惑了。不是這樣。語言中的奇怪的遺漏。這將是possibe「abc」[0]是常量表達式。

回答

18

這隻適用於C++ 0x。沒有C++ 03的機會。

編輯:C++ 0x的Constexpr函數。下面的內容適用於GCC4.6,但是標準並沒有明確允許它,並且正在考慮一個小的措辭調整,以使規範允許它。

constexpr bool isequal(char const *one, char const *two) { 
    return (*one && *two) ? (*one == *two && isequal(one + 1, two + 1)) 
    : (!*one && !*two); 
} 

static_assert(isequal("foo", "foo"), "this should never fail"); 
static_assert(!isequal("foo", "bar"), "this should never fail"); 

在整個遞歸過程中,編譯器都需要跟蹤字符串字符的引用。只是從字符中讀取的最後文字是不被明確允許的(如果你眯起眼睛,你可以把它理解爲允許,IMO)。如果你的編譯器不希望接受上述簡單的版本,你可以讓你的宏聲明數組,然後比較這些

#define CONCAT1(A, B) A ## B 
#define CONCAT(A, B) CONCAT1(A, B) 

#define CHECK_EQUAL(A, B) \ 
    constexpr char CONCAT(x1, __LINE__)[] = A, \ 
       CONCAT(x2, __LINE__)[] = B; \ 
    static_assert(isequal(CONCAT(x1, __LINE__), CONCAT(x2, __LINE__)), \ 
    "'" A "' and '" B "' are not equal!") 

這絕對罰款。

CHECK_EQUAL("foo", "foo"); /* will pass */ 
CHECK_EQUAL("foo", "bar"); /* will fail */ 

請注意,CHECK_EQUAL可用於函數內部。 FCD確實進行了更改,以允許constexpr函數在其調用替換中從自動數組讀取。見DR1197

+0

你可以顯示C++ 0x的方式或提供一個鏈接? – pmr 2011-04-19 20:22:38

+0

+1但是,我一直懷疑這可能是使用元編程在C++中可能的。但我從來沒有能夠完成它。隨着C++ 0x的發展,我放棄了嘗試。 – 2011-04-19 20:50:01

+0

這意味着可以用C++模板語言編寫一個編譯器。哇噢! – Omnifarious 2011-04-19 21:00:41

-3

不可以。甚至不用boost::mplboost預處理器庫。即使您要規定編譯器可以在編譯時將所有重複的字符串引用合併爲相同的指針值,但指針值在鏈接時纔會存在。你想要執行的事情發生在預處理器時間,然後在編譯時斷言。

+0

嗯我被告知模板比預處理器更強大....) – Andrei 2011-04-19 19:58:33

+0

然而,模板不接受「引用字符串」專業化。 – 2011-04-19 20:54:10

+0

它們也不接受'double'或'float'或任何其他非整數值來專門化模板'。 – 2011-04-19 20:55:09