Skip to content

Instantly share code, notes, and snippets.

@MetGang
Created November 24, 2019 21:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MetGang/0b7c7247e9b99969d624c0900eab3f7d to your computer and use it in GitHub Desktop.
Save MetGang/0b7c7247e9b99969d624c0900eab3f7d to your computer and use it in GitHub Desktop.
Stritch swap v2
// Stritch swap v2
// Live demo https://godbolt.org/z/gXEqjX
#include <iostream>
#include <type_traits>
#include <tuple>
#include <new>
template <typename T>
concept Trivial = std::is_trivial_v<T>;
inline static constexpr auto swap = [] <typename T> (T& a, T& b) -> decltype(auto) {
auto [ q, p, s ] = std::tuple {
+[&a]() -> T* { return std::launder(std::addressof(a)); }(),
+[&b]() -> T* { return std::launder(std::addressof(b)); }(),
std::enable_if_t<!!alignof(T), std::integral_constant<size_t, sizeof(T)>>{}
};
using S_t = decltype(s);
typedef struct {
[[nodiscard]]
constexpr auto operator() (void* x, void* y, ...) const && noexcept
requires Trivial<T>
try {
[
ex = [] <size_t I> (auto g) { return *(g + I); }
] <size_t... Is> (auto i, auto j, std::index_sequence<Is...>) {
std::byte k[sizeof...(Is)];
((
Is[k] = ex.template operator()<Is>(i),
Is[i] = ex.template operator()<Is>(j),
Is[j] = ex.template operator()<Is>(k)),
...);
}(
+reinterpret_cast<std::byte*>(*&x),
+reinterpret_cast<std::byte*>(*&y),
std::make_index_sequence<decltype(S_t{}){}()>{}
);
} catch(...) {}
} Swapper[];
return std::remove_extent_t<Swapper>{}(q, p);
};
int main()
{
int x = 10;
int y = 42;
std::cout << x << ' ' << y << '\n';
swap(x, y);
std::cout << x << ' ' << y << '\n';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment