1
0
forked from boostorg/mp11

Add mp_rotate_left and mp_rotate_right

This commit is contained in:
D-Barber
2019-12-16 15:25:13 +00:00
parent 2afc07f189
commit 054f576d14
4 changed files with 357 additions and 0 deletions

View File

@@ -1101,6 +1101,59 @@ struct mp_starts_with_impl<L1<T1...>, L2<T2...> > {
template<class L1, class L2>
using mp_starts_with = typename detail::mp_starts_with_impl<L1, L2>::type;
// mp_rotate_left(_c)<L, N>
namespace detail
{
template<class L, std::size_t N> 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<template<class...> class L, class... T, std::size_t N> struct canonical_rotation<L<T...>, 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<N % (sizeof...(T) == 0 ? 1 : sizeof...(T))>;
};
template<class L, std::size_t N> using canonical_rotation_t = typename canonical_rotation<L, N>::type;
struct left_rotation;
struct right_rotation;
template<class L, class N, class D> 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<template<class...> class L, class... T> struct mp_rotate_impl<L<T...>, mp_size_t<0>, left_rotation>
{
// fast-track the case of an identity rotation
using type = L<T...>;
};
template<template<class...> class L, class... T, std::size_t N> struct mp_rotate_impl<L<T...>, mp_size_t<N>, left_rotation>
{
// avoid errors when rotating fixed-sized lists by using mp_list for the transformation
using type = mp_rename<mp_append<mp_drop_c<mp_list<T...>, N>, mp_take_c<mp_list<T...>, N>>, L>;
};
template<template<class...> class L, class... T, std::size_t N> struct mp_rotate_impl<L<T...>, mp_size_t<N>, right_rotation>
{
// perform right rotation as a left rotation by inverting the number of elements to rotate
using type = typename mp_rotate_impl<L<T...>, canonical_rotation_t<L<T...>, sizeof...(T) - N>, left_rotation>::type;
};
} // namespace detail
template<class L, std::size_t N = 1> using mp_rotate_left_c = typename detail::mp_rotate_impl<L, detail::canonical_rotation_t<L, N>, detail::left_rotation>::type;
template<class L, class N = mp_size_t<1>> using mp_rotate_left = mp_rotate_left_c<L, std::size_t{ N::value }>;
// mp_rotate_right(_c)<L, N>
template<class L, std::size_t N = 1> using mp_rotate_right_c = typename detail::mp_rotate_impl<L, detail::canonical_rotation_t<L, N>, detail::right_rotation>::type;
template<class L, class N = mp_size_t<1>> using mp_rotate_right = mp_rotate_right_c<L, std::size_t{ N::value }>;
// mp_min_element<L, P>
// mp_max_element<L, P>
// in detail/mp_min_element.hpp