类模板专业化与模板

时间:2014-10-18 13:55:06

标签: c++ templates

我有一个类模板name来检测类型名称。它适用于简单类型,例如intfloat。但是,对于某些模板类型,如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";

但由于一些重复的代码,这种方式看起来很难看。有办法四处走走吗?

已更新以修复一些明显符合标准的问题。

2 个答案:

答案 0 :(得分:2)

首先:template<>必须引入任何明确的专业化。尽量保持标准。

  

但由于一些重复的代码,这种方式看起来很难看。有什么办法吗?   到处走走?

没有。不是显式特化的成员定义中的参数和参数列表必须与主模板的列表或其部分特化之一匹配,并且它对应于其匹配列表的模板的成员。 [temp.class.spec.mfunc]:

  

类模板partial的成员的模板参数列表   specialization应匹配类的模板参数列表   模板部分专业化。 a的模板参数列表   类模板部分特化的成员应匹配   模板参数列表的类模板部分特化。

所以你必须部分专门化模板。你可以使用一个宏:

#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>)

答案 1 :(得分: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";