【问题标题】:Explicit specialization of non-class, non-function members of a class template类模板的非类、非函数成员的显式特化
【发布时间】:2012-06-30 04:58:29
【问题描述】:

看代码:

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++ 正在为方法制造相对不合逻辑的例外。枚举只是一个例子。同样的事情可以应用于成员类、typedef等。

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

【问题讨论】:

  • @MooingDuck,感谢您指出错误的语法。固定。
  • Ups,上面的评论应该是@Potatoswatter。

标签: c++


【解决方案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
};

我有filed a bug 与 GCC。有人可以测试最近的 Clang 吗?


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

以下任何一项的明确特化:

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

可以通过template&lt;&gt;引入的声明来声明

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

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

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


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

【讨论】:

  • @MooingDuck 他们悄悄地在 14.7.3/1 中添加了一个要点,使其合法化。我很想看看提案文件,因为从表面上看,该功能很难证明是合理的。
  • 问题不是 C++11。再次修复语法后,我尝试使用 MSVC 2008。现在在实例化尝试时说“错误 C3113:‘枚举’不能是模板”。
  • @KirillKobelev 抱歉,这是一个令人困惑的巧合。在我仔细查看原始答案之前,我对这个 C++11 功能一无所知。我将重新发布它作为当前答案的补充。
  • @Potatoswatter,没问题。感谢您的参与。
  • > 枚举类型总是在第一次声明时只定义一次。哈哈。枚举完全允许前向声明。
猜你喜欢
  • 1970-01-01
  • 2013-12-20
  • 1970-01-01
  • 2011-07-27
  • 1970-01-01
  • 2023-01-10
  • 2015-03-04
相关资源
最近更新 更多