einpoklum
einpoklum

Reputation: 131445

Having a template parameter depend on a parameter list

I have defined the class

template <typename... Ts> struct Bar {
   using inner_type = /* whatever */;
};

Now, I need to define a templated class Foo whose template parameters are some parameter pack, and a value of type Bar::inner_type instantiated for that parameter pack. Unfortunately I can't seem to be able to do it. If I define it this way:

template <Bar<Ts...>::inner_type SomeValue, typename... Ts> struct Foo { };

the compiler doesn't recognize Ts when it's used, since it hasn't see the parameter pack yet; but if I define it this way:

template <typename... Ts, Bar<Ts...>::inner_type SomeValue> struct Foo { };

the compiler sneers at my attempt to use a parameter pack before other template parameters.

So how can I do this?

Note: In case it matters, this failed for me with GCC 4.9.3.

Upvotes: 5

Views: 252

Answers (4)

skypjack
skypjack

Reputation: 50540

You can partially specialize your struct:

template<typename...>
struct Bar { using inner_type = int; };

template <typename T, typename T::inner_type T>
struct Foo;

template <typename... Ts, typename Bar<Ts...>::inner_type SomeValue>
struct Foo<Bar<Ts...>, SomeValue> { };

int main() {
    Foo<Bar<int>, 3> foo;
}

This way Ts parameter pack is deduced and Foo expects the second template parameter to be of type Bar<Ts...>::inner_type.

Upvotes: 2

user3721426
user3721426

Reputation: 273

If I understood your problem correctly, you can do something like this:

template <typename... Ts> struct Bar {
   using inner_type = /* whatever */;
};

template <typename... Ts> struct Foo {
   using inner_type = typename Bar<Ts...>::inner_type;
};

Upvotes: 0

bolov
bolov

Reputation: 75688

The best thing I could come up with:

template <class Inner, Inner Val, class... Args>
struct Foo {
  static_assert(std::is_same<Inner, typename Bar<Args...>::inner_type>::value, "Wrong type");
};

You need to explicitly name the type.

Upvotes: 1

Vahid
Vahid

Reputation: 312

does this solve the issue?

#include <type_traits>

using namespace std;

template <typename... Ts> class Bar {
 public:
    using inner_type = int;
};

template <typename... Ts> class Foo {
  using bar_inner_type = typename Bar<Ts...>::inner_type;
  static_assert(is_same<int, bar_inner_type>::value,"");
};

Upvotes: 0

Related Questions