diff --git a/doc/mp11/algorithm.adoc b/doc/mp11/algorithm.adoc index bff181e..8c51983 100644 --- a/doc/mp11/algorithm.adoc +++ b/doc/mp11/algorithm.adoc @@ -441,6 +441,18 @@ using L1 = mp_list, std::ratio<1,4>>; using R1 = mp_sort; // mp_list, ratio<1,2>> ---- +## mp_nth_element_c + + template class P> using mp_nth_element_c = /*...*/; + +Returns the element at position `I` in `mp_sort`. + +## mp_nth_element + + template class P> using mp_nth_element = /*...*/; + +Like `mp_nth_element_c`, but with a type argument `I`. `I::value` must be a nonnegative number. + ## mp_min_element template class P> using mp_min_element = /*...*/; diff --git a/include/boost/mp11/algorithm.hpp b/include/boost/mp11/algorithm.hpp index 7820756..a0f246e 100644 --- a/include/boost/mp11/algorithm.hpp +++ b/include/boost/mp11/algorithm.hpp @@ -508,6 +508,45 @@ template class L, class T1, class... T, template cl template class P> using mp_sort = typename detail::mp_sort_impl::type; +// mp_nth_element(_c) +namespace detail +{ + +template class P> struct mp_nth_element_impl; + +template class L, class T1, std::size_t I, template class P> struct mp_nth_element_impl, I, P> +{ + static_assert( I == 0, "mp_nth_element index out of range" ); + using type = T1; +}; + +template class L, class T1, class... T, std::size_t I, template class P> struct mp_nth_element_impl, I, P> +{ + static_assert( I < 1 + sizeof...(T), "mp_nth_element index out of range" ); + + template using F = P; + + using part = mp_partition, F>; + + using L1 = mp_first; + static std::size_t const N1 = mp_size::value; + + using L2 = mp_second; + + using type = typename mp_cond< + + mp_bool<(I < N1)>, mp_nth_element_impl, + mp_bool<(I == N1)>, mp_identity, + mp_true, mp_nth_element_impl + + >::type; +}; + +} // namespace detail + +template class P> using mp_nth_element_c = typename detail::mp_nth_element_impl::type; +template class P> using mp_nth_element = typename detail::mp_nth_element_impl::type; + // mp_find namespace detail { diff --git a/test/Jamfile b/test/Jamfile index 86d4f0c..4ce6e88 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -80,6 +80,7 @@ run mp_with_index_cx.cpp ; run mp_from_sequence.cpp ; run mp_min_element.cpp ; run mp_max_element.cpp ; +run mp_nth_element.cpp ; # integral run integral.cpp ; diff --git a/test/mp_nth_element.cpp b/test/mp_nth_element.cpp new file mode 100644 index 0000000..8a077d7 --- /dev/null +++ b/test/mp_nth_element.cpp @@ -0,0 +1,72 @@ + +// Copyright 2017 Peter Dimov. +// +// 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 +#include +#include +#include +#include +#include + +int main() +{ + using boost::mp11::mp_nth_element; + using boost::mp11::mp_nth_element_c; + using boost::mp11::mp_list_c; + using boost::mp11::mp_sort; + using boost::mp11::mp_less; + using boost::mp11::mp_at_c; + using boost::mp11::mp_size_t; + using boost::mp11::mp_rename; + + { + using L1 = mp_list_c; + using L2 = mp_sort; + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_at_c>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_less>, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_less>, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_less>, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_less>, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_less>, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_less>, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_less>, mp_at_c>)); + } + + { + using L1 = mp_rename, std::tuple>; + using L2 = mp_sort; + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_at_c>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_less>, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_less>, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_less>, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_less>, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_less>, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_less>, mp_at_c>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_less>, mp_at_c>)); + } + + return boost::report_errors(); +}