Why does C++11 not have \"template typedefs\", like
template typedef std::vector> vec;
Instead
n1406 was the proposal by Herb Sutter for "typedef templates" which mimics the syntax in your question. n1499 which proposes "template aliases" supersedes it, which contains the using
syntax that's currently present in C++11.
One of the main drawbacks of the "typedef templates" is addressed in both papers. From n1406:
In existing practice, including in the standard library, type names nested inside helper class templates are used to work around this problem in many cases. The following is one example of this usual workaround; the main drawback is the need to write ::Type when using the typedef’d name.
template< typename T > struct SharedPtr { typedef Loki::SmartPtr < T, // note, T still varies RefCounted, // but everything else is fixed NoChecking, false, PointsToOneObject, SingleThreaded, SimplePointer<T> // note, T can be used as here > Type; }; SharedPtr<int>::Type p; // sample usage, “::Type” is ugly
What we’d really like to be able to do is simply this:
template< typename T > typedef Loki::SmartPtr < T, // note, T still varies RefCounted, // but everything else is fixed NoChecking, false, PointsToOneObject, SingleThreaded, SimplePointer<T> // note, T can be used as here > SharedPtr; SharedPtr<int> p; // sample usage, “::Type” is ugly
[...]
The workaround is ugly, and it would be good to replace it with first-class language support that offers users a natural C++ template syntax.
That "first-class language support" comes in the form of template aliases. We can now look at what n1499 has to say:
In this paper we will focus on describing an aliasing mechanism that allows the two semantics mentioned in N1406 to coexist instead being regarded as mutually exclusive. First let’s consider a toy example:
template <typename T> class MyAlloc {/*...*/}; template <typename T, class A> class MyVector {/*...*/}; template <typename T> struct Vec { typedef MyVector<T, MyAlloc<T> > type; }; Vec<int>::type p; // sample usage
The fundamental problem with this idiom, and the main motivating fact for this proposal, is that the idiom causes the template parameters to appear in non-deducible context. That is, it will not be possible to call the function
foo
below without explicitly specifying template arguments.template <typename T> void foo (Vec<T>::type&);
Also, the syntax is somewhat ugly. We would rather avoid the nested ::type call. We’d prefer something like the following:
template <typename T> using Vec = MyVector<T, MyAlloc<T> >; //defined in section 2 below Vec<int> p; // sample usage
Note that we specifically avoid the term "typedef template" and introduce the new syntax involving the pair "using" and "=" to help avoid confusion: we are not defining any types here, we are introducing a synonym (i.e. alias) for an abstraction of a type-id (i.e. type expression) involving template parameters. If the template parameters are used in deducible contexts in the type expression then whenever the template alias is used to form a template-id, the values of the corresponding template parameters can be deduced – more on this will follow. In any case, it is now possible to write generic functions which operate on
Vec<T>
in deducible context, and the syntax is improved as well. For example we could rewritefoo
as:template <typename T> void foo (Vec<T>&);
We underscore here that one of the primary reasons for proposing template aliases was so that argument deduction and the call to
foo(p)
will succeed.
So you can see that n1499 addresses the problems in n1406 as well as introducing a syntax that's much cleaner and easier to read.