【问题标题】:Injected-class-names of class templates类模板的注入类名
【发布时间】:2014-12-20 21:59:54
【问题描述】:

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

template<class>
class A { };

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

这是代码

  1. 格式错误,因为 A&lt;float&gt;::A 命名构造函数(根据 §3.4.3.1 [class.qual]/p2)并且不能在此上下文中使用(加上 &lt;int&gt; 无论如何都无法解析),或者
  2. 格式良好,A&lt;float&gt;::Ainjected-class-name,用作 模板名称(§14.6.1 [temp.local]) , 这样A&lt;float&gt;::A&lt;int&gt;A&lt;int&gt; 的含义完全相同,而a 被声明为函数(由于最令人头疼的解析)?

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

【问题讨论】:

    标签: c++ templates language-lawyer


    【解决方案1】:

    gcc 是正确的;你的 sn-p 格式不正确!

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

    在上面简化的测试用例中,我们有一个 nested-name-specifierA&lt;float&gt;::,后跟一个 unqualified-id A,然后是一些胡言乱语(&lt;int&gt;)。

    这是因为 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.qual]

    在不忽略函数名称的查找中88 并且 nested-name-specifier 指定了一个类 C

    • 如果在nested-name-specifier之后指定的名称,当在C中查找时,是C的注入类名>(第 9 条),或
    • using-declaration (7.3.3) 中,它是一个 member-declaration,如果在 nested-name-specifier 之后指定的名称 em> 与 *nested- 的最后一个组件中的 identifiersimple-template-idtemplate-name 相同名称说明符,

    该名称被认为是命名类C的构造函数。

    [ 注意: ... ]

    这样的构造函数名称只能用于命名构造函数的声明的 declarator-idusing-declaration


    88. 忽略函数名称的查找包括出现在 nested-name-specifier 中的名称,elaborated-type-specifier,或 基本说明符

    14.6.1p2 本地声明的名称 [temp.local]

    与普通(非模板)类一样,类模板具有注入的类名 (第 9 条)。注入的类名可以用作 template-name类型名称

    当它与 template-argument-list 一起使用时,作为 template-argument 用于模板 template-parameter,或作为最终 朋友类模板的详细类型说明符中的标识符 声明,它引用类模板本身。

    否则就是 相当于 template-name 后跟 template-parameters &lt;&gt; 中包含的类模板。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-03
      • 2022-11-01
      相关资源
      最近更新 更多