Description
Full name of submitter (unless configured in github; will be published with the issue): Hubert Tong
Reference (section label): [basic.scope.namespace]
Link to reflector thread (if any): N/A
Issue description:
Consider the following:
namespace N {
inline namespace A {
constexpr int f(int *);
}
inline namespace B {
constexpr int f(long *);
}
} // namespace N
template <typename T> struct Q { using type = long; };
constexpr int N::f(Q<struct X *>::type *) { return 42; }
namespace N {
inline namespace B {
struct X {};
}
} // namespace N
template <> struct Q<N::B::X *>; // explicit specialization after implicit instantiation
static_assert(N::B::f(0) == 42);
https://eel.is/c++draft/basic.scope.namespace#1.sentence-2 tells us that:
For each non-friend redeclaration or specialization whose target scope is or is contained by the scope, the portion after the declarator-id, class-head-name, or enum-head-name is also included in the scope.
The target scope of the declaration whose declarator-id is N::f
is N::B
according to https://eel.is/c++draft/dcl.meaning.general#3.4.
It is unclear how, for the purposes of https://eel.is/c++draft/dcl.type.elab#3, a compiler is supposed to know that the nearest enclosing namespace (and, thus, the target scope for struct X
) is N::B
at the point the specialization of Q
is required.
Indeed, no implementation uses N::B
as the target scope for the elaborated type specifier.
Clang reasonably uses N
and the other implementations questionably use the global namespace: https://godbolt.org/z/drfo4rz9E
Suggested resolution:
Perhaps the scope that starts after the declarator-id should be the one named by the nested-name-specifier until after the declarator.