为什么SFINAE不起作用?

Why SFINAE doesn't work?

本文关键字:不起作用 SFINAE 为什么      更新时间:2023-10-16

我想检查类是否具有operator()。我尝试了以下sfinae。

#include <type_traits>  //for std::true_type/false_type
#include <utility>      //for std::declval
template <typename T, typename... A>
class has_call_operator {
private:
    template <typename U, typename... P>
    static auto check(U u, P... p) -> decltype(u(p...), std::true_type());
    static auto check(...) -> decltype(std::false_type());
public:
    using type
        = decltype(check(std::declval<T>(), std::declval<A>()...));
    static constexpr bool value = type::value;
};

一目了然,这正常工作。

#include <iostream>
struct test {
    void operator()(const int x) {}
};
int main()
{
    std::cout << std::boolalpha << has_call_operator<test, int>::value << std::endl;    //true
    return 0;
}

但是,抽象类未正确地工作。

#include <iostream>
struct test {
    void operator()(const int x) {}
    virtual void do_something() = 0;
};
int main()
{
    std::cout << std::boolalpha << has_call_operator<test, int>::value << std::endl;    //false
    return 0;
}

为什么此代码不起作用?另外,您可以使此代码工作吗?

您按值乘以U,因此也需要类型的构造。

通过const引用来解决该问题。

您可以看一下is_detected,并且有类似的东西:

template <typename T, typename ...Ts>
using call_operator_type = decltype(std::declval<T>()(std::declval<Ts>()...));
template <typename T, typename ... Args>
using has_call_operator = is_detected<call_operator_type, T, Args...>;