In an attempt to rewrite a predicate combinator like this
auto constexpr all = [](auto const&... predicates){
return [predicates...](auto const&... x){
return (predicates(x...) && ...);
};
};
(little generalization of this) in a way that it would give meaningful errors when fed with non-predicates/predicates with different arities/arguments, I started writing something like this:
template<typename T, typename = void>
struct IsPredicate : public std::false_type {};
template<typename T>
struct IsPredicate<T, std::enable_if_t<std::is_same_v<bool, return_type_of_callable_T>, void>>
: public std::true_type {};
and then I stared at it for a while... How do I even check what is the return type of a function, if I don't even know how to call it?
I see this:
- I couldn't even pass
decltype(overloaded_predicate_function)
toIsPredicate
, because template type deduction can't occur with an overloaded name, - even if I only talk of function objects, the problem of the first bullet point could apply to
operator()
, in case it is overloaded.
So my question is: is it even possible to determine the return type of an arbitrary callable?
I'm mostly interested in a C++17 answer, but, why not?, I'd also like to know what C++20's concept offer in this respect.