Как узнать, имеет ли тип функцию-член с любым типом возврата?
Мне нужно выяснить, имеет ли тип выдачи функцию X как вызываемую функцию с заданным списком параметров. Однако проверка не должна касаться возвращаемого значения.
Я нашел это решение из другого вопроса о переполнении стека, который, кажется, работает Что ж. Что он делает, так это:
#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 {};
Это именно то, что я хочу, кроме того, что в чеке вы также указываете желаемый тип возвращаемого значения. Я пытался найти способ изменить это, чтобы иметь возможность проверять, не принимая во внимание тип возврата, но я не мог понять способ.
Кто-нибудь знает, как это сделать?
Ответы
Ответ 1
Просто выполните выражение 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;
};
Живой пример.
Ответ 2
Вы можете использовать:
#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';
}