Please, help me understand this "pack expansion does not contain any unexpanded parameter packs" compiler error

3.4k Views Asked by At
template<typename ...>
bool foo(std::tuple<std::string,float> bar...)
{
    std::vector<std::tuple<std::string,float>> barList(bar...);

    // ...
}

This does not seem to generate any syntax error. There is no error indicator at that line in the editor, but the compiler stops with

[bcc32c Error] Foo.cpp(117): pack expansion does not contain any unexpanded parameter packs

I tried to read online, but all examples I find either seem incomplete, or are not clear to me.

A simple answer to why this does not compile would be appreciated.

1

There are 1 best solutions below

2
On BEST ANSWER

Your syntax is wrong. Your function is equivalent with:

bool foo(int bar...)
{
    std::vector<int> barList(bar...);

    // ...
}

Notice there is no variadic templates at all, and there is nothing to unpack - instead, you have created a C-style variadic function.

One easiest way to change your function would be:

template<typename... Args>
bool foo(Args... bar)
{
    std::vector<std::tuple<std::string,float>> barList({bar...});

    // ...
}

This is not ideal, as it makes your template function quite greedy - it will gladly consume any arguments, not just tuples of strings and floats.

We can spice it up by using C++20 concepts:

template<class T>
concept Tuple = std::is_same_v<T, std::tuple<std::string, float>>;

template<Tuple... T>
bool foo(T... bar)
{
    std::vector<std::tuple<std::string, float>> barList({bar...});

    // ...
    return true;
}

This allows usage like that:

foo(std::tuple<std::string, float>{"ddd", 20}, std::tuple<std::string, float>{"ddd", 20});

But not like that:

foo(10, 20, nullptr);