[class.pre] p3 states:
If a class-head-name contains a nested-name-specifier, the class-specifier shall not inhabit a class scope. If its class-name is an identifier, the class-specifier shall correspond to one or more declarations nominable in the class, class template, or namespace to which the nested-name-specifier refers; they shall all have the same target scope, and the target scope of the class-specifier is that scope.
[ Example:
namespace N { template<class> struct A { struct B; }; } using N::A; template<class T> struct A<T>::B {}; // OK template<> struct A<void> {}; // OK
-- end example ]
The first sentence and the example seem to differ.
Is the specialization of A<void>
template, which does not contain a nested-name-specifier (but only 'relies' on using) still conformant?
clang and msvc accept it, gcc shows the error
error: explicit specialization of 'template struct N::A' outside its namespace must use a nested-name-specifier [-fpermissive]
Additional Context
The paper, which introduced the original wording and example comment, is P1787R6: Declarations and where to find them, containing the line:
template<> struct A<void> {}; // error: A not nominable in ::
An editorial change Edit: [class.pre] Fix incorrect comment in example changed the example so that the comment now says OK
. More discussion relating to it is found in editorial issue 4592
N::A
may be defined in the enclosing namespace. – ArrasA
inA<void>
finds class templateA
from namespaceN
? – Arras.
or->
in a class member access expression… Unless otherwise specified, such a name undergoes unqualified name lookup from the point where it appears. Now one needs to show that it is not otherwise specified, and it is always hard to prove the absence. – ArrasA
inA<void>
is not among those things. – ArrasThe definition of the member function f of class X inhabits the global scope
[for a specific example] – GhislainegholstonN::P
, and notN
. AndN::P
is not in inline namespace set ofN
. – Arrasf
inN
finds a using-declarationusing P::f
, which is replaced with the declaration named by it:N::P::f
. Since it is not nominable inN
, it is ignored. – ArrasA<T>::B
. so best is to wait for a clarifying update of the standard? What else the current draft is missing, except for the normative wording about specializations' target scope? – ArrasA<void>
? Because it specializes a class and not a function template. – ArrasA
is looked up per eel.is/c++draft/basic.lookup.unqual#4.sentence-2 and no lookup results are ignored, because it is a specialization of a class template. – Arrastemplate<> struct A<void> {}
. – ArrasOtherwise, if the class-head-name is a simple-template-id, the terminal name of the simple-template-id is (unqualified name) looked up; they shall all have the same target scope, and the target scope of the class-specifier is that scope.
to class.pre/3. – Ghislainegholstonotherwise
relates to nested-name-specifier), whereas in dcl.meaning.general#3.3 nominability is a requirement. This has an effect on which programs are well-formed. Of course the nominability could be in the target scope (together with eel.is/c++draft/dcl.meaning.general#3.2). – Ghislainegholston