686 lines
30 KiB
C++
686 lines
30 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
|
|
|
// template<class T, class U>
|
|
// concept swappable_with = // see below
|
|
|
|
#include <concepts>
|
|
|
|
#include <array>
|
|
#include <cassert>
|
|
#include <deque>
|
|
#include <forward_list>
|
|
#include <list>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <set>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
#include <vector>
|
|
|
|
#include "type_classification/moveconstructible.h"
|
|
#include "type_classification/swappable.h"
|
|
|
|
template <class T, class U>
|
|
constexpr bool check_swappable_with_impl() {
|
|
static_assert(std::swappable_with<T, U> == std::swappable_with<U, T>);
|
|
return std::swappable_with<T, U>;
|
|
}
|
|
|
|
template <class T, class U>
|
|
constexpr bool check_swappable_with() {
|
|
static_assert(!check_swappable_with_impl<T, U>());
|
|
static_assert(!check_swappable_with_impl<T, U const>());
|
|
static_assert(!check_swappable_with_impl<T const, U>());
|
|
static_assert(!check_swappable_with_impl<T const, U const>());
|
|
|
|
static_assert(!check_swappable_with_impl<T, U&>());
|
|
static_assert(!check_swappable_with_impl<T, U const&>());
|
|
static_assert(!check_swappable_with_impl<T, U volatile&>());
|
|
static_assert(!check_swappable_with_impl<T, U const volatile&>());
|
|
static_assert(!check_swappable_with_impl<T const, U&>());
|
|
static_assert(!check_swappable_with_impl<T const, U const&>());
|
|
static_assert(!check_swappable_with_impl<T const, U volatile&>());
|
|
static_assert(!check_swappable_with_impl<T const, U const volatile&>());
|
|
|
|
static_assert(!check_swappable_with_impl<T&, U>());
|
|
static_assert(!check_swappable_with_impl<T&, U const>());
|
|
static_assert(!check_swappable_with_impl<T const&, U>());
|
|
static_assert(!check_swappable_with_impl<T const&, U const>());
|
|
static_assert(!check_swappable_with_impl<T volatile&, U>());
|
|
static_assert(!check_swappable_with_impl<T volatile&, U const>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&, U>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&, U const>());
|
|
|
|
static_assert(!check_swappable_with_impl<T&, U const&>());
|
|
static_assert(!check_swappable_with_impl<T&, U volatile&>());
|
|
static_assert(!check_swappable_with_impl<T&, U const volatile&>());
|
|
static_assert(!check_swappable_with_impl<T const&, U&>());
|
|
static_assert(!check_swappable_with_impl<T const&, U const&>());
|
|
static_assert(!check_swappable_with_impl<T const&, U volatile&>());
|
|
static_assert(!check_swappable_with_impl<T const&, U const volatile&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&, U&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&, U const&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&, U const volatile&>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&, U&>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&, U const&>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&, U volatile&>());
|
|
static_assert(
|
|
!check_swappable_with_impl<T const volatile&, U const volatile&>());
|
|
|
|
static_assert(!check_swappable_with_impl<T, U&&>());
|
|
static_assert(!check_swappable_with_impl<T, U const&&>());
|
|
static_assert(!check_swappable_with_impl<T, U volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T, U const volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T const, U&&>());
|
|
static_assert(!check_swappable_with_impl<T const, U const&&>());
|
|
static_assert(!check_swappable_with_impl<T const, U volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T const, U const volatile&&>());
|
|
|
|
static_assert(!check_swappable_with_impl<T&&, U>());
|
|
static_assert(!check_swappable_with_impl<T&&, U const>());
|
|
static_assert(!check_swappable_with_impl<T const&&, U>());
|
|
static_assert(!check_swappable_with_impl<T const&&, U const>());
|
|
static_assert(!check_swappable_with_impl<T volatile&&, U>());
|
|
static_assert(!check_swappable_with_impl<T volatile&&, U const>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&&, U>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&&, U const>());
|
|
|
|
static_assert(!check_swappable_with_impl<T&, U&&>());
|
|
static_assert(!check_swappable_with_impl<T&, U const&&>());
|
|
static_assert(!check_swappable_with_impl<T&, U volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T&, U const volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T const&, U&&>());
|
|
static_assert(!check_swappable_with_impl<T const&, U const&&>());
|
|
static_assert(!check_swappable_with_impl<T const&, U volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T const&, U const volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&, U&&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&, U const&&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&, U volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&, U const volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&, U&&>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&, U const&&>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&, U volatile&&>());
|
|
static_assert(
|
|
!check_swappable_with_impl<T const volatile&, U const volatile&&>());
|
|
|
|
static_assert(!check_swappable_with_impl<T&&, U&>());
|
|
static_assert(!check_swappable_with_impl<T&&, U const&>());
|
|
static_assert(!check_swappable_with_impl<T&&, U volatile&>());
|
|
static_assert(!check_swappable_with_impl<T&&, U const volatile&>());
|
|
static_assert(!check_swappable_with_impl<T const&&, U&>());
|
|
static_assert(!check_swappable_with_impl<T const&&, U const&>());
|
|
static_assert(!check_swappable_with_impl<T const&&, U volatile&>());
|
|
static_assert(!check_swappable_with_impl<T const&&, U const volatile&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&&, U&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&&, U const&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&&, U volatile&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&&, U const volatile&>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&&, U&>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&&, U const&>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&&, U volatile&>());
|
|
static_assert(
|
|
!check_swappable_with_impl<T const volatile&&, U const volatile&>());
|
|
|
|
static_assert(!check_swappable_with_impl<T&&, U&&>());
|
|
static_assert(!check_swappable_with_impl<T&&, U const&&>());
|
|
static_assert(!check_swappable_with_impl<T&&, U volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T&&, U const volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T const&&, U&&>());
|
|
static_assert(!check_swappable_with_impl<T const&&, U const&&>());
|
|
static_assert(!check_swappable_with_impl<T const&&, U volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T const&&, U const volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&&, U&&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&&, U const&&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&&, U volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T volatile&&, U const volatile&&>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&&, U&&>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&&, U const&&>());
|
|
static_assert(!check_swappable_with_impl<T const volatile&&, U volatile&&>());
|
|
static_assert(
|
|
!check_swappable_with_impl<T const volatile&&, U const volatile&&>());
|
|
return check_swappable_with_impl<T&, U&>();
|
|
}
|
|
|
|
template <class T, class U>
|
|
constexpr bool check_swappable_with_including_lvalue_ref_to_volatile() {
|
|
constexpr auto result = check_swappable_with<T, U>();
|
|
static_assert(check_swappable_with_impl<T volatile&, U volatile&>() ==
|
|
result);
|
|
return result;
|
|
}
|
|
|
|
namespace fundamental {
|
|
static_assert(
|
|
check_swappable_with_including_lvalue_ref_to_volatile<int, int>());
|
|
static_assert(
|
|
check_swappable_with_including_lvalue_ref_to_volatile<double, double>());
|
|
static_assert(
|
|
!check_swappable_with_including_lvalue_ref_to_volatile<int, double>());
|
|
|
|
static_assert(
|
|
check_swappable_with_including_lvalue_ref_to_volatile<int*, int*>());
|
|
static_assert(
|
|
!check_swappable_with_including_lvalue_ref_to_volatile<int, int*>());
|
|
static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int (*)(), int (*)()>());
|
|
static_assert(
|
|
!check_swappable_with_including_lvalue_ref_to_volatile<int, int (*)()>());
|
|
|
|
struct S {};
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<int, S>());
|
|
static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int S::*, int S::*>());
|
|
static_assert(
|
|
!check_swappable_with_including_lvalue_ref_to_volatile<int, int S::*>());
|
|
static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int (S::*)(), int (S::*)()>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int, int (S::*)()>());
|
|
static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int (S::*)() noexcept, int (S::*)() noexcept>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int (S::*)() noexcept, int (S::*)()>());
|
|
static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int (S::*)() const, int (S::*)() const>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int (S::*)() const, int (S::*)()>());
|
|
static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int (S::*)() const noexcept, int (S::*)() const noexcept>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int (S::*)() const, int (S::*)() const noexcept>());
|
|
static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int (S::*)() volatile, int (S::*)() volatile>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int (S::*)() volatile, int (S::*)()>());
|
|
static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int (S::*)() const volatile, int (S::*)() const volatile>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int (S::*)() const volatile, int (S::*)()>());
|
|
|
|
static_assert(
|
|
check_swappable_with_including_lvalue_ref_to_volatile<int[5], int[5]>());
|
|
static_assert(
|
|
!check_swappable_with_including_lvalue_ref_to_volatile<int[5], int[6]>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int[5], double[5]>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int[5], double[6]>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<int[5][6],
|
|
int[5]>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<int[5][6],
|
|
int[6]>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int[5][6], double[5]>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int[5][6], double[6]>());
|
|
static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int[5][6], int[5][6]>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int[5][6], int[5][4]>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int[5][6], int[6][5]>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int[5][6], double[5][6]>());
|
|
static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
|
|
int[5][6], double[6][5]>());
|
|
|
|
// always false
|
|
static_assert(!check_swappable_with_impl<void, void>());
|
|
static_assert(!check_swappable_with_impl<int, void>());
|
|
static_assert(!check_swappable_with_impl<int&, void>());
|
|
static_assert(!check_swappable_with_impl<void, int>());
|
|
static_assert(!check_swappable_with_impl<void, int&>());
|
|
static_assert(!check_swappable_with_impl<int, int()>());
|
|
static_assert(!check_swappable_with_impl<int, int (&)()>());
|
|
} // namespace fundamental
|
|
|
|
namespace adl {
|
|
static_assert(
|
|
check_swappable_with<lvalue_adl_swappable, lvalue_adl_swappable>());
|
|
static_assert(check_swappable_with<lvalue_rvalue_adl_swappable,
|
|
lvalue_rvalue_adl_swappable>());
|
|
static_assert(check_swappable_with<rvalue_lvalue_adl_swappable,
|
|
rvalue_lvalue_adl_swappable>());
|
|
static_assert(
|
|
check_swappable_with_impl<rvalue_adl_swappable, rvalue_adl_swappable>());
|
|
static_assert(!check_swappable_with_impl<lvalue_rvalue_adl_swappable&,
|
|
lvalue_rvalue_adl_swappable&&>());
|
|
|
|
struct s1 {};
|
|
struct no_common_reference_with_s1 {
|
|
friend void swap(s1&, no_common_reference_with_s1&);
|
|
friend void swap(no_common_reference_with_s1&, s1&);
|
|
};
|
|
static_assert(!check_swappable_with<s1, no_common_reference_with_s1>());
|
|
|
|
struct one_way_swappable_with_s1 {
|
|
friend void swap(s1&, one_way_swappable_with_s1&);
|
|
operator s1();
|
|
};
|
|
static_assert(std::common_reference_with<one_way_swappable_with_s1, s1>);
|
|
static_assert(!check_swappable_with<one_way_swappable_with_s1, s1>());
|
|
|
|
struct one_way_swappable_with_s1_other_way {
|
|
friend void swap(one_way_swappable_with_s1_other_way&, s1&);
|
|
operator s1();
|
|
};
|
|
static_assert(
|
|
std::common_reference_with<one_way_swappable_with_s1_other_way, s1>);
|
|
static_assert(!check_swappable_with<one_way_swappable_with_s1_other_way, s1>());
|
|
|
|
struct can_swap_with_s1_but_not_swappable {
|
|
can_swap_with_s1_but_not_swappable(can_swap_with_s1_but_not_swappable&&) =
|
|
delete;
|
|
friend void swap(s1&, can_swap_with_s1_but_not_swappable&);
|
|
friend void swap(can_swap_with_s1_but_not_swappable&, s1&);
|
|
|
|
operator s1() const;
|
|
};
|
|
static_assert(
|
|
std::common_reference_with<can_swap_with_s1_but_not_swappable, s1>);
|
|
static_assert(!std::swappable<can_swap_with_s1_but_not_swappable>);
|
|
static_assert(
|
|
!check_swappable_with<can_swap_with_s1_but_not_swappable&, s1&>());
|
|
|
|
struct swappable_with_s1 {
|
|
friend void swap(s1&, swappable_with_s1&);
|
|
friend void swap(swappable_with_s1&, s1&);
|
|
operator s1() const;
|
|
};
|
|
static_assert(check_swappable_with<swappable_with_s1, s1>());
|
|
|
|
struct swappable_with_const_s1_but_not_swappable {
|
|
swappable_with_const_s1_but_not_swappable(
|
|
swappable_with_const_s1_but_not_swappable const&);
|
|
swappable_with_const_s1_but_not_swappable(
|
|
swappable_with_const_s1_but_not_swappable const&&);
|
|
swappable_with_const_s1_but_not_swappable&
|
|
operator=(swappable_with_const_s1_but_not_swappable const&);
|
|
swappable_with_const_s1_but_not_swappable&
|
|
operator=(swappable_with_const_s1_but_not_swappable const&&);
|
|
|
|
friend void swap(s1 const&, swappable_with_const_s1_but_not_swappable const&);
|
|
friend void swap(swappable_with_const_s1_but_not_swappable const&, s1 const&);
|
|
|
|
operator s1 const &() const;
|
|
};
|
|
static_assert(
|
|
!std::swappable<swappable_with_const_s1_but_not_swappable const&>);
|
|
static_assert(!std::swappable_with<
|
|
swappable_with_const_s1_but_not_swappable const&, s1 const&>);
|
|
|
|
struct swappable_with_volatile_s1_but_not_swappable {
|
|
swappable_with_volatile_s1_but_not_swappable(
|
|
swappable_with_volatile_s1_but_not_swappable volatile&);
|
|
swappable_with_volatile_s1_but_not_swappable(
|
|
swappable_with_volatile_s1_but_not_swappable volatile&&);
|
|
swappable_with_volatile_s1_but_not_swappable&
|
|
operator=(swappable_with_volatile_s1_but_not_swappable volatile&);
|
|
swappable_with_volatile_s1_but_not_swappable&
|
|
operator=(swappable_with_volatile_s1_but_not_swappable volatile&&);
|
|
|
|
friend void swap(s1 volatile&,
|
|
swappable_with_volatile_s1_but_not_swappable volatile&);
|
|
friend void swap(swappable_with_volatile_s1_but_not_swappable volatile&,
|
|
s1 volatile&);
|
|
|
|
operator s1 volatile &() volatile;
|
|
};
|
|
static_assert(
|
|
!std::swappable<swappable_with_volatile_s1_but_not_swappable volatile&>);
|
|
static_assert(
|
|
!std::swappable_with<swappable_with_volatile_s1_but_not_swappable volatile&,
|
|
s1 volatile&>);
|
|
|
|
struct swappable_with_cv_s1_but_not_swappable {
|
|
swappable_with_cv_s1_but_not_swappable(
|
|
swappable_with_cv_s1_but_not_swappable const volatile&);
|
|
swappable_with_cv_s1_but_not_swappable(
|
|
swappable_with_cv_s1_but_not_swappable const volatile&&);
|
|
swappable_with_cv_s1_but_not_swappable&
|
|
operator=(swappable_with_cv_s1_but_not_swappable const volatile&);
|
|
swappable_with_cv_s1_but_not_swappable&
|
|
operator=(swappable_with_cv_s1_but_not_swappable const volatile&&);
|
|
|
|
friend void swap(s1 const volatile&,
|
|
swappable_with_cv_s1_but_not_swappable const volatile&);
|
|
friend void swap(swappable_with_cv_s1_but_not_swappable const volatile&,
|
|
s1 const volatile&);
|
|
|
|
operator s1 const volatile &() const volatile;
|
|
};
|
|
static_assert(
|
|
!std::swappable<swappable_with_cv_s1_but_not_swappable const volatile&>);
|
|
static_assert(
|
|
!std::swappable_with<swappable_with_cv_s1_but_not_swappable const volatile&,
|
|
s1 const volatile&>);
|
|
|
|
struct s2 {
|
|
friend void swap(s2 const&, s2 const&);
|
|
friend void swap(s2 volatile&, s2 volatile&);
|
|
friend void swap(s2 const volatile&, s2 const volatile&);
|
|
};
|
|
|
|
struct swappable_with_const_s2 {
|
|
swappable_with_const_s2(swappable_with_const_s2 const&);
|
|
swappable_with_const_s2(swappable_with_const_s2 const&&);
|
|
swappable_with_const_s2& operator=(swappable_with_const_s2 const&);
|
|
swappable_with_const_s2& operator=(swappable_with_const_s2 const&&);
|
|
|
|
friend void swap(swappable_with_const_s2 const&,
|
|
swappable_with_const_s2 const&);
|
|
friend void swap(s2 const&, swappable_with_const_s2 const&);
|
|
friend void swap(swappable_with_const_s2 const&, s2 const&);
|
|
|
|
operator s2 const &() const;
|
|
};
|
|
static_assert(std::swappable_with<swappable_with_const_s2 const&, s2 const&>);
|
|
|
|
struct swappable_with_volatile_s2 {
|
|
swappable_with_volatile_s2(swappable_with_volatile_s2 volatile&);
|
|
swappable_with_volatile_s2(swappable_with_volatile_s2 volatile&&);
|
|
swappable_with_volatile_s2& operator=(swappable_with_volatile_s2 volatile&);
|
|
swappable_with_volatile_s2& operator=(swappable_with_volatile_s2 volatile&&);
|
|
|
|
friend void swap(swappable_with_volatile_s2 volatile&,
|
|
swappable_with_volatile_s2 volatile&);
|
|
friend void swap(s2 volatile&, swappable_with_volatile_s2 volatile&);
|
|
friend void swap(swappable_with_volatile_s2 volatile&, s2 volatile&);
|
|
|
|
operator s2 volatile &() volatile;
|
|
};
|
|
static_assert(
|
|
std::swappable_with<swappable_with_volatile_s2 volatile&, s2 volatile&>);
|
|
|
|
struct swappable_with_cv_s2 {
|
|
swappable_with_cv_s2(swappable_with_cv_s2 const volatile&);
|
|
swappable_with_cv_s2(swappable_with_cv_s2 const volatile&&);
|
|
swappable_with_cv_s2& operator=(swappable_with_cv_s2 const volatile&);
|
|
swappable_with_cv_s2& operator=(swappable_with_cv_s2 const volatile&&);
|
|
|
|
friend void swap(swappable_with_cv_s2 const volatile&,
|
|
swappable_with_cv_s2 const volatile&);
|
|
friend void swap(s2 const volatile&, swappable_with_cv_s2 const volatile&);
|
|
friend void swap(swappable_with_cv_s2 const volatile&, s2 const volatile&);
|
|
|
|
operator s2 const volatile &() const volatile;
|
|
};
|
|
static_assert(std::swappable_with<swappable_with_cv_s2 const volatile&,
|
|
s2 const volatile&>);
|
|
|
|
struct swappable_with_rvalue_ref_to_s1_but_not_swappable {
|
|
friend void swap(swappable_with_rvalue_ref_to_s1_but_not_swappable&&,
|
|
swappable_with_rvalue_ref_to_s1_but_not_swappable&&);
|
|
friend void swap(s1&&, swappable_with_rvalue_ref_to_s1_but_not_swappable&&);
|
|
friend void swap(swappable_with_rvalue_ref_to_s1_but_not_swappable&&, s1&&);
|
|
|
|
operator s1() const;
|
|
};
|
|
static_assert(
|
|
!std::swappable<swappable_with_rvalue_ref_to_s1_but_not_swappable const&&>);
|
|
static_assert(
|
|
!std::swappable_with<
|
|
swappable_with_rvalue_ref_to_s1_but_not_swappable const&&, s1 const&&>);
|
|
|
|
struct swappable_with_rvalue_ref_to_const_s1_but_not_swappable {
|
|
friend void
|
|
swap(s1 const&&,
|
|
swappable_with_rvalue_ref_to_const_s1_but_not_swappable const&&);
|
|
friend void
|
|
swap(swappable_with_rvalue_ref_to_const_s1_but_not_swappable const&&,
|
|
s1 const&&);
|
|
|
|
operator s1 const() const;
|
|
};
|
|
static_assert(!std::swappable<
|
|
swappable_with_rvalue_ref_to_const_s1_but_not_swappable const&&>);
|
|
static_assert(!std::swappable_with<
|
|
swappable_with_rvalue_ref_to_const_s1_but_not_swappable const&&,
|
|
s1 const&&>);
|
|
|
|
struct swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable {
|
|
swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable(
|
|
swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&);
|
|
swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable(
|
|
swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&);
|
|
swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable& operator=(
|
|
swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&);
|
|
swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable& operator=(
|
|
swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&);
|
|
|
|
friend void
|
|
swap(s1 volatile&&,
|
|
swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&);
|
|
friend void
|
|
swap(swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&,
|
|
s1 volatile&&);
|
|
|
|
operator s1 volatile &&() volatile&&;
|
|
};
|
|
static_assert(
|
|
!std::swappable<
|
|
swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&>);
|
|
static_assert(
|
|
!std::swappable_with<
|
|
swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&,
|
|
s1 volatile&&>);
|
|
|
|
struct swappable_with_rvalue_ref_to_cv_s1_but_not_swappable {
|
|
swappable_with_rvalue_ref_to_cv_s1_but_not_swappable(
|
|
swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&);
|
|
swappable_with_rvalue_ref_to_cv_s1_but_not_swappable(
|
|
swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&);
|
|
swappable_with_rvalue_ref_to_cv_s1_but_not_swappable& operator=(
|
|
swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&);
|
|
swappable_with_rvalue_ref_to_cv_s1_but_not_swappable& operator=(
|
|
swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&);
|
|
|
|
friend void
|
|
swap(s1 const volatile&&,
|
|
swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&);
|
|
friend void
|
|
swap(swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&,
|
|
s1 const volatile&&);
|
|
|
|
operator s1 const volatile &&() const volatile&&;
|
|
};
|
|
static_assert(
|
|
!std::swappable<
|
|
swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&>);
|
|
static_assert(
|
|
!std::swappable_with<
|
|
swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&,
|
|
s1 const volatile&&>);
|
|
|
|
struct s3 {
|
|
friend void swap(s3&&, s3&&);
|
|
friend void swap(s3 const&&, s3 const&&);
|
|
friend void swap(s3 volatile&&, s3 volatile&&);
|
|
friend void swap(s3 const volatile&&, s3 const volatile&&);
|
|
};
|
|
|
|
struct swappable_with_rvalue_ref_to_s3 {
|
|
friend void swap(swappable_with_rvalue_ref_to_s3&&,
|
|
swappable_with_rvalue_ref_to_s3&&);
|
|
friend void swap(s3&&, swappable_with_rvalue_ref_to_s3&&);
|
|
friend void swap(swappable_with_rvalue_ref_to_s3&&, s3&&);
|
|
|
|
operator s3() const;
|
|
};
|
|
static_assert(std::swappable_with<swappable_with_rvalue_ref_to_s3&&, s3&&>);
|
|
|
|
struct swappable_with_rvalue_ref_to_const_s3 {
|
|
swappable_with_rvalue_ref_to_const_s3(
|
|
swappable_with_rvalue_ref_to_const_s3 const&);
|
|
swappable_with_rvalue_ref_to_const_s3(
|
|
swappable_with_rvalue_ref_to_const_s3 const&&);
|
|
swappable_with_rvalue_ref_to_const_s3&
|
|
operator=(swappable_with_rvalue_ref_to_const_s3 const&);
|
|
swappable_with_rvalue_ref_to_const_s3&
|
|
operator=(swappable_with_rvalue_ref_to_const_s3 const&&);
|
|
|
|
friend void swap(swappable_with_rvalue_ref_to_const_s3 const&&,
|
|
swappable_with_rvalue_ref_to_const_s3 const&&);
|
|
friend void swap(s3 const&&, swappable_with_rvalue_ref_to_const_s3 const&&);
|
|
friend void swap(swappable_with_rvalue_ref_to_const_s3 const&&, s3 const&&);
|
|
|
|
operator s3() const;
|
|
};
|
|
static_assert(std::swappable_with<swappable_with_rvalue_ref_to_const_s3 const&&,
|
|
s3 const&&>);
|
|
|
|
struct swappable_with_rvalue_ref_to_volatile_s3 {
|
|
swappable_with_rvalue_ref_to_volatile_s3(
|
|
swappable_with_rvalue_ref_to_volatile_s3 volatile&);
|
|
swappable_with_rvalue_ref_to_volatile_s3(
|
|
swappable_with_rvalue_ref_to_volatile_s3 volatile&&);
|
|
swappable_with_rvalue_ref_to_volatile_s3&
|
|
operator=(swappable_with_rvalue_ref_to_volatile_s3 volatile&);
|
|
swappable_with_rvalue_ref_to_volatile_s3&
|
|
operator=(swappable_with_rvalue_ref_to_volatile_s3 volatile&&);
|
|
|
|
friend void swap(swappable_with_rvalue_ref_to_volatile_s3 volatile&&,
|
|
swappable_with_rvalue_ref_to_volatile_s3 volatile&&);
|
|
friend void swap(s3 volatile&&,
|
|
swappable_with_rvalue_ref_to_volatile_s3 volatile&&);
|
|
friend void swap(swappable_with_rvalue_ref_to_volatile_s3 volatile&&,
|
|
s3 volatile&&);
|
|
|
|
operator s3 volatile &&() volatile;
|
|
};
|
|
static_assert(
|
|
std::swappable_with<swappable_with_rvalue_ref_to_volatile_s3 volatile&&,
|
|
s3 volatile&&>);
|
|
|
|
struct swappable_with_rvalue_ref_to_cv_s3 {
|
|
swappable_with_rvalue_ref_to_cv_s3(
|
|
swappable_with_rvalue_ref_to_cv_s3 const volatile&);
|
|
swappable_with_rvalue_ref_to_cv_s3(
|
|
swappable_with_rvalue_ref_to_cv_s3 const volatile&&);
|
|
swappable_with_rvalue_ref_to_cv_s3&
|
|
operator=(swappable_with_rvalue_ref_to_cv_s3 const volatile&);
|
|
swappable_with_rvalue_ref_to_cv_s3&
|
|
operator=(swappable_with_rvalue_ref_to_cv_s3 const volatile&&);
|
|
|
|
friend void swap(swappable_with_rvalue_ref_to_cv_s3 const volatile&&,
|
|
swappable_with_rvalue_ref_to_cv_s3 const volatile&&);
|
|
friend void swap(s3 const volatile&&,
|
|
swappable_with_rvalue_ref_to_cv_s3 const volatile&&);
|
|
friend void swap(swappable_with_rvalue_ref_to_cv_s3 const volatile&&,
|
|
s3 const volatile&&);
|
|
|
|
operator s3 const volatile &&() const volatile;
|
|
};
|
|
static_assert(
|
|
std::swappable_with<swappable_with_rvalue_ref_to_cv_s3 const volatile&&,
|
|
s3 const volatile&&>);
|
|
|
|
namespace union_swap {
|
|
union adl_swappable {
|
|
int x;
|
|
double y;
|
|
|
|
operator int() const;
|
|
};
|
|
|
|
void swap(adl_swappable&, adl_swappable&) noexcept;
|
|
void swap(adl_swappable&&, adl_swappable&&) noexcept;
|
|
void swap(adl_swappable&, int&) noexcept;
|
|
void swap(int&, adl_swappable&) noexcept;
|
|
} // namespace union_swap
|
|
static_assert(
|
|
std::swappable_with<union_swap::adl_swappable, union_swap::adl_swappable>);
|
|
static_assert(std::swappable_with<union_swap::adl_swappable&,
|
|
union_swap::adl_swappable&>);
|
|
static_assert(std::swappable_with<union_swap::adl_swappable&&,
|
|
union_swap::adl_swappable&&>);
|
|
static_assert(std::swappable_with<union_swap::adl_swappable&, int&>);
|
|
} // namespace adl
|
|
|
|
namespace standard_types {
|
|
static_assert(
|
|
check_swappable_with<std::array<int, 10>, std::array<int, 10> >());
|
|
static_assert(
|
|
!check_swappable_with<std::array<int, 10>, std::array<double, 10> >());
|
|
static_assert(check_swappable_with<std::deque<int>, std::deque<int> >());
|
|
static_assert(!check_swappable_with<std::deque<int>, std::vector<int> >());
|
|
static_assert(
|
|
check_swappable_with<std::forward_list<int>, std::forward_list<int> >());
|
|
static_assert(
|
|
!check_swappable_with<std::forward_list<int>, std::vector<int> >());
|
|
static_assert(check_swappable_with<std::list<int>, std::list<int> >());
|
|
static_assert(!check_swappable_with<std::list<int>, std::vector<int> >());
|
|
|
|
static_assert(
|
|
check_swappable_with<std::map<int, void*>, std::map<int, void*> >());
|
|
static_assert(!check_swappable_with<std::map<int, void*>, std::vector<int> >());
|
|
static_assert(check_swappable_with<std::optional<std::vector<int> >,
|
|
std::optional<std::vector<int> > >());
|
|
static_assert(!check_swappable_with<std::optional<std::vector<int> >,
|
|
std::vector<int> >());
|
|
static_assert(check_swappable_with<std::vector<int>, std::vector<int> >());
|
|
static_assert(!check_swappable_with<std::vector<int>, int>());
|
|
} // namespace standard_types
|
|
|
|
namespace types_with_purpose {
|
|
static_assert(!check_swappable_with<DeletedMoveCtor, DeletedMoveCtor>());
|
|
static_assert(!check_swappable_with<ImplicitlyDeletedMoveCtor,
|
|
ImplicitlyDeletedMoveCtor>());
|
|
static_assert(!check_swappable_with<DeletedMoveAssign, DeletedMoveAssign>());
|
|
static_assert(!check_swappable_with<ImplicitlyDeletedMoveAssign,
|
|
ImplicitlyDeletedMoveAssign>());
|
|
static_assert(!check_swappable_with<NonMovable, NonMovable>());
|
|
static_assert(
|
|
!check_swappable_with<DerivedFromNonMovable, DerivedFromNonMovable>());
|
|
static_assert(!check_swappable_with<HasANonMovable, HasANonMovable>());
|
|
} // namespace types_with_purpose
|
|
|
|
namespace LWG3175 {
|
|
// Example taken directly from [concept.swappable]
|
|
template <class T, std::swappable_with<T> U>
|
|
constexpr void value_swap(T&& t, U&& u) {
|
|
std::ranges::swap(std::forward<T>(t), std::forward<U>(u));
|
|
}
|
|
|
|
template <std::swappable T>
|
|
constexpr void lv_swap(T& t1, T& t2) {
|
|
std::ranges::swap(t1, t2);
|
|
}
|
|
|
|
namespace N {
|
|
struct A {
|
|
int m;
|
|
};
|
|
struct Proxy {
|
|
A* a;
|
|
constexpr Proxy(A& a_) : a{&a_} {}
|
|
friend constexpr void swap(Proxy x, Proxy y) {
|
|
std::ranges::swap(*x.a, *y.a);
|
|
}
|
|
};
|
|
constexpr Proxy proxy(A& a) { return Proxy{a}; }
|
|
} // namespace N
|
|
|
|
constexpr bool CheckRegression() {
|
|
int i = 1, j = 2;
|
|
lv_swap(i, j);
|
|
assert(i == 2 && j == 1);
|
|
|
|
N::A a1 = {5}, a2 = {-5};
|
|
value_swap(a1, proxy(a2));
|
|
assert(a1.m == -5 && a2.m == 5);
|
|
return true;
|
|
}
|
|
|
|
static_assert(CheckRegression());
|
|
} // namespace LWG3175
|