显性成员专业化

时间:2010-12-16 18:49:25

标签: c++ templates language-lawyer explicit-specialization

g ++ 3.4.5接受此代码:

template <typename T> struct A
{
    static const char* const str;
};

struct B {};

typedef A<B> C;

template<> const char* const C::str = "B";
// Equivalent to following?
// template<> const char* const A<B>::str = "B";

但我不确定它实际上是合法的C ++ 03。特别是,

  

[14.7p3]在类模板的显式特化声明中,类模板的成员或类成员模板,显式专用的类的名称应为template-id。

此要求是否必须在本示例的末尾使用非typedef版本?或者我误解了什么?

编辑:进一步证据:Defect Report 403表明说一个类型(在该上下文中,函数调用表达式的参数类型)是 template-id 是不正确的因为 template-id 具有句法意义,而不是语义意义。后来的标准草案在3.4.2中使用了“类模板专业化”而不是“ template-id ”。

这支持这样的论点:虽然A<B>C表示相同的类型(并且具有相同或几乎相同的语义含义),但A<B> template-id C不是,因为术语 template-id 将句法内容称为标记序列而不是那些标记的含义。

2 个答案:

答案 0 :(得分:4)

我认为这是严重错误的(至少根据C ++ '03)。

我的逻辑是虽然是typedef(7.1.3 / 1):

  

...因此是另一种类型的同义词。

该标准仍然有明确允许在需要class-name的情况下使用typedef的字样(7.1.3 / 4):

  

命名类的typedef-name是类名

template-id没有这样的词。

答案 1 :(得分:0)

我认为明确的专业化并非如此。您可以在没有模板的情况下编写类似的代码:

struct A
{
    static const char* const str;
};

typedef A C;

const char* const C::str = "B";

即使您使用C代替A,此代码也是绝对正确的.C只是别名。

想象一下如何处理C ++代码。在模板实例化过程开始之前,显然会通过编译器扩展Typedef。与宏之前的所有注释相同。因为在实际的C ++解析甚至开始之前,所有的宏都被预处理器扩展。这简化了一切。

关于C ++ 03标准,请看一下

  

7.1.3 / 1使用typedef说明符声明的名称变为a   typedef的名称。在其范围内   声明,typedef-name是   语法等同于关键字   并命名与之关联的类型   标识符的描述方式   因此,typedef-name是一个   另一种类型的同义词。一个   typedef-name不会引入新的   输入类声明的方式(9.1)   或枚举声明。

我想这段代码清楚地解释了代码中的 C 实际上是模板ID。