Skip to content

File interface_traits.hpp

File List > backends > cxx > include > zmbt > core > interface_traits.hpp

Go to the documentation of this file

#ifndef ZMBT_CORE_INTERFACE_TRAITS_HPP_
#define ZMBT_CORE_INTERFACE_TRAITS_HPP_

#include <functional>
#include <tuple>
#include <type_traits>

#include "aliases.hpp"
#include "generic_traits.hpp"



namespace zmbt {



// PREDICATES

template<class T, class D = decay_t<T>>
using ifc_is_pmf_handle = is_member_function_pointer<D>;

template<class T, class D = decay_t<T>>
using ifc_is_pmd_handle = is_member_object_pointer<D>;

template<class T, class D = decay_t<T>>
using ifc_is_member_handle = is_member_pointer<D>;

template<class T, class D = decay_t<T>>
using ifc_is_fn_ref = mp_all<
    is_lvalue_reference<T>,
    is_function<remove_pointer_t<D>>
>;

template<class T, class D = decay_t<T>>
using ifc_is_fn_ptr = mp_all<
    is_pointer<T>,
    is_function<remove_pointer_t<D>>
>;

template<class T>
using ifc_is_fn_handle = mp_any<
    ifc_is_fn_ref<T>, ifc_is_fn_ptr<T>
>;


namespace detail {
template<class T, class=void>
struct support_calltraits_function : mp_false {};

template<class T>
struct support_calltraits_function<T, void_t<ct::function_type_t<T>>> : mp_true {};
}




template<class T, class P = remove_reference_t<T>, class D = remove_pointer_t<P>>
using ifc_is_functor_ptr = mp_all<
    is_pointer<P>, is_class<D>,
    detail::support_calltraits_function<D>
>;

template<class T, class D = remove_reference_t<T>>
using ifc_is_functor_ref = mp_all<
    is_reference<T>, is_class<D>,
    detail::support_calltraits_function<D>
>;

template <class T>
using ifc_is_functor_handle = mp_any<
    ifc_is_functor_ptr<T>,
    ifc_is_functor_ref<T>
>;


template<class T>
using is_ifc_handle = mp_any<
    ifc_is_pmf_handle<T>,
    ifc_is_pmd_handle<T>,
    ifc_is_fn_handle<T>,
    ifc_is_functor_handle<T>
>;



template <class T, class R = decay_t<T>>
auto get_ifc_pointer (T  x) -> first_if_t<R,
    ifc_is_member_handle<T>
>
{
    return x;
}

template <class T, class R = decay_t<T>>
auto get_ifc_pointer (T x) -> first_if_t<R,
    ifc_is_fn_handle<T>
>
{
    return x;
}

template <class T, class R = add_pointer_t<remove_reference_t<T>>>
auto get_ifc_pointer (T*  x) -> first_if_t<R,
    ifc_is_functor_ptr<T*>
>
{
    return x;
}

template <class T, class R = add_pointer_t<remove_reference_t<T>>>
auto get_ifc_pointer (T&  x) -> first_if_t<R,
    ifc_is_functor_ref<T&>
>
{
    return &x;
}



template <class T, class R = decay_t<T> const>
auto get_ifc_handle (T const  x) -> first_if_t<R,
    ifc_is_member_handle<T>
>
{
    return x;
}

template <class T, class R = decay_t<T> const>
auto get_ifc_handle (T  const x) -> first_if_t<R,
    ifc_is_fn_handle<T>
>
{
    return x;
}

template <class T, class R = add_lvalue_reference_t<T> const>
auto get_ifc_handle (T *  x) -> first_if_t<R,
    ifc_is_functor_ptr<T*>
>
{
    return &x;
}

template <class T, class R = add_lvalue_reference_t<T> const>
auto get_ifc_handle (T &  x) -> first_if_t<R,
    ifc_is_functor_ref<T&>
>
{
    return x;
}


namespace detail {
template <class T>
using ifc_pointer_valid_t = decltype(get_ifc_pointer(std::declval<T>()));
}

template <class T>
struct ifc_pointer  {
    using type = mp_eval_or<nullptr_t, detail::ifc_pointer_valid_t, T>;
};

template <class T>
using ifc_pointer_t = typename ifc_pointer<T>::type;


namespace detail {
template <class T>
using ifc_handle_valid_t = decltype(get_ifc_handle(std::declval<T>()));
}

template <class T>
struct ifc_handle  {
    using type = mp_eval_or<nullptr_t, detail::ifc_handle_valid_t, T>;
};

template <class T>
using ifc_handle_t = typename ifc_handle<T>::type;



// PART TRAITS

namespace detail {
template <class T>
struct qualified_class_of {
    using type = ct::qualified_class_of_t<T>;
};
}

template <class T, class = void>
struct ifc_host {
    using type = typename mp_if<ifc_is_member_handle<T>,  ct::qualified_class_of<T>, mp_identity<nullptr_t>>::type;
};


template <class T>
using ifc_host_t = typename ifc_host<T>::type;

template <class T>
constexpr add_pointer_t<remove_reference_t<ifc_host_t<T>>> ifc_host_nullptr {};


namespace detail {
template <class T, class = void>
struct ifc_args_impl {
    using type = ct::args_t<remove_pointer_t<T>>;
};

template <class T>
struct ifc_args_impl <T, first_if_t<void_t<ct::args_t<T>>, ifc_is_member_handle<T>>> {
    using type = mp_rest<ct::args_t<T>>;
};

template <class T>
struct ifc_args_impl <T, first_if_none_t<void_t<ct::args_t<T>>, ifc_is_member_handle<T> >> {
    using type = ct::args_t<T>;
};

} // namespace detail

template <class T>
struct ifc_args
{
    using type = typename mp_eval_or<mp_identity<void>, detail::ifc_args_impl, ifc_handle_t<T>>::type;
};

template <class T>
using ifc_args_t = typename ifc_args<T>::type;


template <class T>
struct ifc_return : ct::return_type<T> {
    using type = typename mp_eval_or<mp_identity<void>, ct::return_type, ifc_handle_t<T>>::type;
};

template <class T>
using ifc_return_t = typename ifc_return<T>::type;

}  // namespace zmbt

#endif  // ZMBT_CORE_INTERFACE_TRAITS_HPP_