如何使用SFINAE的省略号工作?

时间:2016-08-08 16:22:16

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

过去使用SFINAE选择构造函数重载时,我通常使用以下内容:

template <typename T>
class Class {
public:
    template <typename U = T, typename std::enable_if<std::is_void<U>::value, int>::type=0>
    Class() {
        std::cout << "void" << std::endl;
    }

    template <typename U = T, typename std::enable_if<!std::is_void<U>::value, int>::type=0>
    Class() {
        std::cout << "not void" << std::endl;
    }
};

但是,我刚刚遇到了这个替代方案:

template <typename U = T, typename std::enable_if<std::is_void<U>::value>::type...>
Class() {
    std::cout << "void" << std::endl;
}

考虑到以下情况属于非法......

template <typename U = T, void...> // ERROR!
Class() { }

...上面使用省略号而不是非类型模板参数的替代方法如何工作?

完整代码:http://coliru.stacked-crooked.com/a/64a1aaf13ce6099b

1 个答案:

答案 0 :(得分:1)

我之前的回答是错误的。抱歉。我只是想解决它。

此声明:

template <typename U = T, void...>
Class() { }

违反[temp.res] / 8:

  

该计划是   格式错误,无需诊断,如果[...]可变参数模板的每个有效特化都需要空模板参数包

它不需要诊断,但编译器选择发出一个。无论哪种方式,代码都是不正确的。

另一方面

template <typename U = T, std::enable_if_t<std::is_void<U>::value>...>
Class() { }

不违反此要求。我们有一个空包装,所以我们不要碰到你不能使用void作为非类型模板参数的事实。此外,enable_if的假设专业化可以提供一种不void的类型,因此由于上述限制,它不会形成错误。