我有一个类模板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 :(得分: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";