交换类型列表中的两个类型
Swapping two types in a type list
为了简单起见,让我们使用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, "!" );
}
#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...>;
};
演示
对于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;
};
演示2
没有理由使用三个序列。一个就足够了:
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> {};
现在也不需要特殊情况,I>=J的情况。
演示。
我提出了一个替代方案(但我认为@Piotr的解决方案更优雅)。
template <size_t ...>
struct seq { };
// X, Y are the indeces we want to swap
template <size_t N, size_t X, size_t Y, size_t ...S>
struct gen : gen<N-1, X, Y, (N-1 == X ? Y : (N-1 == Y ? X : N - 1)), S...> { };
template <size_t X, size_t Y, size_t ...S>
struct gen<0, X, Y, S...> {
typedef seq<S...> type;
};
// X and Y are the index we want to swap, T is the tuple
template <size_t X, size_t Y, class T, class S>
struct swapImpl;
template <size_t X, size_t Y, class T, size_t... S>
struct swapImpl<X, Y, T, seq<S...>>{
using type = std::tuple<typename std::tuple_element<S, T>::type...>;
};
template <size_t X, size_t Y, class T>
struct swap {
using type = typename swapImpl<X, Y, T,
typename gen<std::tuple_size<T>::value, X, Y>::type>::type;
};
int main() {
using tuple_t = std::tuple<int, unsigned, void, char, double>; // int, void, double
using swapped_tuple_a_t = std::tuple<unsigned, int, void, char, double>; // double, void, int
static_assert( std::is_same<swap<0, 1, tuple_t>::type, swapped_tuple_a_t>::value, "!" );
static_assert( std::is_same<swap<1, 0, tuple_t>::type, swapped_tuple_a_t>::value, "!" );
using swapped_tuple_b_t = std::tuple<int, char, void, unsigned, double>; // double, void, int
static_assert( std::is_same<swap<1, 3, tuple_t>::type, swapped_tuple_b_t>::value, "!" );
static_assert( std::is_same<swap<3, 1, tuple_t>::type, swapped_tuple_b_t>::value, "!" );
}
相关文章:
- 我有两个类需要在同一 cpp 文件中相互引用,但第一个类无法识别第二个类类型的对象
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 可以将两个相同类型的连续数组视为一个数组吗?
- 如何允许模板参数中的类类型,仅当它有两个基类时
- 测试两个类型列表中的所有组合
- 在类 A 中创建类型为 B 类的向量 - 访问数据 [C++] [成员在两个类中都是私有的]
- 堆栈分配的类类型.为什么两个 ID 实例的地址相同?
- 为什么在传递长整型时调用具有两个双精度类型的参数的重载函数?
- 如何创建两个具有相同名称和不同返回类型并基于布尔参数运行的函数
- 为什么 Clang 和 GCC 中两个无符号整数之和的结果类型不同
- 比较两个整数在C++中与未知 int 类型的相等性
- 为什么C++不允许两个同名的函数/类模板,区别仅在于非类型模板参数(整型)的类型?
- [[no_unique_address]] 和两个相同类型的成员值
- C++stoi:这两个重载都无法转换所有参数类型
- 类型测试对象的动态数组的这两个声明之间的区别?
- 如何实现对参数顺序不可知的std::same_as的广义形式(即对于两个以上的类型参数)
- C++将两个不同类型的向量的属性连接到新的向量中
- 使用相同名称类型的两个不同库
- 重写虚函数协变返回类型(两个指针)
- 在c++中,如何在另一个嵌套类中使用嵌套类类型(两个嵌套类在同一个外部类下)