8

I have the following problem:

#include <vector>
#include <tuple>

using namespace std;

template< size_t... N_i, typename Ts... >
class A
{
  // ...

  private:
    std::vector<size_t> _v = { N_i... };
    std::tuple<Ts...> _t;
};

int main()
{
  A<1> a;
}

As you can see above, I try to define multiple parameter packs as template arguments of the class A.
Unfortunately, the code does not compile:

error: expected nested-name-specifier before 'Ts'

How can I define multiple parameter packs for this example?

skypjack
  • 49,335
  • 19
  • 95
  • 187
abraham_hilbert
  • 2,221
  • 1
  • 13
  • 30
  • Why do you want to give the contents of the vector as template parameters instead of an argument to the constructor? – Anedar Oct 14 '16 at 21:12
  • You have a syntax error, it should be `template< size_t... N_i, typename... Ts >`. But then you have the multiple parameter pack problem... – rodrigo Oct 14 '16 at 21:21
  • @Brian Duplicate is pretty different from this question. Here the problem is that packs cannot be deduced. Duplicate has problems while defining a context to have them deduced. – skypjack Oct 14 '16 at 22:07
  • skypjack: isn't it required that nontype template parameters must go after the type template parameters? – Chris Beck Oct 14 '16 at 23:44
  • edit: I think i'm confused, I was remembering this question: http://stackoverflow.com/questions/32104890/why-is-initialization-of-a-constant-dependent-type-in-a-template-parameter-list – Chris Beck Oct 14 '16 at 23:45

2 Answers2

9

One way to achieve the end goal is by a using a nested template:

template< size_t... N_i> class initial_values {

public:

    template <typename Ts...>
    class A
    {
       // ...

       private:
         std::vector<size_t> _v = { N_i... };
         std::tuple<Ts...> _t;
    };
};

Then the template can be referenced as, for example:

initial_values<1,2,3>::A<int, char> a;
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
6

Consider the error:

expected nested-name-specifier before 'Ts'

It is due to the fact that you wrote:

template< size_t... N_i, typename Ts... >

Instead of:

template< size_t... N_i, typename... Ts >

That said, even if you fix it, code won't compile.
This is because you can't mix two parameters packs the way you did.
You must refactor your code so as they can be deduced from the context somehow.

As an example, you can use std::index_sequence and a partial specialization as it follows:

#include <vector>
#include <tuple>
#include<functional>

using namespace std;

template< typename... >
class A;

template< size_t... N_i, typename... Ts >
class A<index_sequence<N_i...>, Ts...>
{
  // ...

  private:
    std::vector<size_t> _v = { N_i... };
    std::tuple<Ts...> _t;
};

int main()
{
  A<index_sequence<1>> a;
}
skypjack
  • 49,335
  • 19
  • 95
  • 187
  • It sounds like 'mixing two parameter packs' might be OK in some cases. IMHO, they could easily be deduced here, because of the obvious size_t vs general types. Probably such a fringe case that no compiler writer ever cared – non-user38741 Apr 06 '20 at 18:40