为什么 injected-class-name 有时不被视为 class 模板中的模板名称?
Why injected-class-name is sometimes not treated as a template name in a class template?
In the following cases, the injected-class-name is treated as a template-name of the class template itself:
- it is followed by <
- it is used as a template argument that corresponds to a template template parameter
- it is the final identifier in the elaborated class specifier of a friend class template declaration.
所以我尝试检查所有 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;
};
上面的规则是否只适用于模板本身,而不适用于基础?如果是这样,碱基的规则是什么,尤其是最后两种情况?
这里的相关规则是[temp.local]/4:
A lookup that finds an injected-class-name ([class.member.lookup]) can result in an ambiguity in certain cases (for example, if it is found in more than one base class). If all of the injected-class-names that are found refer to specializations of the same class template, and if the name is used as a template-name, the reference refers to the class template itself and not a specialization thereof, and is not ambiguous. [ Example:
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
};
— end example ]
我认为这意味着这是一个 gcc 和一个 clang 错误。在:
using a = A<Base>;
找到的所有注入-class-名称确实指的是同一 class 模板 (Base<T>
) 和 该名称用作 模板名称 (因为它是模板模板参数的模板参数),所以这应该仅引用 class 模板本身而不是模糊的。
In the following cases, the injected-class-name is treated as a template-name of the class template itself:
- it is followed by <
- it is used as a template argument that corresponds to a template template parameter
- it is the final identifier in the elaborated class specifier of a friend class template declaration.
所以我尝试检查所有 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;
};
上面的规则是否只适用于模板本身,而不适用于基础?如果是这样,碱基的规则是什么,尤其是最后两种情况?
这里的相关规则是[temp.local]/4:
A lookup that finds an injected-class-name ([class.member.lookup]) can result in an ambiguity in certain cases (for example, if it is found in more than one base class). If all of the injected-class-names that are found refer to specializations of the same class template, and if the name is used as a template-name, the reference refers to the class template itself and not a specialization thereof, and is not ambiguous. [ Example:
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 };
— end example ]
我认为这意味着这是一个 gcc 和一个 clang 错误。在:
using a = A<Base>;
找到的所有注入-class-名称确实指的是同一 class 模板 (Base<T>
) 和 该名称用作 模板名称 (因为它是模板模板参数的模板参数),所以这应该仅引用 class 模板本身而不是模糊的。