特征类的typedef中的匿名结构

时间:2011-05-09 16:02:05

标签: c++ templates c++11 anonymous-class

对不起有趣的标题。

在C ++ 0x之前,使用函数本地结构(“本地类型”)作为模板参数有restrictions。我的问题基本上是否类似的限制适用于匿名结构。具体而言,在特质类的上下文中:

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?

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

4 个答案:

答案 0 :(得分:6)

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

  

本地类型,没有链接的类型,   未命名的类型或复合类型   任何这些类型都不得   用作a的模板参数   模板类型参数。

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

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

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

编辑:从7.1.3 / 1开始:

  

...因此,typedef-name是其同义词   另一种类型。 typedef-name没有   介绍一种新类型的方式   声明(9.1)或枚举声明   确实...

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

答案 1 :(得分:4)

在即将推出的标准中,限制已从语言中删除。

中的标准说明了

14.3.1 [temp.arg.type] / 1

  

作为类型的template-parameter的template-argument应为type-id。

typedef是有效的 type-id 。事实上,下一段包含了这样一个例子:

14.3.1 [temp.arg.type] / 2

template <class T> class X { };
template <class T> void f(T t) { }
void f() { 
   typedef struct { } B;
   B b;
   X<B> x3;
   f(b);
}

(我已经修剪了大多数其他示例)示例显示,未命名的类型可以在类模板和函数模板中用作类模板参数。

答案 2 :(得分:3)

一个typedef声明,它定义了该类的匿名类和typedef-name,typedef-name是用于链接目的的类的名称。因此,如果该类符合其他标准,则将该类用作模板参数是合法的。

参见C ++ 03标准的7.1.3p5

  

如果typedef声明定义了   未命名的类(或枚举),第一个   声明定义的typedef-name是该类类型(或枚举   type)用于表示类类型   (或枚举类型)用于链接目的   只(3.5)。 [实施例:

typedef struct { } *ps, S; // S is the class name for linkage purposes

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

FWIW,此代码与MSVC2010(模数拼写错误)编译正常。

答案 3 :(得分:0)

嗯,这相当于

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

这是完全合法的。