2

I am trying to create an "object manager" that will create and store instances of a template class. The class takes one template argument and inherits from a base class to allow instances with different template args to be stored in the same container. The types that will be used as template arguments will be provided by the user in a variadic template function.

Below is a minimal example that illustrates the issue:

struct A
{
    int m_a = 0;
};

template<typename T>
struct B : public A
{
    int m_b = 1;
    T m_t;
};

template<typename... Types> std::vector<A*> generate_a_vec()
{
    std::vector<A*> a_vec; // <--- Need to initialize with a new B<T> for each T in "Types"
    return a_vec;
}

int main()
{
    std::vector<A*> a_vec = generate_a_vec<int, float, bool>();

    for(A* a : a_vec)
    {
       std::cout << a->m_a << std::endl;
    }

    return 0;
}

Let's assume every T we will use has a default constructor. Is there a way to use a fold expression to create a B<T> with new for each type in Types and add the resulting pointers to the vector in generate_a_vec()?

max66
  • 65,235
  • 10
  • 71
  • 111
yah_nosh
  • 155
  • 1
  • 8

1 Answers1

5

If I understand correctly what do you want, you're looking for

std::vector<A*> a_vec { new B<Types>{}... };

But this isn't "fold expression"; it's a simple variadic template pack expansion and it's available starting from C++11.

An example of "fold expression" (available from C++17) can be the following

std::vector<A*> a_vec;

( a_vec.push_back( new B<Types>{} ), ... );

where variadic template pack is folding expanded using the comma operator

max66
  • 65,235
  • 10
  • 71
  • 111
  • My example was a bit flawed, since your 1st method works for what I need to do. But let's assume I wanted to use your second method, i.e a C++17 fold expression. With MSVC I get "error C3520: 'Types': parameter pack must be expanded in this context" – yah_nosh Oct 07 '20 at 00:50
  • @yah_nosh - Maybe your MSVC is too old to support C++17? Or you have to add the option to compile C++17? Anyway, I can say that the `push_back()` version compile with both g++ (8.3.0) and clang++ (7.0.1) (both with `-std=c++17`, obviously) – max66 Oct 07 '20 at 00:55
  • My bad, forgot to add the command line argument in Godbolt. Tried it again both there and in Visual Studio, works like a charm! Going to accept, thanks again! – yah_nosh Oct 07 '20 at 01:06