如何使用椭圆的SFINAE工作

How does using ellipses for SFINAE work?

本文关键字:SFINAE 工作 何使用      更新时间:2023-10-16

在过去使用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

我之前的答案是错误的。对不起。我要把它修好。


这宣言:

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

违反(temp.res)/8:

程序是格式错误,不需要诊断,如果[…]可变变量模板的每个有效的特化都需要一个空的模板形参pack

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

另一方面

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

不违反这个要求。我们有一个空包,所以我们不会遇到不能使用void作为非类型模板参数的事实。此外,enable_if的假设专门化可以提供一个不是void的类型,因此由于上述限制,它不会是病态的。