我见过以下的C ++ 11之前的代码,用作声明类模板朋友的技巧(在C ++ 11中可以简单地用friend T;
完成)
template <typename T>
struct Wrapper
{
typedef T type;
};
template <typename T>
class Foo
{
friend class Wrapper<T>::type; // effectively makes T a friend
};
struct Test{};
int main()
{
Foo<Test> foo;
}
代码在g ++(4.9 / 5.1 / 6)上编译很好,但在clang ++(3.5 / 3.6 / 3.7)下失败并出现错误
错误:详细说明类型是指typedef
朋友类Wrapper :: type;
上述代码是否符合标准,即是否有效?
答案 0 :(得分:1)
§7.1.6.3/ 2:
如果标识符解析为 typedef-name 或 simple-template-id 解析为别名模板专精, elaborated-type-specifier 格式错误。
答案 1 :(得分:0)
它不合规。 [class.friend] / 3中friend
的语法规则是:
未声明函数的朋友声明应具有以下形式之一:
friend elaborated-type-specifier ; friend simple-type-specifier ; friend typename-specifier ;
class Wrapper<T>::type
不是那些说明符类型。它不是详细说明类型说明符,因为Wrapper<T>::type
不是标识符或类名,显然也不是其他两个中的一个。您正在寻找的只是:
friend typename Wrapper<T>::type;
答案 2 :(得分:0)
[dcl.typedef] / P8:
[注意:命名类类型或其cv限定版本的 typedef-name 也是类名(9.1)
如果 typedef-name 用于标识详细类型说明符 (7.1.6.3)的主题,则为类定义 (第9条),构造函数声明(12.1)或析构函数声明(12.4),程序格式错误。 - 结束记录] [示例:
struct S { S(); ~S(); }; typedef struct S T; S a = T(); // OK struct T * p; // error
- 结束示例]
代码应该在模板实例化时失败,它在Clang中正确执行。
使用typename
代替struct
,代码可以在两个编译器中传递。