2013-07-08 219 views
4

有什麼方法可以在C++宏中評估decltype?我的主要動機是創建一個能夠確定this類型並將其轉換爲字符串的宏。有沒有辦法將decltype轉換爲宏中的字符串?

如果無法使用decltype還有什麼其他方式在類聲明中使用的宏可以將類的類型作爲字符串?

回答

4

有沒有什麼辦法可以在C++宏中評估decltype

沒有,因爲宏decltype前嚴格評估

據我所知,沒有辦法讓這個班的名字成爲一個宏,完全停下來。任何這樣的方式都必須由編譯器生成的宏支持

但是,您可以使用typeid來獲取損壞的名稱(嚴格來說,是實現定義的表示形式),然後使用特定於編譯器的工具從其中檢索取消加載的名稱。

例如,GCC提供demangling library來做到這一點。

這裏有一個小例子online demo

#define THIS_CLASS_NAME() demangled(typeid(*this).name()) 

std::string demangled(char const* tname) { 
    std::unique_ptr<char, void(*)(void*)> 
     name{abi::__cxa_demangle(tname, 0, 0, nullptr), std::free}; 
    return {name.get()}; 
} 

用法:

namespace foo { 
    template <typename T> 
    struct bar { 
     bar() { std::cout << THIS_CLASS_NAME() << '\n'; } 
    }; 
} 

int main() { 
    foo::bar<int> b; 
} 

產量:

foo::bar<int> 
4
任何代碼被編譯之前

宏被擴展,所以很遺憾他們不沒有任何類型的概念。

根據您的需要,您也許可以使用traits類。從理論上講,它比RTTI和typeid在效率和便攜性方面要高一些,但它只適用於你明確告訴它的類型。例如:

template <typename T> 
struct Traits 
{ 
    static const char * TYPE_NAME; 
}; 
// Generic definition as a fall-back: 
template <typename T> const char * Traits<T>::TYPE_NAME = "unknown"; 

// Explicit definitions 
template < > const char * Traits<int>::TYPE_NAME = "int"; 
template < > const char * Traits<float>::TYPE_NAME = "float"; 
template < > const char * Traits<ExampleClass>::TYPE_NAME = "ExampleClass"; 

的明確定義是有點麻煩,所以你可以創建一個宏,使他們更容易閱讀:

#define DECLARE_TYPE_TRAIT(name) template < > const char * Traits<name>::TYPE_NAME = #name; 

DECLARE_TYPE_TRAITS(int) 
DECLARE_TYPE_TRAITS(float) 
DECLARE_TYPE_TRAITS(ExampleClass) 

使用在你的代碼的特性類是很容易的。你只需實例化要查找任何類型的特徵模板,並訪問TYPE_NAME成員:

int foo; 
ExampleClass blah; 

cout << Traits<decltype(foo)>::TYPE_NAME << endl; 
cout << Traits<decltype(blah)>::TYPE_NAME << endl; 
+0

謝謝 - 我去,實際上只是使用類型名作爲參數傳遞給宏的解決方案 - 這是有效的與此相同,但更具體到我的具體情況。 –

相關問題