Why do type aliases in C++ use 'using' instead of 'typedef' in their syntax?
What you suggest was actually proposed back in 2002 in document N1406 by Herb Sutter. It would allow, for example, to write:
template<typename T> typedef X<T,int> Xi;
This was later revised in N1449 by Gabriel Dos Reis and Mat Marcus. They adopt the using
syntax, and note the following:
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.
They also state:
Two straw polls were taken regarding syntax. A strong majority voted to avoid the typedef template syntax, in favor of the “=” syntax. A second vote indicated strong preference for the “using” keyword as opposed to a word like “alias” or the absence of any keyword as in the draft version of this proposal. The motivation for using any keyword at all stemmed partly from the desire to use a syntax that might be compatible with the non-template aliasing direction briefly outlined above.
This syntax was then adopted in the final proposal N2258 by Gabriel Dos Reis and Bjarne Stroustrup.
Here is what Bjarne Stroustrup says about why they introduced using
instead of extending typedef
:
The keyword using is used to get a linear notation "name followed by what it refers to." We tried with the conventional and convoluted typedef solution, but never managed to get a complete and coherent solution until we settled on a less obscure syntax.
He also claims that he likes this syntax also more for usual typedefs:
In addition to being important in connection with templates, type aliases can also be used as a different (and IMO better) syntax for ordinary type aliases:
using PF = void (*)(double);
He is quite correct here, this seems very clean. In contrast a typedef would be extremely convoluted with the name being somewhere in the middle:
typedef void(*PF)(double);
Here is an explanation (see page 4) from their proposal that is even more in-depth:
It has been suggested to (re)use the keyword typedef — as done in the paper [4] — to introduce template aliases:
template<class T> typedef std::vector<T,MyAllocator<T>> Vec;
That notation has the advantage of using a keyword already known to introduce a type alias. However, it also displays several disadvantages among which the confusion of using a keyword known to introduce an alias for a type-name in a context where the alias does not designate a type, but a template;
Vec
is not an alias for a type, and should not be taken for a typedef-name. The nameVec
is a name for the familystd::vector<*,MyAllocator<*>>
- where the asterisk is a placeholder for a type-name. Consequently, we do not propose the "typedef" syntax.template<class T> using Vec = std::vector<T,MyAllocator<T>>;
can be read/interpreted as: from now on, I'll be using
Vec<T>
as a synonym forstd::vector<T,MyAllocator<T>>
. With that reading, the new syntax for aliasing seems reasonably logical.
So he has basically two points here:
- A
using
template becomes a family of types, not a type, sotypedef
is "wrong" using
can be read almost as an english sentence