This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-10-26
[Moved to DR at 4/02 meeting.]
Consider this example:
namespace N { template <class T> void f(T){} template <class T> void g(T){} template <> void f(int); template <> void f(char); template <> void g(char); } using namespace N; namespace M { template <> void N::f(char){} // prohibited by standard template <class T> void g(T){} template <> void g(char){} // specialization of M::g or ambiguous? template void f(long); // instantiation of N::f? } template <class T> void g(T){} template <> void N::f(char){} // okay template <> void f(int){} // is this a valid specialization of N::f? template void g(int); // instantiation of ::g(int) or ambiguous?
The question here is whether unqualified names made visible by a using-directive can be used as the declarator in an explicit instantiation or explicit specialization.
Note that this question is already answered for qualified names in 9.3.4 [dcl.meaning] paragraph 1. In a qualified name such as N::f, f must be a member of class or namespace N, not a name made visible in N by a using-directive (or a using-declaration, for that matter).
The standard does not, as far as I can tell, specify the behavior of these cases one way or another.
My opinion is that names from using-directives should not be considered when looking up the name in an unqualified declarator in an explicit specialization or explicit instantiation. In such cases, it is reasonable to insist that the programmer know exactly which template is being specialized or instantiated, and that a qualified name must be used if the template is a member of a namespace.
As the example illustrates, allowing names from using-directives to be used would also have the affect of making ambiguous otherwise valid instantiation and specialization directives.
Furthermore, permitting names from using-directives would require an additional rule to prohibit the explicit instantiation of an entity in one namespace from being done in another (non-enclosing) namespace (as in the instantiation of f in namespace M in the example).
Mike Miller: I believe the explicit specialization case is already covered by _N4868_.9.8.2.3 [namespace.memdef] paragraph 2, which requires using a qualified name to define a namespace member outside its namespace.
John Spicer: _N4868_.9.8.2.3 [namespace.memdef] deals with namespace members. An explicit specialization directive deals with something that is a specialization of a namespace member. I don't think the rules in _N4868_.9.8.2.3 [namespace.memdef] could be taken to apply to specializations unless the standard said so explicitly.
Proposed resolution (suggested 04/01, proposed 10/01):
(The first change below will need to be revised in accordance with the resolution of issue 284 to add a cross-reference to the text dealing with class names.)
Add in 13.9.3 [temp.explicit] paragraph 2 before the example:
An explicit instantiation shall appear in an enclosing namespace of its template. If the name declared in the explicit instantiation is an unqualified name, the explicit instantiation shall appear in the namespace where its template is declared. [Note: Regarding qualified names in declarators, see 9.3.4 [dcl.meaning].]
Change the first sentence of _N4868_.9.8.2.3 [namespace.memdef] paragraph 1 from
Members of a namespace can be defined within that namespace.
to
Members (including explicit specializations of templates (13.9.4 [temp.expl.spec])) of a namespace can be defined within that namespace.
Change the first sentence of _N4868_.9.8.2.3 [namespace.memdef] paragraph 2 from
Members of a named namespace can also be defined...
to
Members (including explicit specializations of templates (13.9.4 [temp.expl.spec])) of a named namespace can also be defined...
Change the last sentence of 13.9.4 [temp.expl.spec] paragraph 2 from
If the declaration is not a definition, the specialization may be defined later in the namespace in which the explicit specialization was declared, or in a namespace that encloses the one in which the explicit specialization was declared.
to
If the declaration is not a definition, the specialization may be defined later (_N4868_.9.8.2.3 [namespace.memdef]).