2014-04-30 4 views
11

मुझे यह पता लगाने की आवश्यकता है कि किसी दिए गए पैरामीटर सूची के साथ एक कॉल प्रकार को कॉल करने योग्य फ़ंक्शन के रूप में एक्स को फ़ंक्शन किया गया है या नहीं। चेक हालांकि वापसी मूल्य के बारे में परवाह करना चाहिए।कैसे पता लगाएं कि किसी प्रकार के पास किसी रिटर्न प्रकार के साथ सदस्य फ़ंक्शन है या नहीं?

मुझे another 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

चेक परिवर्तनीय मानकों के लिए भी सच है। स्पष्ट जांच के लिए कोई समाधान? – stschindler

+0

@Tank ऐसा करने का एक तरीका है '& T :: ऑपरेटर()' और SFINAE संदर्भ में सही हस्ताक्षर पर डालना है, लेकिन इसका मतलब है कि आपको रिटर्न प्रकार की भी आवश्यकता है। लेकिन यह नहीं है कि ओपी क्या चाहता है, 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'; 
} 
संबंधित मुद्दे