Skip to content

Instantly share code, notes, and snippets.

@CaseyCarter
Last active August 29, 2015 14:22
Show Gist options
  • Select an option

  • Save CaseyCarter/c82e4db76618e34fc253 to your computer and use it in GitHub Desktop.

Select an option

Save CaseyCarter/c82e4db76618e34fc253 to your computer and use it in GitHub Desktop.
Potential conceptified STL2 array swap implementation.
#include <type_traits>
#include <utility>
#include <stl2/concepts/foundational.hpp>
template <stl2::Movable T>
void swap(T& a, T& b)
noexcept(std::is_nothrow_move_constructible<T>::value &&
std::is_nothrow_move_assignable<T>::value)
{
T tmp(std::move(a));
a = std::move(b);
b = std::move(tmp);
}
template <class, class>
struct swappable_array :
std::false_type {};
template <class T, class U>
requires requires(T& t, U&u) {
swap(t, u); swap(u, t);
}
struct swappable_array<T, U> {
static constexpr bool value = true;
static constexpr bool nothrow =
noexcept(swap(std::declval<T&>(),
std::declval<U&>()));
};
template <class T, class U, std::size_t N>
struct swappable_array<T[N], U[N]> :
swappable_array<T, U> {};
template <class T, class U, std::size_t N>
requires swappable_array<T, U>::value
void swap(T (&t)[N], U (&u)[N])
noexcept(swappable_array<T, U>::nothrow)
{
for (std::size_t i = 0; i < N; ++i) {
swap(t[i], u[i]);
}
}
template <class T, class U>
concept bool Swappable =
requires(T&& t, U&& u) {
swap(std::forward<T>(t), std::forward<U>(u));
swap(std::forward<U>(u), std::forward<T>(t));
};
struct A
{
int i;
friend void swap(A& a, int& i) noexcept
{ swap(a.i, i); }
friend void swap(int& i, A& a) noexcept
{ swap(a.i, i); }
};
template <class T, std::size_t N>
struct array
{ T e[N]; };
template <class T, class U, std::size_t N>
requires Swappable<T&, U&>
void swap(array<T, N>& a, array<U, N>& other)
noexcept(noexcept(swap(a.e, other.e)))
{ swap(a.e, other.e); }
template <class T, class U, std::size_t N>
requires Swappable<T&, U&>
void swap(array<T, N>& a, U (&other)[N])
noexcept(noexcept(swap(a.e, other)))
{ swap(a.e, other); }
template <class T, class U, std::size_t N>
requires Swappable<T&, U&>
void swap(T (&other)[N], array<U, N>& a)
noexcept(noexcept(swap(a.e, other)))
{ swap(a.e, other); }
int main()
{
{
int a[2], b[2];
swap(a, b);
}
{
A a{}, b{};
swap(a, b);
}
{
A a{}; int i{};
swap(a, i);
swap(i, a);
}
{
A a[2]{}; int i[2]{};
swap(a, i);
swap(i, a);
}
{
array<int, 2> a; int i[2];
swap(a, i);
swap(i, a);
}
{
array<array<int, 2>, 2> a; int i[2][2];
swap(a, i);
swap(i, a);
}
{
array<array<int, 4>, 3> a[1][2]; int i[1][2][3][4];
swap(a, i);
swap(i, a);
}
{
array<array<A, 4>, 3> a[1][2]; int i[1][2][3][4];
swap(a, i);
swap(i, a);
static_assert(noexcept(swap(a, i)), "");
}
static_assert(noexcept(noexcept(
swap(std::declval<int(&)[1][2][3][4][5]>(),
std::declval<array<array<array<A, 5>, 4>, 3>(&)[1][2]>()))), "");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment