受the code in this answer的启发。考虑:
template<class>
class A { };
int main()
{
A<float> a(A<float>::A<int>());
return 0;
}
这是代码吗
A<float>::A
命名构造函数(根据§3.4.3.1[class.qual] / p2)并且不能在此上下文中使用(加上<int>
将完成无法解析无论如何),或A<float>::A
是注入类名,用作模板名称(§14.6.1[temp.local] ]),A<float>::A<int>
表示与A<int>
完全相同,a
被声明为函数(由于最令人烦恼的解析)?g++ says 1. clang says 2,ICC 13也一样。哪个编译器是正确的?
答案 0 :(得分:6)
gcc
是正确的;你的片段格式不正确!// reduced testcase
template<class T>
class A { };
int main () {
A<float>::A<int> x; // ill-formed, bug in `clang` and `icc`
}
在上面的简化测试用例中,我们有一个嵌套名称说明符,A<float>::
,后跟一个 unqualified-id A
,其中然后是一些乱码(<int>
)。
这是因为嵌套名称说明符出现的上下文要求在查找期间包含函数名称(意味着首先找到构造函数,表达式为不良形成的)。
相关错误报告:
有些上下文通过 nested-name-specifier (提名类)查找的成员名称不应包含函数(因此,找不到构造函数的上下文),以下是一些例子:
template<class T>
struct A {
typedef T value_type;
};
struct A<float>::A<int> x; // ok, context: elaborate-type-specifier
typename A<float>::A<int> (); // ok, context: [expr.type.conv]p1
A<float>::A::value_type x; // ok, context: nested-name-specifier
struct X : A<float>::A<int> { }; // ok, context: base-specifier
3.4.3.1p2
班级成员[class.qual]
在不忽略函数名称的查找 88 且嵌套名称说明符指定类 C :
- 如果嵌套名称说明符之后指定的名称(在 C 中查找)是 C 的注入类名称>(第9条)或
- 在 using-declaration (7.3.3)中是 member-declaration ,如果在 nested-name-specifier 之后指定的名称与标识符或 simple-template-id 的模板名称在最后一个组件中相同*嵌套名-specicifier,
而是将名称视为命名 C 类的构造函数。
[注意:...]
这样的构造函数名称只能用于命名构造函数的声明的 declarator-id 或 using-declaration 。
88。忽略函数名称的查找包括出现在嵌套名称说明符中的名称, elaborated-type-specifier < / em>,或 base-specifier 。
14.6.1p2
本地声明的名称[temp.local]
与普通(非模板)类一样,类模板具有注入类名 (第9条)。 inject-class-name可以用作模板名称或a 类型名称
当它与 template-argument-list 一起使用时,作为 template-argument 用于模板 template-parameter ,或作为最终版本 友元类模板的 elaborated-type-specifier 中的标识符 声明,它指的是类模板本身。
否则就是 相当于 template-name ,后跟 template-parameters
<>
中包含的类模板。