2014-04-30 13 views
11

Muszę się dowiedzieć, czy funkcja give ma funkcję X jako funkcję wywoływalną z podaną listą parametrów. Sprawdzenie nie powinno jednak dotyczyć wartości zwracanej przez .Jak sprawdzić, czy typ ma funkcję składową z dowolnym typem zwracanym?

Znalazłem this solution z another Stack Overflow question, który wydaje się działać dobrze. To, co robi to:

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

To jest dokładnie to, czego chcę, z wyjątkiem tego, że w czeku można również podać żądany typ zwrotu. Próbowałem znaleźć sposób, aby to zmienić, aby móc sprawdzić, nie biorąc pod uwagę typu zwrotu, ale nie mogłem wymyślić sposób.

Czy ktoś wie, jak to zrobić?

+0

więc zasadniczo chcesz sprawdzić, czy funkcja 'powrót' 'void 'czy nie? – Valerij

Odpowiedz

10

Tylko nie wyrażenie SFINAE i odrzucić wynik:

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

Kontrola zwraca także wartość true dla parametrów przekształcalnych. Wszelkie rozwiązania dotyczące wyraźnych kontroli? – stschindler

+0

@Tank Jednym ze sposobów na zrobienie tego jest wzięcie '& T :: operator()' i przesłanie do poprawnego podpisu w kontekście SFINAE, ale to oznacza, że ​​potrzebujesz również typu zwrotu. Ale nie tego chce OP, AFAICT. – jrok

+0

prawda, właśnie się zastanawiałem. Dzięki – stschindler

1

Można użyć:

#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'; 
} 
Powiązane problemy