#ifndef BOOST_LEAF_DETAIL_MP11_HPP_INCLUDED #define BOOST_LEAF_DETAIL_MP11_HPP_INCLUDED // Copyright 2015-2017 Peter Dimov. // Copyright 2019 Emil Dotchevski. // // Distributed under the Boost Software License, Version 1.0. // // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt #include #include namespace boost { namespace leaf { namespace leaf_detail_mp11 { // mp_list template struct mp_list { }; // mp_identity template struct mp_identity { using type = T; }; // mp_inherit template struct mp_inherit: T... {}; // mp_if, mp_if_c namespace detail { template struct mp_if_c_impl { }; template struct mp_if_c_impl { using type = T; }; template struct mp_if_c_impl { using type = E; }; } // namespace detail template using mp_if_c = typename detail::mp_if_c_impl::type; template using mp_if = typename detail::mp_if_c_impl(C::value), T, E...>::type; // mp_bool template using mp_bool = std::integral_constant; using mp_true = mp_bool; using mp_false = mp_bool; // mp_to_bool template using mp_to_bool = mp_bool( T::value )>; // mp_not template using mp_not = mp_bool< !T::value >; // mp_int template using mp_int = std::integral_constant; // mp_size_t template using mp_size_t = std::integral_constant; // mp_set_contains namespace detail { template struct mp_set_contains_impl; template class L, class... T, class V> struct mp_set_contains_impl, V> { using type = mp_to_bool, mp_inherit...> > >; }; } // namespace detail template using mp_set_contains = typename detail::mp_set_contains_impl::type; // mp_set_push_back namespace detail { template struct mp_set_push_back_impl; template class L, class... U> struct mp_set_push_back_impl> { using type = L; }; template class L, class... U, class T1, class... T> struct mp_set_push_back_impl, T1, T...> { using S = mp_if, T1>, L, L>; using type = typename mp_set_push_back_impl::type; }; } // namespace detail template using mp_set_push_back = typename detail::mp_set_push_back_impl::type; // mp_unique namespace detail { template struct mp_unique_impl; template class L, class... T> struct mp_unique_impl> { using type = mp_set_push_back, T...>; }; } // namespace detail template using mp_unique = typename detail::mp_unique_impl::type; // mp_append namespace detail { template struct mp_append_impl; template<> struct mp_append_impl<> { using type = mp_list<>; }; template class L, class... T> struct mp_append_impl> { using type = L; }; template class L1, class... T1, template class L2, class... T2, class... Lr> struct mp_append_impl, L2, Lr...> { using type = typename mp_append_impl, Lr...>::type; }; } template using mp_append = typename detail::mp_append_impl::type; // mp_front namespace detail { template struct mp_front_impl { // An error "no type named 'type'" here means that the argument to mp_front // is either not a list, or is an empty list }; template class L, class T1, class... T> struct mp_front_impl> { using type = T1; }; } // namespace detail template using mp_front = typename detail::mp_front_impl::type; // mp_pop_front namespace detail { template struct mp_pop_front_impl { // An error "no type named 'type'" here means that the argument to mp_pop_front // is either not a list, or is an empty list }; template class L, class T1, class... T> struct mp_pop_front_impl> { using type = L; }; } // namespace detail template using mp_pop_front = typename detail::mp_pop_front_impl::type; // mp_first template using mp_first = mp_front; // mp_rest template using mp_rest = mp_pop_front; // mp_remove_if namespace detail { template class P> struct mp_remove_if_impl; template class L, class... T, template class P> struct mp_remove_if_impl, P> { template using _f = mp_if, mp_list<>, mp_list>; using type = mp_append, _f...>; }; } // namespace detail template class P> using mp_remove_if = typename detail::mp_remove_if_impl::type; // integer_sequence template struct integer_sequence { }; // detail::make_integer_sequence_impl namespace detail { // iseq_if_c template struct iseq_if_c_impl; template struct iseq_if_c_impl { using type = T; }; template struct iseq_if_c_impl { using type = E; }; template using iseq_if_c = typename iseq_if_c_impl::type; // iseq_identity template struct iseq_identity { using type = T; }; template struct append_integer_sequence; template struct append_integer_sequence, integer_sequence> { using type = integer_sequence< T, I..., ( J + sizeof...(I) )... >; }; template struct make_integer_sequence_impl; template struct make_integer_sequence_impl_ { private: static_assert( N >= 0, "make_integer_sequence: N must not be negative" ); static T const M = N / 2; static T const R = N % 2; using S1 = typename make_integer_sequence_impl::type; using S2 = typename append_integer_sequence::type; using S3 = typename make_integer_sequence_impl::type; using S4 = typename append_integer_sequence::type; public: using type = S4; }; template struct make_integer_sequence_impl: iseq_if_c>, iseq_if_c>, make_integer_sequence_impl_ > > { }; } // namespace detail // make_integer_sequence template using make_integer_sequence = typename detail::make_integer_sequence_impl::type; // index_sequence template using index_sequence = integer_sequence; // make_index_sequence template using make_index_sequence = make_integer_sequence; // index_sequence_for template using index_sequence_for = make_integer_sequence; // implementation by Bruno Dutra (by the name is_evaluable) namespace detail { template class F, class... T> struct mp_valid_impl { template class G, class = G> static mp_true check(int); template class> static mp_false check(...); using type = decltype(check(0)); }; } // namespace detail template class F, class... T> using mp_valid = typename detail::mp_valid_impl::type; } } } #endif