Namespace Association ("strong" using)

Jason Merrill
2007-06-22
Document Number N2331=07-0191
Revision 1

Introduction

This paper provides proposed wording for the extension referred to in N2013 as "namespace association".

The Problem

In N1344, Herb Sutter discussed the problems of shared library versioning specifically with regard to allowing the C++98 and C++0x standard libraries to coexist, going over various options and the problems with them.

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.

The Proposed Solution

The proposed extension creates a stronger 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
  {
    template  class 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
}

Proposed Wording

In [namespace.udir] and appendix A

Change the grammar for using-directive to
using-directive:
        externopt using  namespace ::opt nested-name-specifieropt namespace-name ;

Also in [namespace.udir]

Add a new paragraph:

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.

In [basic.lookup.argdep]

Add to the end of paragraph 2:

If any of the associated namespaces have their own associated namespaces ([namespace.udir]), those are also included in the set.

In [namespace.memdef]

Add a new paragraph:

-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.

In [temp.explicit]

-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.

In [temp.expl.spec]

-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.

References

Benjamin Kosnik, Versioning with Namespaces, N2013

Herb Sutter, Namespaces and Library Versioning, N1344