为什么inject-class-name有时不被视为类模板中的模板名称?

时间:2018-05-08 20:00:27

标签: c++ templates c++14 c++17 injected-class-name

Source

  

在以下情况中,inject-class-name被视为类模板本身的模板名称:

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

所以我尝试检查所有3个案例(另外在基础模糊的背景下,虽然我认为这不应该在这里)。

第一种情况似乎很简单。

问题是 - 为什么不注释出示例工作?它们不适用于海湾合作委员会和Clang所以我认为这不是一个实施问题

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 个答案:

答案 0 :(得分:2)

此处的相关规则是[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和一个clang bug。在:

using a = A<Base>;

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