2014-04-30 44 views
11

我需要找出一個給定類型是否具有函數X作爲具有給定參數列表的可調用函數。但是應該檢查而不是關心返回值。如何找出一個類型是否有任何返回類型的成員函數?

我發現this solutionanother Stack Overflow question這似乎很好。它所做的是:

#include <type_traits> 

template <typename C, typename F, typename = void> 
struct is_call_possible : public std::false_type {}; 

template <typename C, typename R, typename... A> 
struct is_call_possible<C, R(A...), 
    typename std::enable_if< 
     std::is_same<R, void>::value || 
     std::is_convertible<decltype(
      std::declval<C>().operator()(std::declval<A>()...) 
     ), R>::value 
    >::type 
> : public std::true_type {}; 

這正是我想要的,除了在檢查中還提供了所需的返回類型。我試圖找到一種方法來修改這個能夠檢查而不考慮返回類型,但我無法找出一種方法。

有誰知道如何做到這一點?

+0

所以基本上要檢查是否該函數將 '迴歸''無效'或不? – Valerij

回答

10

只是不表達SFINAE並丟棄結果:

template <typename C, typename... Args> 
struct is_call_possible { 
private: 
    template<typename T> 
    static auto check(int) 
     -> decltype(std::declval<T>().operator()(std::declval<Args>()...), 
        // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
        // overload is removed if this expression is ill-formed 
      std::true_type()); 

    template<typename> 
    static std::false_type check(...); 
public: 
    static constexpr bool value = decltype(check<C>(0))::value; 
}; 

Live example.

+0

該檢查還對可轉換參數返回true。任何明確檢查的解決方案? – stschindler

+0

@Tank一種方法是採用'&T :: operator()'並將其轉換爲SFINAE上下文中的正確簽名,但這意味着您也需要返回類型。但這不是OP想要的,AFAICT。 – jrok

+0

是真的,只是想知道。謝謝 – stschindler

1

您可以使用:

#include <iostream> 

namespace Detail { 
    struct is_callable 
    { 
     template<typename F, typename... A> 
     static decltype(std::declval<F>()(std::declval<A>()...), std::true_type()) 
     test(int); 

     template<typename F, typename... A> 
     static std::false_type 
     test(...); 
    }; 
} // namespace Detai 

template<typename F, typename... A> 
using is_callable = decltype(Detail::is_callable::test<F, A...>(0)); 

struct X { 
    int operator()(int) { return 0; } 
}; 

int main() { 
    std::cout << is_callable<X>() << '\n'; 
    std::cout << is_callable<X, int>() << '\n'; 
} 
相關問題