Default value for template parameter, followed by non-type parameter pack

136 views Asked by At

I'm struggling to make this code work

template <typename T, typename U = int, auto... Params>
class Foo {};

int main()
{
    auto foo1 = Foo<int, int, 1, 2, 3>{};
    auto foo2 = Foo<int, 1, 2, 3>{}; // I want it to compile
}

It looks like I need some hack. I tried partial specialization, but it doesn't work either

template <typename T, typename U, auto... Params>
class Foo {};

template <typename T, auto... Params>
class Foo<T, int, Params...> {};

int main()
{
    auto foo1 = Foo<int, int, 1, 2, 3>{};
    auto foo2 = Foo<int, 1, 2, 3>{}; // I want it to compile
}

I can't find anything closely related to this, help pls :)

1

There are 1 answers

0
Sam Varshavchik On BEST ANSWER

Unfortunately due to the way that template deduction works, this is ...not going to work.

Here's one alternative approach where the first template parameter is always a tuple, with one or two types, with the second type defaulting to an int:

#include <tuple>

template<typename T, auto ...Params> class Foo;

template<typename T, typename U, auto ...Params>
class Foo< std::tuple<T, U>, Params...> {

    // Your template goes here, making use of T and U
};

template<typename T, auto ...Params>
class Foo< std::tuple<T>, Params...> : Foo<std::tuple<T, int>, Params...> {

    // Might need to define some cleanups here, like a delegating constructor,
    // and/or delegated overload operators.

};

Foo<std::tuple<char>, 3, 4> defaulted;

Foo<std::tuple<char, float>, 3, 4> non_defaulted;

With a little bit more elbow grease it should be possible to require a formal std::tuple only when the 2nd optional type needs to be specified, and just specify the primary type directly (although that will create some avoidable confusion if the primary type is a std::tuple, itself).