kwikius said:
Its a library. I can't know all the units a user might want to make use
of.
Sure thats your moral position. OTOH I find it convenient to use a
struct for grouping and save typing. Member typedefs are a well known
idiom for traits classes for example.
A namespace is reopenable which is a useful feature it has over a
struct.
So given that it's reopenable, how would you instantiate a namespace
template? Piece by piece, I suppose: instantiate those parts that are
visible.
I could see it being a shorthand that could save a lot of repetitive
template syntax. E.g.
template <typename T> namespace N {
int foo(const T &);
}
Here, uses of the template ID N::foo without template arguments would
deduce T.
Would this be allowed?
template <typename T> namespace N {
void foo(); // no arguments
}
Here, nothing in the foo type signature depends on T. But foo could
refer to T things in the namespace.
template <typename T> namespace N {
T t;
void reset() { T = 0; }
}
I suppose it's similar to a class with a static member and static
function:
template <typename T> class C {
public:
static T t;
static void reset() { t = 0; }
};
int C<int>::t;
int main()
{
C<int>::reset();
return 0;
}
Basically, here we are just using the class as a namespace, right? It
has only static members. We never instantiate the class. Instantiation
of the template is forced by the definition of the static member.
You have to repeat that definition for every type.
The template namespace could do away with that inconvenience, since the
namespace could enclose a definition. But then that definition would
have to be in scope in order to be implicitly instantiated.
Classes are different from namespaces because they separate the
declaration from the implementation. The entire declaration is visible
at once. Where it's not visible, the class is not known. A namespace is
not necessarily all visible at once. Moreover, if a function has a body
in a class declaration, it's an inline function, which is not true of
namespaces. A namespace can contain noninline functions.
So there would have to be some special rules for namespace template
instantiation, such as: 1) instantiate just the necessary parts, from
whatever part of the templated namespace that is visible, and place the
instantiations into the translation unit where the reference is made.
Full function and object definitions are instantiated automatically if
implicit instantiation takes place. If only declarations are visible,
they are instantiated, but the definitions are not.
E.g.
// File1.cc
template <type T> namespace N {
int def_obj = 0;
extern int decl_obj;
int def_fun()
{
return def_obj + decl_obj;
}
int decl_fun();
int foo;
}
// ...
N::def_fun(); // error, ambiguous
N<int>::def_fun();
// requests N<int>::def_fun() instantiation.
// also requests N<int>::def_obj instantiation, needed by the body.
// also requests N<int>::decl_obj instantiation, but that is just a
decl
// so this won't link unless N<int>::decl_obj is generated somewhere.
N<int>::decl_fun();
// "instantiates" the declaration, but a definition must be
// made somewhere.
Now suppose there is a second file:
// File2.cc
template <typename T> namespace N {
int decl_obj = 42;
}
// alternate syntax; must use template arguments on N
template <typename T>
int N<T>::decl_fun()
{
return decl_obj;
}
// now we must force instantiation somehow.
// How about explicit request?
// Generates over all /visible/ N<T>.
// E.g. does not generate N<int>::foo since
// N<T>::foo is declared in the other translation unit,
// which is not known here.
template namespace N<int>;