2014-10-18 177 views
0

我有一個類模板name來檢測類型名稱。它適用於簡單類型,如int,float。但是,對於某些模板類型(如std:pair),編譯器(VS2013)會在我嘗試定義其靜態成員變量時在行上報告錯誤。帶模板的類模板專業化

#include <cassert> 
#include <memory> 

using namespace std; 

template<class T> struct name{ static const char* value; }; 

template<class T> const char* name<T>::value = "unknown"; 
template<> const char* name<int>::value = "int"; 
template<> const char* name<float>::value = "float"; 
template<class T1, class T2> const char* name<pair<T1, T2> >::value = "pair"; //compilation error 

void main() 
{ 
    assert(name<int>::value == "int"); 
    assert(name<float>::value == "float"); 
    assert(name<double>::value == "unknown"); 
    assert((name<pair<int, char> >::value) == "pair"); 
} 

如果我用以下四行替換該行,該程序按預期工作。

template<class T1, class T2> struct name < pair<T1, T2> > { 
    static const char* value; 
}; 
template<class T1, class T2> const char* name<pair<T1, T2> >::value = "pair"; 

但這種方式看起來很醜,由於一些重複的代碼。有什麼方法可以四處走動嗎?

更新已修復了一些明顯符合標準的問題。

+0

很難甚至開始枚舉所有的都錯了,此代碼的東西,而是專心於手頭的問題:你只能專注靜態數據成員明確,但不能部分。 – 2014-10-18 14:24:52

+0

對不起,你正在使用這樣一個可怕的編譯器,你不知怎麼就想到你的代碼是遠程正確的。幾乎每一行都有嚴重的錯誤,我責怪編譯器欺騙你認爲這是好的。 – 2014-10-18 14:25:45

+0

你應該使'static const char * const值'類型 – 2014-10-18 14:27:01

回答

2

首先:任何明確的專業化必須由template<>引入。儘量保持標準兼容。

但這種方式看起來很醜,由於一些重複的代碼。 有什麼方法可以走動嗎?

號在一個構件定義的參數和參數列表是不明確的專業化必須在主模板或它的部分特中的一個的列表匹配,並且它對應於模板的成員,其列出了它火柴。 [temp.class.spec.mfunc]:

類模板局部 專業化應匹配類 模板部分特例的模板參數列表中的一員的模板參數列表。類模板部分專業化的 成員的模板參數列表應與類模板部分專業化的 模板參數列表匹配。

所以你必須部分專門化模板。你可以使用一個宏,雖然:

#define REM_PAR(...) __VA_ARGS__ 
#define PART_SPEC(string, params, ...) \ 
    template<REM_PAR params> struct name <__VA_ARGS__ > \ 
    { static const char* value; }; \ 
    \ 
    template<REM_PAR params> const char* name<__VA_ARGS__>::value = string; 

PART_SPEC("pair", (class T, class U), pair<T,U>) 
2

首先,以供參考,這是你的僞代碼看起來是在C++:

#include <cassert> // for assert 
#include <cstring> // for std::strcmp 
#include <utility> // for std::pair 

template <class T> struct name 
{ static const char * const value; }; 

template <class T> 
const char * const name<T>::value = "unknown"; 

template <>   // "template <>" for specialization 
const char * const name<int>::value = "int"; 

template <>   // "template <>" for specialization 
const char * const name<float>::value = "float"; 

// template <class T1, class T2>        // Error here (partial 
// const char * const name<std::pair<T1, T2>>::value = "pair"; // spec'n not allowed) 

int main() // return type int 
{ 
    assert(std::strcmp(name<int>::value, "int") == 0);  // strcmp! 
    assert(std::strcmp(name<float>::value,"float") == 0); 
    assert(std::strcmp(name<double>::value, "unknown") == 0); 
    assert(std::strcmp(name<std::pair<int, char>>::value,"pair") == 0); 
} 

現在,這裏有一個方法可以使偏特工作:專門研究整個模板。

template <class T1, class T2> struct name<std::pair<T1, T2>> 
{ static const char * const value; }; 

template <class T1, class T2> 
const char * const name<std::pair<T1, T2>>::value = "pair";