在类型列表中交换两种类型

use*_*177 6 c++ template-meta-programming c++11

为简单起见,我们将其std::tuple用作我们的类型列表.

在两个类型中交换两种类型的最佳(简洁,最少递归等)方法是std::tuple什么?

通过使用索引来说明功能:

#include <tuple>

int main()
{
    using tuple_t = std::tuple<int, void, double>;          // int, void, double
    using swapped_tuple_t = std::tuple<double, void, int>;  // double, void, int
    static_assert( std::is_same<swap<0, 2, tuple_t>::type, swapped_tuple_t>::value, "!" );
}
Run Code Online (Sandbox Code Playgroud)

Pio*_*cki 7

#include <tuple>
#include <utility>
#include <cstddef>

template <std::size_t I
        , std::size_t J
        , typename T
        , typename = std::make_index_sequence<I>
        , typename = std::make_index_sequence<J - I - 1>
        , typename = std::make_index_sequence<std::tuple_size<T>::value - J - 1>>
struct swap;

template <std::size_t I
        , std::size_t J
        , typename T
        , std::size_t... As
        , std::size_t... Bs
        , std::size_t... Cs>
struct swap<I, J, T
         , std::index_sequence<As...>
         , std::index_sequence<Bs...>
         , std::index_sequence<Cs...>
         >
{
    using type = std::tuple<typename std::tuple_element<As, T>::type...
                          , typename std::tuple_element<J, T>::type
                          , typename std::tuple_element<Bs + I + 1, T>::type...
                          , typename std::tuple_element<I, T>::type
                          , typename std::tuple_element<Cs + J + 1, T>::type...>;
};
Run Code Online (Sandbox Code Playgroud)

DEMO


对于J可以低于或等于的情况I,请使用以下特征:

template <std::size_t I, std::size_t J, typename T>
struct swap : swap_impl<I<J?I:J, I<J?J:I, T> {};

template <std::size_t I, typename T>
struct swap<I,I,T>
{
    using type = T;
};
Run Code Online (Sandbox Code Playgroud)

演示2


T.C*_*.C. 6

没有理由使用三个序列。一个就足够了:

template <std::size_t I
        , std::size_t J
        , typename T
        , typename = std::make_index_sequence<std::tuple_size<T>::value>>
struct swap_impl;

template <std::size_t I
        , std::size_t J
        , typename T
        , std::size_t... As>
struct swap_impl<I, J, T
               , std::index_sequence<As...>
         >
{
    using type = std::tuple<std::tuple_element_t<As == I ? J : As == J? I : As, T>... >;
};

template <std::size_t I, std::size_t J, typename T>
struct swap : swap_impl<I, J, T> {};
Run Code Online (Sandbox Code Playgroud)

而且现在也不需要对I> = J进行特殊处理。

演示