特征类的typedef中的匿名结构

Kon*_*lph 14 c++ templates anonymous-class c++11

抱歉有趣的标题.

在此之前的C++ 0x,有限制的使用功能局部结构("本地型")作为模板参数.我的问题基本上是否类似的限制适用于匿名结构.具体来说,在特质类的上下文中:

template <typename T>
struct trait;

template <>
struct trait<int> {
    typedef int type;
};

template <typename T>
struct trait<std::basic_string<T> > {
    typedef struct {
        T value;
    } type;
};

trait<std::string>::type foo; // Is this valid?

template <typename T>
void f() { }

f<trait<std::string>::type> >(); // Is this?

template <typename T>
void g() { f<typename trait<T>::type>(); }

g<std::string>(); // And this?
Run Code Online (Sandbox Code Playgroud)

这有效可靠吗?它汇编了最新版本的GCC和LLVM,但我仍然不安全,这是否严格有效,以及VC++和ICC是否理解它.

Mar*_*k B 6

供参考,14.3.1/2中链接问题的引用:

本地类型,没有链接的类型,未命名的类型或从这些类型中的任何类型复合的类型不应用作模板类型参数的模板参数.

我的解释是typedef struct创建了一个未命名类型的别名,因此它不能用作模板类型参数.进一步注意到,另外在C typedef struct {} Foo;中的处理方式与struct Foo {};先前的两种形式不相等有所不同(尽管可以肯定这种差异不会出现在C++中).

因此,看起来你的第一个例子是有效的(因为它没有使用未命名的类型作为模板类型参数),而第二个和第三个例子在技术上是无效的(因为它们确实将它用作模板类型参数).

最后在结束时我不得不问,有没有理由你不能命名结构而不是typedef它?

编辑:从7.1.3/1:

...因此,typedef-name是另一种类型的同义词.typedef-name不会像类声明(9.1)或枚举声明那样引入新类型...

这强烈暗示typedef以这种方式使用不会引入适合用作模板类型参数的类型.


Ant*_*ams 3

typedef定义匿名类和该类的 typedef-name 的声明,typedef-name 是用于链接目的的类的名称。因此,如果该类满足其他条件,则使用该类作为模板参数是合法的。

参见C++03标准的7.1.3p5

如果 typedef 声明定义了一个未命名的类(或枚举),则该声明声明为该类类型(或枚举类型)的第一个 typedef 名称仅用于表示该类类型(或枚举类型),仅用于链接目的(3.5)。[例子:

typedef struct { } *ps, S; // S is the class name for linkage purposes
Run Code Online (Sandbox Code Playgroud)

这是 C++0x FDIS 中的 7.1.3p9。

FWIW,此代码可以使用 MSVC2010 编译正常(模数拼写错误)。

  • 它随之而来。`typedef` 本身并不引入新类型,而是 typedef 声明“内部”的类定义引入新类型。然后 typedef 给出新类型的名称。它不是类型的“该”名称——例如,您不能在类定义中使用它来定义构造函数或析构函数——但它提供了一个“用于链接目的”的名称。 (2认同)