SFINAE,是可赎回的特质

时间:2017-10-30 23:14:32

标签: c++ c++11 sfinae

我正在尝试实施一点is_callable特性以改善mysel。但是,我正在运行一个小问题。当我尝试使用带有参数(或lambda)的仿函数时,问题就出现了。 我没弄清楚如何传递参数类型,或者如何自动推导它们......这是我的代码和结果:

#include <iostream>
#include <type_traits>
#include <cstdlib>



template<typename T, typename = void>
struct is_callable_impl : std::false_type {};

template<typename R, typename ...Args>
struct is_callable_impl<R(Args...), std::void_t <R(Args...)>> : std::true_type {};

template<typename Fn>
struct is_callable_impl < Fn, std::void_t<decltype(std::declval<Fn>()())>> : std::true_type{};

struct fonctor {
    void operator()() {}
};

struct fonctor2 {
    void operator()(double) {}
};

int fonct();
int fonct2(double);


int main() {
    auto l = [](float) {return false; };
    auto l2 = [&l] {return true; };
    std::cout << "expr" << std::endl;
    std::cout << is_callable_impl<double()>::value << std::endl; //write 1
    std::cout << is_callable_impl<int(int)>::value << std::endl; // write 1
    std::cout << is_callable_impl<void(double)>::value << std::endl;// write 1
    std::cout << is_callable_impl<void(double, int)>::value << std::endl; // write 1

    std::cout << "lambda" << std::endl;
    std::cout << is_callable_impl<decltype(l)>::value << std::endl;// write 0
    std::cout << is_callable_impl<decltype(l2)>::value << std::endl;// write 1

    std::cout << "function" << std::endl;
    std::cout << is_callable_impl<decltype(fonct)>::value << std::endl;// write 1
    std::cout << is_callable_impl<decltype(fonct2)>::value << std::endl;// write 1

    std::cout << "functors" << std::endl;
    std::cout << is_callable_impl<fonctor>::value << std::endl; // write 1
    std::cout << is_callable_impl<fonctor2>::value << std::endl; // write 0

    std::cout << "uncalled type" << std::endl;
    std::cout << is_callable_impl<int>::value << std::endl;// write 0

    system("pause");
    return 0;
}

1 个答案:

答案 0 :(得分:0)

好的,我测试了另一个想法。使用std :: is_function可以检测对象是函数还是表达式。 之后,您只需要检查operator =是否存在。但是,当函子重载了operator()函数时,我的实现不起作用。

template<typename T, typename AlwaysVoid = void>
struct is_callable_impl : std::false_type {};

template<typename F>
struct is_callable_impl < F, std::enable_if_t < std::is_function<F>{}>> // Expression and Functions
    : std::true_type {};

// Lambda and functor
template<typename F>
struct is_callable_impl < F, std::void_t<std::enable_if_t < !std::is_function<F>{} >, decltype(&F::operator())>> : std::true_type{};