1

看代码:

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
}

正如在不能重载函数中讨论的那样,第一个特化是合法的,甚至在 MSVC 中也有效。而第二个专业化 forenum甚至不想编译,说“错误 C2988:无法识别的模板声明/定义”。

在我看来,C++ 正在为方法制造相对不合逻辑的例外。枚举只是一个例子。同样的事情可以应用于成员类、类型定义等。

我会很高兴有人对此发表评论。

4

1 回答 1

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提交了一个错误。有人可以测试最近的 Clang 吗?


在 C++03 中,只有类和函数可以显式特化。从标准,C++03 14.7.3/1:

以下任何一项的明确专业化:

  • 功能模板
  • 类模板
  • 类模板的成员函数
  • 类模板的静态数据成员
  • 类模板的成员类
  • 类或类模板的成员类模板
  • 类或类模板的成员函数模板

可以通过引入的声明来声明template<>

成员枚举不是这种情况。(一般来说,一个enum类型总是在第一次声明时只定义一次。)

要获得模板化的enumor typedef,您可以将其包装在类模板中。在您的情况下,它将是Foo. 这样的构造称为元函数。

C++11 也有别名模板,类似于模板化的 typedef,但它们不能显式特化。


只允许类和函数被特化,然后允许这样的模板封装其他的东西,比如enumand typedef,对我来说似乎比允许直接特化enum. 但是,也许语言正朝着您喜欢的方向发展。

于 2012-06-30T05:15:52.537 回答