In C ++ 11, the using keyword when used for type alias identical to typedef .
7.1.3.2
The typedef name can also be entered using the alias declaration. the identifier after the using keyword becomes typedef-name and the optional qualifier-seq attribute following the identifier. to this 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 will not appear in the type identifier.
Bjarne Stroustrup gives a practical example:
typedef void (*PFD)(double);
Pre-C ++ 11, the using keyword can introduce member functions into scope. In C ++ 11, you can do this for designers (another example of Bjarne Stroustrup):
class Derived : public Base { public: using Base::f;
Ben Voight provides a pretty good reason to justify that you are not introducing a new keyword or new syntax. The standard wants to avoid breaking as much old code as possible. That is why in the proposal documents you will see sections such as Impact on the Standard , Design decisions and how they can affect the old code. There are situations when a proposal seems to be a really good idea, but it may not have traction, because it would be too difficult to implement, too confusing, or contradict old codes.
Here is an old article from 2003 n1449 . The rationale seems to be related to patterns. Warning: there may be typos due to copying from PDF.
First, consider an example of a toy:
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;
The main problem with this idiom, and the main motivating fact for this proposal, is that the idiom makes the template options appear in an un-deducible context. That is, it will be impossible to call the foo function below without explicitly specifying the Arguments pattern.
template <typename T> void foo (Vec<T>::type&);
So the syntax is somewhat ugly. We would prefer to avoid nested ::type Wed prefers something like the following:
template <typename T> using Vec = MyVector<T, MyAlloc<T> >;
Note that we specifically avoid the term “typedef pattern” and intr oduce a new syntax involving the pair “using” and “=” to avoid confusion: we do not define any types here, we enter a synonym (i.e. an alias ) to abstract the type identifier (i.e. type expression) using template parameters. If the template parameters are used in the displayed contexts in the type expression, then the template alias is used to generate the template identifier, the values can be determined by the corresponding template parameters - more on this will follow. In any case, it is now possible to write general functions that work on Vec<T> in the displayed context, and the syntax has also improved. For example, we could rewrite foo as:
template <typename T> void foo (Vec<T>&);
We emphasize here that one of the main reasons for suggesting template aliases was such that the argument output and the call to foo(p) would succeed.
The following article n1489 explains why using instead of using typedef :
It was suggested (repeatedly) to use the typedef keyword - as was done in [4] - to introduce template aliases:
template<class T> typedef std::vector<T, MyAllocator<T> > Vec;
This notation has the advantage of using a keyword that is already known to enter a type alias. However, it also displays several drawbacks, including the confusion of using a keyword known to enter an alias for a type name in a context where the alias is not a type but a pattern; Vec not an alias for type and should not be accepted for typedef-name. The name Vec is the name for the family std::vector< [bullet] , MyAllocator< [bullet] > > - where the bullet is a placeholder for the type name. Therefore, we do not suggest typedef syntax. On the other hand, the proposal
template<class T> using Vec = std::vector<T, MyAllocator<T> >;
can be read / interpreted as: from now on Ill will use Vec<T> as a synonym for std::vector<T, MyAllocator<T> > . With this reading, the new syntax for aliases seems quite logical.
I think that an important distinction is made here, aliases instead of types. Another quote from the same document:
An alias declaration is a declaration, not a definition. The alias declaration introduces the name into the declarative region as an alias for the type indicated on the right side of the declaration. The core of this proposal concerns type alias names, but it is obvious that the notation can be generalized to provide an alternative spelling of the namespace or change the names of overloaded functions (see ✁ 2.3 for further discussion). [ My note. This section discusses how this syntax might look and why it is not part of the sentence. ] It may be noted that a grammar alias declaration is valid wherever a typedef declaration or namespace alias definition is used.
Summary for the using role:
- template aliases (or generic typedefs, the former is preferable).
- namespace aliases (i.e.
namespace PO = boost::program_options and using PO = ... equivalent) - The document states
A typedef declaration can be viewed as a special case of non-template alias-declaration . This is an aesthetic change and in this case is considered identical. - introduces something into scope (e.g.
namespace std in global scope), member functions inheriting constructors
It cannot be used for:
int i; using r = i;
Instead, run:
using r = decltype(i);
Overload set naming.
// bring cos into scope using std::cos; // invalid syntax using std::cos(double); // not allowed, instead use Bjarne Stroustrup function pointer alias example using test = std::cos(double);