2014-10-18 143 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";