查看代码:
template <class x> struct Foo
{
int getX(x *p) { return(0); }
enum E12 { a };
};
template <> int Foo<int>::getX(int*)
{
return(-15);
}
template <> enum Foo<int>::E12
{
a, b, c
}
正如Cannot overload function中所讨论的那样,第一个专业化是合法的,甚至可以在MSVC中使用。虽然enum
的第二个专门化甚至不想编译,但说“错误C2988:无法识别的模板声明/定义”。
在我看来,C ++正在为方法制造相对非逻辑的异常。 Enum只是一个例子。同样的事情可以应用于成员类,typedef等。
我很高兴有人会对此发表评论。
答案 0 :(得分:1)
这是C ++ 11的一个非常模糊的新功能。向Microsoft提交一份错误报告,虽然它不太可能优先,因为几乎没有人知道这是允许的。正确的语法是
template <class x> struct Foo
{
int getX(x *p) { return(0); }
enum E12 { a };
};
template <> int Foo<int>::getX(int*)
{
return(-15);
}
template <> enum Foo<int>::E12
{
a, b, c
};
我和GCC一起filed a bug。有人可以测试最近的Clang吗?
在C ++ 03中,只有类和函数可以显式专用。从标准,C ++ 03 14.7.3 / 1:
以下任何一项的明确专业化:
- 功能模板
- 课程模板
- 类模板的成员函数
- 类模板的静态数据成员
- 类模板的成员类
- 类或类模板的成员类模板
- 类或类模板的成员函数模板
可以由
引入的声明声明template<>
成员枚举不是这种情况。 (一般来说,enum
类型在第一次声明时始终只定义一次。)
要获取模板enum
或typedef
,您可以将其包装在类模板中。在您的情况下,它将是Foo
的成员类模板。这种结构称为元函数。
C ++ 11也有别名模板,它们类似于模板化的typedef,但它们不能明确专门化。
仅允许类和函数专用的策略,然后允许这些模板封装其他内容,如enum
和typedef
,似乎比允许直接专门化{{1}更加一致}}。但是,也许语言正朝着你的首选方向发展。