Commit 8e13f34b authored by Dominik Charousset's avatar Dominik Charousset

Cleanup type traits

parent 281f478b
...@@ -56,6 +56,7 @@ using enable_if_t = typename std::enable_if<V, T>::type; ...@@ -56,6 +56,7 @@ using enable_if_t = typename std::enable_if<V, T>::type;
template <class Trait, class T = void> template <class Trait, class T = void>
using enable_if_tt = typename std::enable_if<Trait::value, T>::type; using enable_if_tt = typename std::enable_if<Trait::value, T>::type;
/// Checks whether `T` is inspectable by `Inspector`.
template <class Inspector, class T> template <class Inspector, class T>
class is_inspectable { class is_inspectable {
private: private:
...@@ -71,6 +72,7 @@ public: ...@@ -71,6 +72,7 @@ public:
static constexpr bool value = !std::is_same<result_type, std::false_type>::value; static constexpr bool value = !std::is_same<result_type, std::false_type>::value;
}; };
/// Checks whether `T` defines a free function `to_string`.
template <class T> template <class T>
class has_to_string { class has_to_string {
private: private:
...@@ -396,88 +398,83 @@ struct is_mutable_ref<T&> : std::true_type { }; ...@@ -396,88 +398,83 @@ struct is_mutable_ref<T&> : std::true_type { };
template <class Functor> template <class Functor>
struct callable_trait; struct callable_trait;
// member const function pointer // good ol' function
template <class C, typename Result, class... Ts> template <class R, class... Ts>
struct callable_trait<Result (C::*)(Ts...) const> { struct callable_trait<R (Ts...)> {
using result_type = Result; using result_type = R;
using arg_types = type_list<Ts...>; using arg_types = type_list<Ts...>;
using fun_type = std::function<Result(Ts...)>; using fun_sig = R (Ts...);
using fun_type = std::function<R (Ts...)>;
}; };
// member function pointer // member const function pointer
template <class C, typename Result, class... Ts> template <class C, typename R, class... Ts>
struct callable_trait<Result (C::*)(Ts...)> { struct callable_trait<R (C::*)(Ts...) const> : callable_trait<R (Ts...)> {};
using result_type = Result;
using arg_types = type_list<Ts...>;
using fun_type = std::function<Result(Ts...)>;
};
// good ol' function // member function pointer
template <class Result, class... Ts> template <class C, typename R, class... Ts>
struct callable_trait<Result(Ts...)> { struct callable_trait<R (C::*)(Ts...)> : callable_trait<R (Ts...)> {};
using result_type = Result;
using arg_types = type_list<Ts...>;
using fun_type = std::function<Result(Ts...)>;
};
// good ol' function pointer // good ol' function pointer
template <class Result, class... Ts> template <class R, class... Ts>
struct callable_trait<Result (*)(Ts...)> { struct callable_trait<R (*)(Ts...)> : callable_trait<R (Ts...)> {};
using result_type = Result;
using arg_types = type_list<Ts...>; template <class T>
using fun_type = std::function<Result(Ts...)>; struct has_apply_operator {
template <class U>
static auto sfinae(U*) -> decltype(&U::operator(), std::true_type());
template <class U>
static auto sfinae(...) -> std::false_type;
using type = decltype(sfinae<T>(nullptr));
static constexpr bool value = type::value;
}; };
// matches (IsFun || IsMemberFun) // matches (IsFun || IsMemberFun)
template <bool IsFun, bool IsMemberFun, typename T> template <class T,
bool IsFun = std::is_function<T>::value
|| std::is_function<
typename std::remove_pointer<T>::type
>::value
|| std::is_member_function_pointer<T>::value,
bool HasApplyOp = has_apply_operator<T>::value>
struct get_callable_trait_helper { struct get_callable_trait_helper {
using type = callable_trait<T>; using type = callable_trait<T>;
using result_type = typename type::result_type;
using arg_types = typename type::arg_types;
using fun_type = typename type::fun_type;
using fun_sig = typename type::fun_sig;
static constexpr size_t num_args = tl_size<arg_types>::value;
}; };
// assume functor providing operator() // assume functor providing operator()
template <class C> template <class T>
struct get_callable_trait_helper<false, false, C> { struct get_callable_trait_helper<T, false, true> {
using type = callable_trait<decltype(&C::operator())>; using type = callable_trait<decltype(&T::operator())>;
};
/// Gets a callable trait for `T,` where `T` is a functor type,
/// i.e., a function, member function, or a class providing
/// the call operator.
template <class T>
struct get_callable_trait {
// type without cv qualifiers
using bare_type = decay_t<T>;
// if T is a function pointer, this type identifies the function
using signature_type = typename std::remove_pointer<bare_type>::type;
using type =
typename get_callable_trait_helper<
std::is_function<bare_type>::value
|| std::is_function<signature_type>::value,
std::is_member_function_pointer<bare_type>::value,
bare_type
>::type;
using result_type = typename type::result_type; using result_type = typename type::result_type;
using arg_types = typename type::arg_types; using arg_types = typename type::arg_types;
using fun_type = typename type::fun_type; using fun_type = typename type::fun_type;
using fun_sig = typename type::fun_sig;
static constexpr size_t num_args = tl_size<arg_types>::value; static constexpr size_t num_args = tl_size<arg_types>::value;
}; };
template <class T>
struct get_callable_trait_helper<T, false, false> {};
/// Gets a callable trait for `T,` where `T` is a function object type,
/// i.e., a function, member function, or a class providing
/// the call operator.
template <class T>
struct get_callable_trait : get_callable_trait_helper<decay_t<T>> {};
/// Checks wheter `T` is a function or member function. /// Checks wheter `T` is a function or member function.
template <class T> template <class T>
struct is_callable { struct is_callable {
template <class C> template <class C>
static bool _fun(C*, typename callable_trait<C>::result_type* = nullptr) { static bool _fun(C*, typename get_callable_trait<C>::type* = nullptr);
return true;
}
template <class C>
static bool
_fun(C*,
typename callable_trait<decltype(&C::operator())>::result_type* = 0) {
return true;
}
static void _fun(void*) { } static void _fun(void*);
using result_type = decltype(_fun(static_cast<decay_t<T>*>(nullptr))); using result_type = decltype(_fun(static_cast<decay_t<T>*>(nullptr)));
...@@ -485,12 +482,6 @@ public: ...@@ -485,12 +482,6 @@ public:
static constexpr bool value = std::is_same<bool, result_type>::value; static constexpr bool value = std::is_same<bool, result_type>::value;
}; };
/// Checks wheter each `T` in `Ts` is a function or member function.
template <class... Ts>
struct all_callable {
static constexpr bool value = conjunction<is_callable<Ts>::value...>::value;
};
/// Checks wheter `F` takes mutable references. /// Checks wheter `F` takes mutable references.
/// ///
/// A manipulator is a functor that manipulates its arguments via /// A manipulator is a functor that manipulates its arguments via
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment