2

There's a new syntax in C++11 for creating a type alias, using. It can be used, where typedef is used, and can be templated. The explanation which favors using, goes like this:

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.

However, I don't get it. We use templates for classes, functions, and we don't have a separate keyword for them. Then why do we have a separate keyword for typedef?

I.e.:

class Foo {
};

template <typename>
class Bar {
};

We use class for both Foo and Bar, and Foo is an actual class, but Bar is a template, a "collection" of classes.

Can someone shed some light on this?

moooeeeep
  • 31,622
  • 22
  • 98
  • 187
geza
  • 28,403
  • 6
  • 61
  • 135
  • 3
    I feel it's heavily opinion based. And probably doesn't have a satisfactory answer. For one thing, `using` syntax feels more natural (at least to some). But except for that I dunno. Maybe someone has enough inside to provide a technical reasoning... or confirm there is none. – luk32 Oct 30 '17 at 13:46
  • Yes, barring concrete technical reasons against it, the answer would simply be 'because the Committee said so'. `using` is more consistent syntactically: this way, you always write `template <[args]> [category: class | using | function | etc.] [identifier] [definition]` – underscore_d Oct 30 '17 at 13:48
  • What about the explanations in the thread you linked don't you get? Right now your question appears redundant to me (this is not intended as an insult, merely my lack of seeing what's different here, so help me out :-) ) – AndyG Oct 30 '17 at 13:51
  • @underscore_d That pattern doesn't apply to functions. You don't write `template function foo = T (T x) { return x + 1; }`, so I don't see why it couldn't be extended to `typedef` in the same way. – melpomene Oct 30 '17 at 13:53
  • @AndyG: please read again my question. I'm not asking the reason behind `using`. And asking about the explanation of it, whether it is well-established. There's nothing written about this in the linked answer. – geza Oct 30 '17 at 13:56

1 Answers1

2

aside the (IMO) much greater readability argument, alias templates are not just aliases ( as typedef's are, you cannot distinguish typedefs from their aliased types in any way ): they truly represent a family of types, for example, you can write:

template<class T>
using foo = ...;
template<template<typename> class TT> void bar();
bar<foo>();

so foo is not just an alias, it's a different beast; having used typedef could have been confusing then... I think this is what it's meant by "Vec is not an alias for a type, and should not be taken for a typedef-name".

Massimiliano Janes
  • 5,524
  • 1
  • 10
  • 22
  • Why would it be confusing? Why using `class` for both types and templates is *not* confusing? Same principle. They could have added templated typedef's, as Herb proposed them. What is confusing about templated typedefs (if they have chosen this way...), which is not confusing abot templated classes? – geza Oct 30 '17 at 13:59
  • @geza, it's not the same principle; class declares a *new* type, template<> class declares a *new* family of type VS typename declares an *alias* of a types, template<>using declares a *new* family of type aliases; as said above, typedef introduces just a new name, template<>using introduces a new entity – Massimiliano Janes Oct 30 '17 at 14:01
  • Hmm. `class` declares a new type, `template<> class` declares a new family of type VS `typedef` declares an alias of a type, `template<> typedef` declares a new family of type aliases. This seems the same principle to me (if this would be the reality). – geza Oct 30 '17 at 14:03
  • `foo` is not just an alias, but we could theoretically have made `template typedef ... foo2;` valid by making `foo2` just an alias; i.e. `bar` would be invalid under this implementation. This would be similar to parametrized `type` in Haskell. – melpomene Oct 30 '17 at 14:09
  • 3
    @geza, in other words, given a template<>typedef and the usual typedef semantics, would you expect the bar() call above to compile ? – Massimiliano Janes Oct 30 '17 at 14:11
  • Ah, now I see what you mean! Sorry I wasn't careful enough. Thanks for the answer! – geza Oct 30 '17 at 14:13