在模板类型列表中交换两个元素.寻求最有效的算法

pre*_*eys 3 c++ templates c++11

Swap<T, Position1, Position2, Pack>::type,其中Pack包含类型T的元素,是返回包含Position1和Position2中的元素的包.我的解决方案不是最有效的.应该有一种方法可以非常干净地完成这项任务,而无需两次访问任何元素.有人能想到吗?

// ReplaceElement replaces the element of a pack with a specified position (0 being the first position) with a specified value.
template <typename T, std::size_t, std::size_t, T, typename, typename> struct ReplaceElementHelper;

template <typename T, std::size_t Position, std::size_t CurrentPosition, T NewValue, template <T...> class Z, T First, T... Rest, T... Accumulated>
struct ReplaceElementHelper<T, Position, CurrentPosition, NewValue, Z<First, Rest...>, Z<Accumulated...>>
    : ReplaceElementHelper<T, Position, CurrentPosition + 1, NewValue, Z<Rest...>, Z<Accumulated..., First>> {};

template <typename T, std::size_t Position, T NewValue, template <T...> class Z, T First, T... Rest, T... Accumulated>
struct ReplaceElementHelper<T, Position, Position, NewValue, Z<First, Rest...>, Z<Accumulated...>> {
    using type = Z<Accumulated..., NewValue, Rest...>;
};

template <typename T, std::size_t, T, typename> struct ReplaceElement;

template <typename T, std::size_t Position, T NewValue, template <T...> class Z, T... Ts>
struct ReplaceElement<T, Position, NewValue, Z<Ts...>> : ReplaceElementHelper<T, Position, 0, NewValue, Z<Ts...>, Z<>> {
    static_assert (Position < sizeof...(Ts), "Error!  Invalid position for ReplaceElement.");
};

// Swapping two elements of specified positions in a pack.
template <typename, std::size_t, std::size_t, typename> struct Swap;

template <typename T, std::size_t Position1, std::size_t Position2, template <T...> class Z, T... Ts>
struct Swap<T, Position1, Position2, Z<Ts...>> {
    static constexpr T a[sizeof...(Ts)] = {Ts...};
    using type = typename ReplaceElement<T, Position2, a[Position1], typename ReplaceElement<T, Position1, a[Position2], Z<Ts...>>::type>::type;
};
Run Code Online (Sandbox Code Playgroud)

您可以告诉我的解决方案all在Position1(或Position2)之前访问元素两次.应该没有必要.我知道必须有一个避免这种情况的解决方案,但我无法想到它.

Col*_*mbo 6

如果value_pack定义有点像

template <typename T, T... v>
struct value_pack {
    static constexpr T array[] {v...};
    static constexpr std::size_t len = sizeof...(v);
    using type = value_pack;
};
template <typename T, T... v>
constexpr T value_pack<T, v...>::array[];
Run Code Online (Sandbox Code Playgroud)

那么C++ 14中的解决方案如下所示:

template <typename T, std::size_t p1, std::size_t p2,
          typename pack,
          typename=std::make_index_sequence<pack::len>>
struct Swap;
template <typename T, std::size_t p1, std::size_t p2,
          typename pack, std::size_t...indices>
struct Swap<T, p1, p2, pack, std::index_sequence<indices...>> :
    value_pack<T,  pack::array[indices==p1? p2 : indices==p2? p1 : indices]...> {};
Run Code Online (Sandbox Code Playgroud)

演示.如果没有C++ 14标准库,您可以make_index_sequence自己实现- 许多示例分散在SO中.