2017-03-09 32 views
1

我想檢查該類是否有operator()。 我試了下面的SFINAE。爲什麼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; 
} 

爲什麼不能使用此代碼? 另外,你可以使這個代碼工作?

回答

2

您按價值獲得U,所以它也需要構造類型。

通過const引用來修復該問題。

你可以看看is_detected和有類似:

typename <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...>;