Clearly, type aliases and templated type aliases are semantically equivalent to typedefs and an extension of typedefs to support template. How come new syntax with the using
keyword was created for these instead of using typedefs for the first and some syntax extension with the word typedef
.
NOTE: This is not a clone of the "difference between using and typedef" question. I know that using
gives the advantage of defining a family of typedef
s. What I am asking is why did the standard people decide on having this extension use the using
keyword instead of the typedef
keyword. This seems like it just adds confusion in the language.
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 name Vec
is a name for the family std::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 Vect<T>
as a synonym for std::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, so typedef
is "wrong"
using
can be read almost as an english sentence