22#define PHLEX_METAPROGRAMMING_TYPE_DEDUCTION_HPP
33
44#include " phlex/metaprogramming/detail/ctor_reflect_types.hpp"
5- # include " phlex/metaprogramming/detail/number_output_objects.hpp "
6- #include " phlex/metaprogramming/detail/number_parameters .hpp"
7- #include " phlex/metaprogramming/detail/parameter_types .hpp"
8- #include " phlex/metaprogramming/detail/return_type .hpp"
5+
6+ #include " boost/callable_traits .hpp"
7+ #include " boost/mp11/algorithm .hpp"
8+ #include " boost/mp11/list .hpp"
99
1010#include < atomic>
1111#include < iterator>
1212#include < tuple>
1313#include < type_traits>
1414
1515namespace phlex ::experimental {
16+ namespace ct = boost::callable_traits;
17+ namespace mp11 = boost::mp11;
1618 template <typename T>
17- using return_type = decltype (detail::return_type_impl(std::declval <T>())) ;
19+ using return_type = ct:: return_type_t <T>;
1820
21+ // A simple mp_if doesn't work because both branches always need to be valid.
22+ // With eval_if and eval_if_not the false branch doesn't need to be valid, but
23+ // does need to be expressed in this F, Args... format.
1924 template <typename T>
20- using function_parameter_types = decltype (detail::parameter_types_impl(std::declval<T>()));
25+ using function_parameter_types = mp11::
26+ mp_eval_if_not<std::is_member_function_pointer<T>, ct::args_t <T>, mp11::mp_rest, ct::args_t <T>>;
2127
2228 template <std::size_t I, typename T>
2329 using function_parameter_type = std::tuple_element_t <I, function_parameter_types<T>>;
@@ -26,37 +32,29 @@ namespace phlex::experimental {
2632 using constructor_parameter_types = typename refl::as_tuple<T>;
2733
2834 template <typename T>
29- constexpr std::size_t number_parameters = detail::number_parameters_impl<T> ;
35+ constexpr std::size_t number_parameters = mp11::mp_size<function_parameter_types<T>>::value ;
3036
37+ // Wrapping in a tuple then "flattening" (which just removes one nested inner layer of tuple)
38+ // ensures a single T by itself becomes std::tuple<T> without changing anything that's already
39+ // a tuple.
3140 template <typename T>
32- constexpr std::size_t number_output_objects = detail::number_output_objects_impl<T>;
33-
34- using detail::number_types;
35-
36- namespace detail {
37- template <typename Head, typename ... Tail>
38- std::tuple<Tail...> skip_first_type_impl (std::tuple<Head, Tail...> const &);
41+ constexpr std::size_t number_types = mp11::mp_size<mp11::mp_flatten<std::tuple<T>>>::value;
3942
40- template <typename Head, typename ... Tail >
41- std::tuple<Tail...> skip_first_type_impl (std::pair<Head, Tail...> const &);
42- }
43+ template <typename T >
44+ constexpr std::size_t number_output_objects =
45+ std::same_as< void , return_type<T>> ? 0 : number_types<return_type<T>>;
4346
47+ // mp_apply<std::tuple, ..> converts other wrapper types (e.g. std::pair) to tuple
4448 template <typename Tuple>
45- using skip_first_type = decltype (detail::skip_first_type_impl(std::declval< Tuple>())) ;
49+ using skip_first_type = mp11::mp_rest<mp11::mp_apply<std::tuple, Tuple>> ;
4650
4751 template <typename T, typename ... Args>
4852 struct check_parameters {
4953 using input_parameters = function_parameter_types<T>;
5054 static_assert (std::tuple_size<input_parameters>{} >= sizeof ...(Args));
51-
52- template <std::size_t ... Is>
53- static constexpr bool check_params_for (std::index_sequence<Is...>)
54- {
55- return std::conjunction_v<std::is_same<std::tuple_element_t <Is, input_parameters>, Args>...>;
56- }
57-
55+ static constexpr bool value =
56+ mp11::mp_starts_with<input_parameters, std::tuple<Args...>>::value;
5857 constexpr operator bool () noexcept { return value; }
59- static constexpr bool value = check_params_for(std::index_sequence_for<Args...>{});
6058 };
6159
6260 // ===================================================================
@@ -66,20 +64,10 @@ namespace phlex::experimental {
6664 template <typename T>
6765 struct is_non_const_lvalue_reference <T const &> : std::false_type {};
6866
67+ // mp_similar<std::atomic<int>, T> just checks if T is an atomic (of any type)
6968 template <typename T>
70- class remove_atomic {
71- public:
72- using type = T;
73- };
74-
75- template <typename T>
76- class remove_atomic <std::atomic<T>> {
77- public:
78- using type = T;
79- };
80-
81- template <typename T>
82- using remove_atomic_t = remove_atomic<T>::type;
69+ using remove_atomic_t =
70+ mp11::mp_eval_if_not<mp11::mp_similar<std::atomic<int >, T>, T, mp11::mp_front, T>;
8371
8472 template <typename T>
8573 concept container = requires {
0 commit comments