This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
[Voted into WP at July, 2009 meeting.]
Paper N2657, adopted at the June, 2008 meeting, removed the prohibition of local and unnamed types as template arguments. As part of the change, 6.6 [basic.link] paragraph 8 was modified to read,
A type without linkage shall not be used as the type of a variable or function with linkage, unless
the variable or function has extern "C" linkage (9.11 [dcl.link]), or
the type without linkage was named using a dependent type (13.8.3.2 [temp.dep.type]).
Because a type without linkage can only be named as a dependent type, there are still some potentially useful things that cannot be done:
template <class T> struct A { friend void g(A, T); // this can't be defined later void h(T); // this cannot be explicitly specialized }; template <class T> void f(T) { A<T> at; g(at, (T)0); } enum { e }; void g(A<decltype(e)>, decltype(e)){} // not allowed int main() { f(e); }
These deficiencies could be addressed by allowing types without linkage to be used as the type of a variable or function, but with the requirement that any such entity that is used must also be defined in the same translation unit. This would allow issuing a compile-time, instead of a link-time, diagnostic if the definition were not provided, for example. It also seems to be easier to implement than the current rules.
Proposed resolution (March, 2009):
Change 6.6 [basic.link] paragraph 8 as follows:
...A type without linkage shall not be used as the type of a variable or function with linkage, unless
the variable or function has extern "C" linkage (9.11 [dcl.link]), or
the type without linkage was named using a dependent type (13.8.3.2 [temp.dep.type])the variable or function is not used (6.3 [basic.def.odr]) or is defined in the same translation unit.[Note: in other words, a type without linkage contains a class or enumeration that cannot be named outside its translation unit. An entity with external linkage declared using such a type could not correspond to any other entity in another translation unit of the program and thus
is not permittedmust be defined in the translation unit if it is used. Also note that classes with linkage may contain members whose types do not have linkage, and that typedef names are ignored in the determination of whether a type has linkage. —end note] [Example:void f() { struct A { int x; }; // no linkage extern A a; // ill-formed typedef A B; extern B b; // ill-formed }
—end example]
[Example:template <class T> struct A { // in A<X>, the following is allowed because the type with no linkage // X is named using template parameter T. friend void f(A, T){} }; template <class T> void g(T t) { A<T> at; f(at, t); } int main() { class X {} x; g(x); }template <typename T> struct B { void g(T){} void h(T); friend void i(B, T){} }; void f() { struct A { int x; }; // no linkage A a = {1}; B<A> ba; // declares B<A>::g(A) and B<A>::h(A) ba.g(a); // OK ba.h(a); // error: B<A>::h(A) not defined in the translation unit i(ba, a); // OK }—end example]
[Drafting note: issue 527 also changes part of the same text.]