2014-04-30 7 views
11

Ich muss herausfinden, ob ein Give-Typ Funktion X als eine aufrufbare Funktion mit einer bestimmten Parameterliste hat. Die Überprüfung sollte nicht kümmern über den Rückgabewert jedoch.Wie finde ich heraus, ob ein Typ eine Memberfunktion mit einem beliebigen Rückgabetyp hat?

Ich fand this solution von another Stack Overflow question, die gut zu funktionieren scheint. Was sie tut, ist dies:

#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 {}; 

Das ist genau das, was ich außer dass will bei der Prüfung Du auch den gewünschten Rückgabetyp liefern. Ich habe versucht, einen Weg zu finden, dies zu modifizieren, um zu überprüfen, ohne den Rückgabetyp zu berücksichtigen, aber ich konnte keinen Weg finden.

Weiß jemand, wie man das macht?

+0

so im Wesentlichen Sie, ob die Funktion überprüfen wollen 'Rückkehr' 'Leere 'oder nicht? – Valerij

Antwort

10

nur Ausdruck SFINAE tun und verwerfen das Ergebnis:

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

Die Überprüfung gibt auch true für konvertierbare Parameter zurück. Irgendwelche Lösungen für explizite Prüfungen? – stschindler

+0

@Tank Eine Möglichkeit, dies zu tun, ist '& T :: operator()' und die Umwandlung in die korrekte Signatur im SFINAE-Kontext, aber das bedeutet, dass Sie auch den Rückgabetyp benötigen. Aber es ist nicht das, was OP will, AFAICT. – jrok

+0

wahr, fragte sich nur, obwohl. Vielen Dank – stschindler

1

Sie könnten verwenden:

#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'; 
} 
Verwandte Themen