特征类的类型定义中的匿名结构

Anonymous struct in typedef of trait class

本文关键字:结构 定义 类型 特征      更新时间:2023-10-16

对不起,这个有趣的标题。

在 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?

这是否有效和可靠?它在最新版本的GCC和LLVM中编译,但我仍然不确定这是否严格有效,以及VC++和ICC是否理解它。

作为参考,引用了 14.3.1/2 中链接问题的引文:

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

我的解释是,typedef struct正在为未命名类型创建别名,因此它不能用作模板类型参数。进一步注意,另外,在C中,typedef struct {} Foo;的处理方式与struct Foo {};给出两种形式不等价的先例相当不同(尽管不可否认,这种差异在C++中没有出现)。

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

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

编辑:从7.1.3/1:

。因此,typedef-name 是 另一种类型。类型定义名称不 以类的方式引入新类型 声明 (9.1) 或枚举声明 难道...

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

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

14.3.1 [温度参数类型]/1

作为类型的模板参数的模板参数应为类型 ID。

typedef 是有效的类型 ID。事实上,下一段包含这样一个例子:

14.3.1 [温度参数类型]/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);
}

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

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

请参阅 C++03 标准的 7.1.3p5

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

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

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

FWIW,此代码可以使用MSVC2010(模错别字)编译正常。

嗯,这相当于

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

这是完全合法的。