0

I am aware of the most obvious differences; ie. that using allows you to specify a new name for the type being introduced, but what is the difference between the following two statements:

template <typename T>
class Derived : public X<T>
{
  using Base = X<T>;
  using Type = typename Base::Type; // statement 1
  using typename Base::Type; // statement 2
};

I've noticed that sometimes statement two doesn't work as expected. For example, I might get an error like "error: no member named 'Type' in X".

So how do these statements differ?

quant
  • 21,507
  • 32
  • 115
  • 211
  • possible duplicate of [Where and why do I have to put the "template" and "typename" keywords?](http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords) – Pradhan Feb 15 '15 at 21:24
  • @Pradhan I don't see how these are related. – quant Feb 15 '15 at 21:27
  • It makes no sense to use `typename` outside the declaration or definition of a template. In such a context, the answer pointed to shows you how and why it should be used. – Pradhan Feb 15 '15 at 21:29
  • I realise that the title might have attracted drive-by close requests, so I've changed it. **Please read the question before close-voting**. – quant Feb 15 '15 at 21:29
  • Retracted close-vote. – Pradhan Feb 15 '15 at 21:33
  • @Pradhan Thanks. Also, I've edited the code to clarify why I'm using the `template` keyword in my code. – quant Feb 15 '15 at 21:33

2 Answers2

4

using T1 = T2; is new (as of C++11) syntax that provides an alternative to typedef. using Type = typename X::Type; means exactly the same thing as typedef typename X::Type Type;.

using typename X::Type; is older syntax, specifically intended for inheriting members from base classes. Normally, the typename would be redundant, normally you would be able to write using X::Type; instead, but in the case of template base classes, you may need typename to prevent X::Type from being parsed as a non-type member.

An example where they differ is

struct A {
  typedef int i;
};

struct B {
  using i = typename A::i; // valid
  using typename A::i; // invalid, A is not a base class of B
};
1

The first form introduces a new name for a type, it's alternative syntax for typedef.

The second form redeclares a name for use in the current scope. i.e. it makes a name from another scope usable in the current scope qualifying it, e.g. using std::swap means you can just say swap instead of std::swap.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521