Considering the following custom definition:
A functor is a (possibly final) (possibly union) class with a publicly overloaded
operator()
.
How to define a type trait:
template <class T>
struct is_functor {
static constexpr bool value = /* something */
};
template <class T>
inline constexpr bool is_functor_v = is_functor<T>::value;
that evalues to true
when T
is such a functor, and false
otherwise, in standard C++17
?
Here is an attempt (non-working counter examples are welcome)
struct _argument {
template <class T> constexpr operator T&() const& noexcept;
template <class T> constexpr operator T&&() const&& noexcept;
};
template <class F, class Args = std::tuple<>, std::size_t N = 128, class = void>
struct _min_arity {};
template <class F, template <class...> class T, class... Args, std::size_t N>
struct _min_arity<F, T<Args...>, N, std::enable_if_t<sizeof...(Args) <= N>>
: std::conditional_t<
std::is_invocable_v<F, Args...>,
std::integral_constant<std::size_t, sizeof...(Args)>,
_min_arity<F, std::tuple<Args..., _argument>, N>
> {};
template <class F, class = void, class = void>
struct _has_function_call_operator
: std::false_type
{};
template <class F>
struct _has_function_call_operator<
F,
std::enable_if_t<std::is_class_v<F> || std::is_union_v<F>>,
std::void_t<decltype(_min_arity<F>::value)>
>
: std::true_type
{};
template <class T>
struct is_functor
: std::bool_constant<_has_function_call_operator<T>::value>
{};