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

2

16

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!

Mosa answered 24/7, 2012 at 13:28 Comment(0)
D
12

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.

Disobedient answered 24/7, 2012 at 13:43 Comment(1)
This is incorrect. You also need the typename keyword here, because A::Sibling<...> is a dependently-scoped type name here.Burnie
B
10

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 
Burnie answered 14/7, 2013 at 6:56 Comment(1)
Flippin' GCC and its flippin' errors... LOLDahliadahlstrom

© 2022 - 2024 — McMap. All rights reserved.