diff --git a/include/boost/mp11/algorithm.hpp b/include/boost/mp11/algorithm.hpp index 6ffc572..fea5bc6 100644 --- a/include/boost/mp11/algorithm.hpp +++ b/include/boost/mp11/algorithm.hpp @@ -1101,6 +1101,59 @@ struct mp_starts_with_impl, L2 > { template using mp_starts_with = typename detail::mp_starts_with_impl::type; +// mp_rotate_left(_c) +namespace detail +{ + +template struct canonical_rotation +{ + // provide a default rotation so that "no type named 'type'" errors appear in mp_rotate_impl instead of here + using type = mp_size_t<0>; +}; + +template class L, class... T, std::size_t N> struct canonical_rotation, N> +{ + // limit divisor to 1 to avoid division by 0 and give a rotation of 0 for lists containing 0 or 1 elements + using type = mp_size_t; +}; + +template using canonical_rotation_t = typename canonical_rotation::type; + +struct left_rotation; +struct right_rotation; + +template struct mp_rotate_impl +{ +// An error "no type named 'type'" here means that the first argument to mp_rotate_left/mp_rotate_right is not a list +}; + +template class L, class... T> struct mp_rotate_impl, mp_size_t<0>, left_rotation> +{ + // fast-track the case of an identity rotation + using type = L; +}; + +template class L, class... T, std::size_t N> struct mp_rotate_impl, mp_size_t, left_rotation> +{ + // avoid errors when rotating fixed-sized lists by using mp_list for the transformation + using type = mp_rename, N>, mp_take_c, N>>, L>; +}; + +template class L, class... T, std::size_t N> struct mp_rotate_impl, mp_size_t, right_rotation> +{ + // perform right rotation as a left rotation by inverting the number of elements to rotate + using type = typename mp_rotate_impl, canonical_rotation_t, sizeof...(T) - N>, left_rotation>::type; +}; + +} // namespace detail + +template using mp_rotate_left_c = typename detail::mp_rotate_impl, detail::left_rotation>::type; +template> using mp_rotate_left = mp_rotate_left_c; + +// mp_rotate_right(_c) +template using mp_rotate_right_c = typename detail::mp_rotate_impl, detail::right_rotation>::type; +template> using mp_rotate_right = mp_rotate_right_c; + // mp_min_element // mp_max_element // in detail/mp_min_element.hpp diff --git a/test/Jamfile b/test/Jamfile index 440bd9e..d242273 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -117,6 +117,8 @@ run mp_nth_element_q.cpp ; run mp_back.cpp ; run mp_pop_back.cpp ; run mp_flatten.cpp ; +run mp_rotate_left.cpp ; +run mp_rotate_right.cpp ; # integral run integral.cpp ; diff --git a/test/mp_rotate_left.cpp b/test/mp_rotate_left.cpp new file mode 100644 index 0000000..bccbbe4 --- /dev/null +++ b/test/mp_rotate_left.cpp @@ -0,0 +1,151 @@ + +// Copyright 2015 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 + +struct X1 {}; +struct X2 {}; +struct X3 {}; +struct X4 {}; +struct X5 {}; + +int main() +{ + using boost::mp11::mp_list; + using boost::mp11::mp_rotate_left; + using boost::mp11::mp_rotate_left_c; + using boost::mp11::mp_size_t; + + { + using L1 = mp_list<>; + + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + + using L2 = mp_list; + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + } + + { + using L1 = std::tuple<>; + + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + + using L2 = std::tuple; + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + } + + { + using L1 = std::pair; + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::pair>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::pair>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::pair>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::pair>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::pair>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::pair>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::pair>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::pair>)); + } + + return boost::report_errors(); +} diff --git a/test/mp_rotate_right.cpp b/test/mp_rotate_right.cpp new file mode 100644 index 0000000..92d6854 --- /dev/null +++ b/test/mp_rotate_right.cpp @@ -0,0 +1,151 @@ + +// Copyright 2015 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 + +struct X1 {}; +struct X2 {}; +struct X3 {}; +struct X4 {}; +struct X5 {}; + +int main() +{ + using boost::mp11::mp_list; + using boost::mp11::mp_rotate_right; + using boost::mp11::mp_rotate_right_c; + using boost::mp11::mp_size_t; + + { + using L1 = mp_list<>; + + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + + using L2 = mp_list; + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + } + + { + using L1 = std::tuple<>; + + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + + using L2 = std::tuple; + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + } + + { + using L1 = std::pair; + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::pair>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::pair>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::pair>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::pair>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::pair>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::pair>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::pair>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::pair>)); + } + + return boost::report_errors(); +}