代码之家  ›  专栏  ›  技术社区  ›  ledonter

为什么注入的类名有时不被视为类模板中的模板名?

  •  6
  • ledonter  · 技术社区  · 6 年前

    Source

    在以下情况下,注入的类名被视为类模板本身的模板名:

    • 后跟<
    • 它用作与模板模板参数相对应的模板参数
    • 它是友元类模板声明的详细类说明符中的最终标识符。

    因此,我尝试检查所有3种情况(此外,在基础歧义的情况下,虽然我认为这在这里并不重要)。

    第一种情况似乎很简单。

    问题是,为什么注释掉的示例不起作用?GCC和;所以我不认为这是一个实现问题

    template <template <class> class> struct A;
    
    template <class T> struct Base {};
    
    template <class T> struct Derived: Base<int>, Base<char>
    {
        // #1
        typename Derived::Base<double> d;
        
        // #2
        
        // using a = A<Base>;
    
        using a = A<Derived::template Base>;
    
        // #3
    
        template<class U1>
        friend struct Base;
    
        // template<class U>
        // friend struct Derived::template Base;
    };
    

    上述规则是否仅适用于模板本身,而不适用于基础?如果是的话,什么是基本原则,尤其是最后两种情况?

    1 回复  |  直到 4 年前
        1
  •  2
  •   Barry    6 年前

    这里的相关规则是 [temp.local]/4 :

    查找注入的类名([class.member.lookup])可能会在某些情况下导致歧义(例如,如果在多个基类中找到)。如果找到的所有注入类名都引用同一类模板的专门化,并且如果该名称用作 模板名称 ,该引用引用类模板本身,而不是其专门化,并且没有歧义。 [示例:

    template <class T> struct Base { };
    template <class T> struct Derived: Base<int>, Base<char> {
      typename Derived::Base b;             // error: ambiguous
      typename Derived::Base<double> d;     // OK
    };
    

    结束示例]

    我认为这意味着这是一个gcc和一个叮当作响的bug。在中:

    using a = A<Base>;
    

    找到的所有注入类名都引用同一类模板的专门化( Base<T> ) 该名称用作 模板名称 (因为它是模板模板参数的模板参数),所以这应该只引用类模板本身,而不是模棱两可的。