仅在给定n个以上参数的情况下,才能启用可变参数模板构造函数?

时间:2019-01-25 20:29:44

标签: c++ c++11 variadic-templates sfinae template-deduction

我有一个带有以下构造函数的类:

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;
};

我还想创建一个构造函数,该构造函数接受任意数量的参数(所有参数都可以是T)。构造函数也不能遮蔽我已经编写的其他构造函数,因为完成的工作是不同的。我尝试使用enable_if进行了一些尝试,但是无法使其正常工作。这是我到目前为止的内容:

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

但是,当这样调用时:

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

会产生此错误(以及其他错误):

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

因此,编译器甚至可能看不到构造函数。另一方面,如果我只省去enable_if,它将永远不会调用我的其他更专业的构造函数。

简而言之,如何使可变参量的构造函数称为当且仅当具有三个或更多给该构造函数的参数时?

编辑:

正如评论中所建议的那样,我现在也尝试了以下方法,但这也行不通:

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

以及

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

或两者的任意组合。

1 个答案:

答案 0 :(得分:1)

建议:尝试

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

或更好(以避免与具有相同签名的多个启用SFINAE的构造函数发生冲突)。

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

原始代码存在的问题

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

仅当相对参数位于最后一个位置时,您才能推断出可变的类型列表。

如果添加其他参数

typename std::enable_if<sizeof...(mArgs) >= 3>::type

您打破了TArgs...类型的推论。