2

我有問題在下面的代碼中說明。C++通用編程微妙

#include <iostream> 

#define X 4 

int main() 
{ 

    std::cout << "should be 4: " << X << std::endl; 
#define Y X + 4 
    std::cout << "should be 8: " << Y << std::endl; 

#undef Y 
#define Y X+0 
#undef X 
#define X Y+1 

    std::cout << "expecting 5: " << X << std::endl; 
} 

錯誤:

test2.cc: In function ‘int main()’: 
test2.cc:17: error: ‘X’ was not declared in this scope 

我試圖效仿的代碼擴展程序/建造水平模式(很像nginx模塊是如何wired up at compile-time)。我需要建立一個可擴展的編譯時結構,這個結構是可擴展的(可插入的),通過將#include添加到我的構建中,導致boost-mpl-vector具有包含我所有插件的唯一名稱。因此,如果X是唯一的最終名稱,則X_0,X_1,X_2是在向量應用mpl-vector push_back時沿途建立的名稱。

知道 boost :: preprocessor的抽象是關鍵,但我不想花時間去研究它,因爲我正在原型化系統的一部分,最終將編譯時模塊化。

所以,以供將來參考,

  1. 爲什麼會出現上述錯誤?
  2. 正確的原始預處理器模式應該是什麼樣子。
  3. 正確的boost-preprocessor-library模式是什麼樣的。
+1

您是否嘗試過通過預處理器運行以查看C++編譯器正在嘗試編譯的內容? – 2011-04-08 09:16:31

回答

5

使用g ++編譯-E給出了這樣的:

int main() 
{ 

    std::cout << "should be 4: " << 4 << std::endl; 

    std::cout << "should be 8: " << 4 + 4 << std::endl; 






    std::cout << "expecting 5: " << X+0 +1 << std::endl; 
} 

所以,你可以看到爲什麼你的錯誤。

4

爲什麼不能用一塊石頭殺死兩隻鳥並使用命名空間。

// a.hpp: 

namespace a { 
    const int module_id = 0; 

    class module_a : extension_module<module_id> { … }; 
} 

#undef last_module 
#define last_module a 

// b.hpp: 

namespace b { 
    const int last = last_module::module_id + 1; 

    class module_b : extension_module<module_id> { … }; 
} 

#undef last_module 
#define last_module b 

這種方式不那麼「聰明」,並留下了一個ID的蹤跡。

但是,每次ODR工作時都需要將模塊包含在相同的順序中。

我不主張殺死任何鳥類。

+0

我一直盯着你最後20分鐘的回答,尤里卡剛剛擊中。通過const整數+名稱空間進行模板專門化確實是我的問題的一個乾淨優雅的解決方案,而且我不需要使用boost MPL或預處理器。它們在C++中的間接層次太多:D。我會接受'GCC -E'的答案,因爲它與問題最相關,但是您的答案具有更高的整體價值,並且是我將採用的解決方案。 – 2011-04-08 09:39:04

+0

@Hassan:大聲笑,我沒有討論'gcc -E'的結果,因爲我認爲你已經做到了,只想要一個解決方案:vP – Potatoswatter 2011-04-08 09:41:57

2

您的代碼示例的問題是,你必須在X和Y宏循環依賴關係:

Y定義爲X + 0和X定義爲Y + 1。所以當宏被擴展時(發生在你使用X的地方),你有一個問題。

地址:

看來,行爲是這樣的:擴展宏X其定義名稱X內時,不預處理器名稱空間中定義,所以你看到X + 0 + 1的X擴展。