vendredi 25 janvier 2019

How do I enable_if a variadic template constructor only if more than n arguments are given?

I have a class with the following constructors:

template<typename T>
class MyClass {
public:
    MyClass() = default;
    explicit MyClass(T val) : value_1(val) { /* ... */ }
    explicit MyClass(T val, T val2) : value_1(val), value_2(val2) { /* ... */}

private:
    T value_1 = 0;
    T value_2 = 0;
};

I also want to create a constructor that takes an arbitrary number of arguments (all of which can be T's). The constructor also mustn't shadow the other constructors I already wrote, as the work done is different. I tried around with enable_if a little bit, but am unable to get this to work. Here is what I have so far:

template<typename... TArgs>
explicit MyClass(TArgs... mArgs, typename std::enable_if<sizeof...(mArgs) >= 3>) { /* ... */ }

However, when called like this:

MyClass<double>(2, 3, 4, 5, 6, 7);

it yields this error (among others):

error: no matching function for call to 'MyClass<double>::MyClass(int, int, int, int, int, int)'

So the compiler probably doesn't even see the constructor. On the other hand if I just leave out the enable_if, it will never call my other, more specialized constructors.

In short, how do I make it so the variadic constructor is called if and only if there are three or more arguments given to the constructor?

EDIT:

As proposed in the comments, I have now also tried the following, which also does not work:

template<typename... TArgs>
explicit MyClass(TArgs... mArgs, typename std::enable_if<sizeof...(mArgs) >= 3>::type) { /* ... */ }

as well as

template<typename... TArgs>
explicit MyClass(TArgs... mArgs, typename std::enable_if<sizeof...(mArgs) >= 3>* = nullptr) { /* ... */ }

or any combination of the two.

Aucun commentaire:

Enregistrer un commentaire