Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 `using` keyword: specialize template alias of template parameter

I had a problem today using the using keyword in C++11. I decided to use another approach now (added as comments in the example below). You can think of X as a matrix, of Y as a mixin and the aim is to access the tranposed matrix type of X in Y. Instead of typedefing X<B,A> in X<A,B>, we take another approach that is more powerful and define a Sibling alias that takes two template parameters itself.

template <class A, class B>
struct X
{
  using Left = A;
  using Right = B;
  template <class T1, class T2>
  using Sibling = X<T1, T2>;
  // using Reversed = X<B, A>; // What I really want and use now. :-)
};

template <class A>
struct Y
{
  using Left = typename A::Left;
  using Right = typename A::Right;
  using AReverse = typename A::Sibling<Right, Left>; // Gives a compiler error
  // using AReverse2 = typename A::Reversed; // Works, of course.
};

using Z = X<int,double>::Sibling<double,int>; // Works

I tried compiling the code above with g++-4.7 -std=c++11 -c and it shows me the following error message:

t.cpp:16:9: error: expected nested-name-specifier before ‘AReverse’
t.cpp:16:9: error: using-declaration for non-member at class scope
t.cpp:16:18: error: expected ‘;’ before ‘=’ token
t.cpp:16:18: error: expected unqualified-id before ‘=’ token

I do not understand why a get an error message at all or how I could fix it. Could someone explain to me what the problem is?

Thanks alot!

like image 447
Markus Mayr Avatar asked Jul 24 '12 13:07

Markus Mayr


2 Answers

You need to drop the typename and use ::template instead:

using AReverse = A::template Sibling<Right, Left>;

The identifier to the right of :: in this case (Sibling) is not a type, it's a template, and that's why this disambiguator is needed instead of typename.

like image 147
R. Martinho Fernandes Avatar answered Oct 25 '22 12:10

R. Martinho Fernandes


Here's what Clang says:

<stdin>:16:32: error: use 'template' keyword to treat 'Sibling' as a dependent template name
  using AReverse = typename A::Sibling<Right, Left>; // Gives a compiler error
                               ^
                               template 
like image 21
Richard Smith Avatar answered Oct 25 '22 12:10

Richard Smith