On page 7, he writes "One might think that a more C++-ish way of hoisting a
facility into two namespaces would be to use
a using-declaration
. One would be almost right."
It does seem that using
would be a good way to separate the
actual implementation from the namespace that we want other code to
interact with. But as Herb notes, the problem with this is that we can
only specialize a template in its actual namespace, not a namespace it has
been imported into. Also, argument-dependent lookup breaks down if library
components are split across multiple namespaces.
using-directive
that
allows other code to define and specialize members of the used namespace as
though they actually belong to the using namespace. This is referred to as
namespace association because of its effects on argument-dependent lookup.
This paper proposes adding the extern
keyword to
the using-directive
to request the additional behavior, but
other syntax choices would be possible.
For instance:
namespace Lib { namespace Lib_1 { } extern using namespace Lib_1; namespace Lib_1 { templateclass A; } template void g(T); } ... struct MyClass { ... }; namespace Lib { template<> class A { ... }; } int main() { Lib::A a; g(a); // ok, Lib is an associated namespace of A }
using-directive: externopt using namespace ::opt nested-name-specifieropt namespace-name ;
If the extern specifier is used, the used namespace must be a member (possibly indirect) of the current namespace. Such a using-directive declares the using namespace to be an associated namespace ([basic.lookup.argdep]) of the used namespace. Furthermore, members of the used namespace can subsequently be defined ([namespace.memdef]), explicitly instantiated ([temp.explicit]) or explicitly specialized ([temp.expl.spec]) as though they were a member of the using namespace.
If any of the associated namespaces have their own associated namespaces ([namespace.udir]), those are also included in the set.
-4- If a named namespace has associated namespaces ([namespace.udir]), its members can also be defined within an associated namespace, or by explicit qualification with an associated namespace.
-5- An explicit instantiation of a class or function template specialization is placed in the namespace in which the template is defined, or an associated namespace thereof. An explicit instantiation for a member of a class template is placed in the namespace where the enclosing class template is defined, or an associated namespace thereof. An explicit instantiation for a member template is placed in the namespace where the enclosing class or class template is defined, or an associated namespace thereof.
-2- An explicit specialization shall be declared in the namespace of which the template is a member, or, for member templates, in the namespace of which the enclosing class or enclosing class template is a member, or an associated namespace thereof. An explicit specialization of a member function, member class or static data member of a class template shall be declared in the namespace of which the class template is a member, or an associated namespace thereof. Such a declaration may also be a definition. 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.
Herb Sutter, Namespaces and Library Versioning, N1344