For simplicity, let's use std::tuple
as our type list.
What is the best (concise, least recursive, etc.) way to swap two types in a std::tuple
?
Illustration of the functionality through the use of indices:
#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, "!" );
}
To swap two list elements x and y by value, get the index of their first occurrences using the list. index(x) and list. index(y) methods and assign the result to variables i and j , respectively. Then apply the multiple assignment expression lst[i], lst[j] = lst[j], lst[i] to swap the elements.
Given a list in Python and provided the positions of the elements, write a program to swap the two elements in the list. Since the positions of the elements are known, we can simply swap the positions of the elements.
A far better method you can use to swap array elements is destructuring, as it does the job in only one line of code. You just create a new array containing both elements in a particular order, then assign it to a new array that contains both elements in the reversed order.
#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...>;
};
DEMO
For cases where J
can be lower than or equal to I
, use the below trait:
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;
};
DEMO 2
There's no reason to use three sequences. One is enough:
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> {};
And now there's also no need to special-case the I >= J case.
Demo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With