struct A{
template<typename U>
void T(){}
};
struct B{
template<typename U>
struct T{
using type = U;
};
};
struct C:A,B{
};
int main(){
C::T<int>::type d;
}
This example is accepted by neither GCC nor Clang.
As per basic.lookup.qual#1
The name of a class or namespace member or enumerator can be referred to after the:: scope resolution operator ([expr.prim.id.qual]) applied to a nested-name-specifier that denotes its class, namespace, or enumeration. If a:: scope resolution operator in a nested-name-specifier is not preceded by a decltype-specifier, lookup of the name preceding that :: considers only namespaces, types, and templates whose specializations are types.
That means that when looking up the declarations for the template name T
, the specialization of T
shall denote a type in this context. On the other hand, as per class.member.lookup#4
If C contains a declaration of the name f, the declaration set contains every declaration of f declared in C that satisfies the requirements of the language construct in which the lookup occurs.
Again, when looking up the template T
in the scope of C
, only those templates whose specialization is a type should be considered by this lookup. The scope of C
does not have any declarations for T
, hence the lookup will be performed for S(T,C)
in every one of its base classes. The template T
in A
does not satisfy the requirement. Meanwhile, the template T
declared in the scope of B
does satisfy the requirement. So the lookup is not ambiguous and the B::T
is the unique result. That means C::T<int>::type d
should be well-formed. Why do both GCC and Clang reject this example? Can it be considered a bug of in both? If I missed something, what's the reason that this example should be ill-formed?
The lookahead required to have the lookup for T
depend on the ::
even as the interpretation of <
depends on the meaning of T
is considered undesirable. As such, lookup for a name followed by <
is not restricted to types and namespaces regardless of any >::
found later. P1787R6 fixed this, restricting the special lookup to identifiers immediately followed by ::
(since other kinds of names can’t refer to types or namespaces anyway).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With