How does using ellipses for SFINAE work?

空扰寡人 提交于 2021-02-20 08:59:25

问题


When using SFINAE to select constructor overloads in the past, I have typically used the following:

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

However, I just came across this alternative:

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

Considering that the following is illegal ...

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

... how does the alternative above using ellipses rather than a non-type template argument work?


Full code: http://coliru.stacked-crooked.com/a/64a1aaf13ce6099b


回答1:


My previous answer was wrong. Sorry. I'm just going to fix it.


This declaration:

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

violates [temp.res]/8:

The program is ill-formed, no diagnostic required, if [...] every valid specialization of a variadic template requires an empty template parameter pack

It's no diagnostic required, but the compiler chooses to issue one anyway. Either way, the code is ill-formed.

On the other hand

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

doesn't violate this requirement. We have an empty pack, so we don't run afoul of the fact that you can't use void as a non-type template parameter. Additionally, a hypothetical specialization of enable_if could provide a type that isn't void there so it's not ill-formed due to the above limitation.



来源:https://stackoverflow.com/questions/38834149/how-does-using-ellipses-for-sfinae-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!