6

资源

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

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

因此,我尝试检查所有 3 个案例(此外,在基本歧义的背景下,尽管我认为这在这里无关紧要)。

第一种情况看起来很简单。

问题是 - 为什么不注释掉的例子有效?他们不在 GCC 和 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;
};

上面的规则是否仅适用于模板本身,而不适用于基础?如果是这样,基地的规则是什么,尤其是最后两个案例?

4

1 回答 1

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 错误。在:

using a = A<Base>;

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

于 2018-05-08T20:11:49.877 回答