What was the issue solved by the new "using" syntax for template typedefs? [duplicate]
Asked Answered
P

4

16

In C++11 you can create a "type alias" by doing something like

template <typename T>
using stringpair = std::pair<std::string, T>;

But this is a deviation from what you'd expect a template typedef would look like:

template <typename T>
typedef std::pair<std::string, T> stringpair;

So this raises the question - why did they need to come up with a new syntax? what was it that did not work with the old typedef syntax?

I realize the last bit doesn't compile but why can't it be made to compile?

Pelagianism answered 17/10, 2013 at 22:26 Comment(4)
It might be that the new syntax is more readable in that the name is separate from the type, separated by an =. Not to mention putting the alias, followed by the existing type seems to not work backwards in my brain like typedef does.Perceptible
I still think it was a case of "we hate typedef but used it for historical reasons; however, now that we're adding new functionality, we have an opportunity to stray."Tompion
@TemplateRex, what is "templastes"?Lancelle
@Lancelle typo, fixed!Moisten
M
9

From the WG21 proposal N1489 Template aliases (by Stroustrup and Dos Reis):

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 disavantages 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<o, MyAllocator<o> > where the bullet is a placeholder for a type-name. Consequently we do not propose the typedef syntax.

On the other hand the sentence

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 for std::vector<T, MyAllocator<T> >. With that reading, the new syntax for aliasing seems reasonably logical.

The paper [4] referred to in the above quote was a prior proposal WG21 N1406 Proposed Addition to C++: Typedef Templates (by Herb Sutter). It uses both a different syntax (typedef vs using) as well as a different nomenclature (typedef templates vs template aliases). Herb's proposed syntax didn't make it, but the nomenclature can sometimes be found in informal discussions.

Moisten answered 18/10, 2013 at 7:50 Comment(1)
Although a bit pedantic in the interpretation I think there is a very straight-forward argument in here: A typedef for a template wouldn't define a type, but a template.Expert
E
18

I'll just refer to stroustrup himself:

http://www.stroustrup.com/C++11FAQ.html#template-alias

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.

Expert answered 17/10, 2013 at 22:33 Comment(7)
typedefs IMO suck to read since there is no delimiter between the original type and the aliasPalliative
@Expert What I'm interested to know is what they supposedly tried and how it failed. This was the only reference I could find that seem to address the question but it basically says - trust me, it's bad. I want to know what are the crucial flaws.Pelagianism
@shoosh: typedef is already described by an existing grammar. Have a go yourself and formalizing how you'd add templatization to the language and see how far you get.Rejoinder
@KerrekSB: but unless shoosh is as smart as Stroustrup, that's not going to work. It will produce reasons why shoosh can't do it, but probably not the reasons that Stroustrup couldn't do it (especially given that Stroustrup's problems were apparently so complex that nobody here can articulate them).Hussey
Or they were not practical problems, which seems more likely to me.Tompion
@LightnessRacesinOrbit for some historical background, see my answer.Moisten
@TemplateRex: Excellent :)Tompion
M
9

From the WG21 proposal N1489 Template aliases (by Stroustrup and Dos Reis):

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 disavantages 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<o, MyAllocator<o> > where the bullet is a placeholder for a type-name. Consequently we do not propose the typedef syntax.

On the other hand the sentence

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 for std::vector<T, MyAllocator<T> >. With that reading, the new syntax for aliasing seems reasonably logical.

The paper [4] referred to in the above quote was a prior proposal WG21 N1406 Proposed Addition to C++: Typedef Templates (by Herb Sutter). It uses both a different syntax (typedef vs using) as well as a different nomenclature (typedef templates vs template aliases). Herb's proposed syntax didn't make it, but the nomenclature can sometimes be found in informal discussions.

Moisten answered 18/10, 2013 at 7:50 Comment(1)
Although a bit pedantic in the interpretation I think there is a very straight-forward argument in here: A typedef for a template wouldn't define a type, but a template.Expert
T
0

(tl;dr: using supports templates, whereas typedef does not.)


As it sounds like you know already, the difference between the two examples without templates is nothing:

[C++11: 7.1.3/2]: A typedef-name can also be introduced by an alias-declaration. The identifier following the using keyword becomes a typedef-name and the optional attribute-specifier-seq following the identifier appertains to that typedef-name. It has the same semantics as if it were introduced by the typedef specifier. In particular, it does not define a new type and it shall not appear in the type-id.

However, template typedefs do not exist!

[C++11: 14.5.7/1]: A template-declaration in which the declaration is an alias-declaration (Clause 7) declares the identifier to be a alias template. An alias template is a name for a family of types. The name of the alias template is a template-name.

Why didn't they simply re-use typedef syntax? Well, I think typedef is simply the "old" style and, given the use of using in other contexts, it was decided that new functionality should take the using form for consistency.

Tompion answered 17/10, 2013 at 22:32 Comment(2)
This does nothing to actually answer the question asked. Read the question.Pelagianism
@shoosh: Yes, it does. Not very well, but it does. You're welcome.Tompion
E
0

One more reason for the new syntax - typedefs for functions, arrays and similar constructs become a bit more comprehensible.

Reference to array before / after:

typedef int(&my_type)[3];
using my_type = int(&)[3];

Array of function pointers before / after:

typedef void(*my_type[3])();
using my_type = void(*[3])();
Embow answered 17/10, 2013 at 23:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.