c++ - 类模板的注入(inject)类名

标签 c++ templates language-lawyer

灵感来自 the code in this answer .考虑:

template<class>
class A { };

int main()
{
    A<float> a(A<float>::A<int>());
    return 0;
}

这是代码

  1. 格式错误,因为 A<float>::A命名构造函数(根据 §3.4.3.1 [class.qual]/p2)并且不能在此上下文中使用(加上 <int> 无论如何都无法解析),或者
  2. 格式良好,带有 A<float>::Ainjected-class-name,用作 template-name (§14.6.1 [temp.local]),这样 A<float>::A<int>表示与 A<int> 完全相同, 和 a被声明为函数(由于最麻烦的解析)?

g++ says 1. clang says 2ICC 13 也是如此.哪个编译器是正确的?

最佳答案

gcc是正确的;您的代码段格式不正确!

// reduced testcase
template<class T>
class A { };

int main () {
  A<float>::A<int> x; // ill-formed, bug in `clang` and `icc`
}

在上述简化的测试用例中,我们有一个 nested-name-specifierA<float>:: , 后跟 unqualified-id A ,然后是一些乱码(<int>)。

这是因为 nested-name-specifier 出现的上下文要求在查找期间包含函数名称(意味着首先找到构造函数,并且表达式为格式错误)。


相关错误报告:


如何规避“问题”?

在某些上下文中,通过 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 members [class.qual]

In a lookup in which function names are not ignored88 and the nested-name-specifier nominates a class C:

  • if the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C (Clause 9), or
  • in a using-declaration (7.3.3) that is a member-declaration, if the name specified after the nested-name-specifier is the same as the identifier or the simple-template-id's template-name in the last component of the *nested-name-specicifier,

the name is instead considered to name the constructor of class C.

[ Note: ... ]

Such a constructor name shall be used only in the declarator-id of a declaration that names a constructor or in a using-declaration.


88. Lookups in which function names are ignored include names appearing in a nested-name-specifier, an elaborated-type-specifier, or a base-specifier.

14.6.1p2 Locally declared names [temp.local]

Like normal (non-template) classes, class templates have an injected-class-name (Clause 9). The injected-class-name can be used as a template-name or a type-name.

When it is used with a template-argument-list, as a template-argument for a template template-parameter, or as the final identifier in the elaborated-type-specifier of a friend class template declaration, it refers to the class template itself.

Otherwise, it is equivalent to the template-name followed by the template-parameters of the class template enclosed in <>.

关于c++ - 类模板的注入(inject)类名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26558507/

相关文章:

c++ - 设置 g++ 编译器标志以进行调试

c++ - strcpy 不适用于相同大小的数组

c++ - 默认模板参数在(部分特化的)类模板的重载决议中的作用

c++ - 模板类构造函数接受参数时出错

c++ - 为什么 std::hash 不能保证是确定性的?

c++ - 根据我对 §3.4.1/8 的解释,这段代码应该可以编译。我错过了什么?

c++ - volatile 类类型的丢弃值表达式与 volatile 内置类型的行为不同

c++ - 带有 lambda 捕获的 EXC_BAD_ACCESS

c++ - malloc.c :3097: sYSMALLOc: Assertion fails inside constructor of dynamically created object

C++11模板函数接受多个模板别名