diff options
Diffstat (limited to 'libcxx/test/std/utilities')
8 files changed, 534 insertions, 61 deletions
diff --git a/libcxx/test/std/utilities/memory/unique.ptr/unique.ptr.special/swap.pass.cpp b/libcxx/test/std/utilities/memory/unique.ptr/unique.ptr.special/swap.pass.cpp index 44b746fbcfd..c525137d484 100644 --- a/libcxx/test/std/utilities/memory/unique.ptr/unique.ptr.special/swap.pass.cpp +++ b/libcxx/test/std/utilities/memory/unique.ptr/unique.ptr.special/swap.pass.cpp @@ -16,6 +16,7 @@ #include <memory> #include <cassert> +#include "test_macros.h" #include "../deleter.h" struct A @@ -34,6 +35,16 @@ struct A int A::count = 0; +template <class T> +struct NonSwappableDeleter { + explicit NonSwappableDeleter(int) {} + NonSwappableDeleter& operator=(NonSwappableDeleter const&) { return *this; } + void operator()(T*) const {} +private: + NonSwappableDeleter(NonSwappableDeleter const&); + +}; + int main() { { @@ -74,4 +85,18 @@ int main() assert(A::count == 6); } assert(A::count == 0); +#if TEST_STD_VER >= 11 + { + // test that unique_ptr's specialized swap is disabled when the deleter + // is non-swappable. Instead we should pick up the generic swap(T, T) + // and perform 3 move constructions. + typedef NonSwappableDeleter<int> D; + D d(42); + int x = 42; + int y = 43; + std::unique_ptr<int, D&> p(&x, d); + std::unique_ptr<int, D&> p2(&y, d); + std::swap(p, p2); + } +#endif } diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable.pass.cpp new file mode 100644 index 00000000000..2465987355b --- /dev/null +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// type_traits + +// is_swappable + +#include <type_traits> +#include <vector> +#include "test_macros.h" + +namespace MyNS { + +// Make the test types non-copyable so that generic std::swap is not valid. +struct A { + A(A const&) = delete; + A& operator=(A const&) = delete; +}; + +struct B { + B(B const&) = delete; + B& operator=(B const&) = delete; +}; + +void swap(A&, A&) noexcept {} +void swap(B&, B&) {} + +struct M { + M(M const&) = delete; + M& operator=(M const&) = delete; +}; + +void swap(M&&, M&&) noexcept {} + +struct ThrowingMove { + ThrowingMove(ThrowingMove&&){} + ThrowingMove& operator=(ThrowingMove&&) {} +}; + +} // namespace MyNS + +int main() +{ + using namespace MyNS; + { + // Test that is_swappable applies an lvalue reference to the type. + static_assert(std::is_nothrow_swappable<int>::value, ""); + static_assert(std::is_nothrow_swappable<int&>::value, ""); + static_assert(!std::is_nothrow_swappable<M>::value, ""); + static_assert(!std::is_nothrow_swappable<M&&>::value, ""); + } + { + // Test that it correctly deduces the noexcept of swap. + static_assert(std::is_nothrow_swappable<A>::value, ""); + static_assert(!std::is_nothrow_swappable<B>::value + && std::is_swappable<B>::value, ""); + static_assert(!std::is_nothrow_swappable<ThrowingMove>::value + && std::is_swappable<ThrowingMove>::value); + } + { + // Test that it doesn't drop the qualifiers + static_assert(!std::is_nothrow_swappable<const A>::value, ""); + } + { + // test non-referenceable types + static_assert(!std::is_nothrow_swappable<void>::value, ""); + static_assert(!std::is_nothrow_swappable<int() const>::value, ""); + static_assert(!std::is_nothrow_swappable<int(int, ...) const &>::value, ""); + } + { + // test for presence of is_nothrow_swappable_v + static_assert(std::is_nothrow_swappable_v<int>); + static_assert(!std::is_nothrow_swappable_v<void>); + } +} diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp new file mode 100644 index 00000000000..54c0a040398 --- /dev/null +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// type_traits + +// is_nothrow_swappable_with + +#include <type_traits> +#include <vector> +#include "test_macros.h" + +namespace MyNS { + +struct A { + A(A const&) = delete; + A& operator=(A const&) = delete; +}; + +struct B { + B(B const&) = delete; + B& operator=(B const&) = delete; +}; + +struct C {}; +struct D {}; + +void swap(A&, A&) {} + +void swap(A&, B&) noexcept {} +void swap(B&, A&) noexcept {} + +void swap(A&, C&) noexcept {} +void swap(C&, A&) {} + +struct M {}; + +void swap(M&&, M&&) noexcept {} + +} // namespace MyNS + +int main() +{ + using namespace MyNS; + { + // Test that is_swappable_with doesn't apply an lvalue reference + // to the type. Instead it is up to the user. + static_assert(!std::is_nothrow_swappable_with<int, int>::value, ""); + static_assert(std::is_nothrow_swappable_with<int&, int&>::value, ""); + static_assert(std::is_nothrow_swappable_with<M, M>::value, ""); + static_assert(std::is_swappable_with<A&, A&>::value && + !std::is_nothrow_swappable_with<A&, A&>::value, ""); + } + { + // test that hetrogenius swap is allowed only if both 'swap(A, B)' and + // 'swap(B, A)' are valid. + static_assert(std::is_nothrow_swappable_with<A&, B&>::value, ""); + static_assert(!std::is_nothrow_swappable_with<A&, C&>::value && + std::is_swappable_with<A&, C&>::value, ""); + static_assert(!std::is_nothrow_swappable_with<D&, C&>::value, ""); + } + { + // test we guard against cv void inputs as required. + static_assert(!std::is_nothrow_swappable_with_v<void, int>); + static_assert(!std::is_nothrow_swappable_with_v<int, void>); + static_assert(!std::is_nothrow_swappable_with_v<const void, const volatile void>); + + } + { + // test for presense of is_nothrow_swappable_with_v + static_assert(std::is_nothrow_swappable_with_v<int&, int&>); + static_assert(!std::is_nothrow_swappable_with_v<int&&, int&&>); + } +} diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable.pass.cpp new file mode 100644 index 00000000000..43a0a4fe46b --- /dev/null +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable.pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// type_traits + +// is_swappable + +#include <type_traits> +#include <utility> +#include <vector> +#include "test_macros.h" + +namespace MyNS { + +// Make the test types non-copyable so that generic std::swap is not valid. +struct A { + A(A const&) = delete; + A& operator=(A const&) = delete; +}; + +struct B { + B(B const&) = delete; + B& operator=(B const&) = delete; +}; + +struct C {}; +struct D {}; + +void swap(A&, A&) {} + +void swap(A&, B&) {} +void swap(B&, A&) {} + +void swap(A&, C&) {} // missing swap(C, A) +void swap(D&, C&) {} + +struct M { + M(M const&) = delete; + M& operator=(M const&) = delete; +}; + +void swap(M&&, M&&) {} + +} // namespace MyNS + +int main() +{ + using namespace MyNS; + { + // Test that is_swappable applies an lvalue reference to the type. + static_assert(std::is_swappable<A>::value, ""); + static_assert(std::is_swappable<A&>::value, ""); + static_assert(!std::is_swappable<M>::value, ""); + static_assert(!std::is_swappable<M&&>::value, ""); + } + static_assert(!std::is_swappable<B>::value, ""); + static_assert(std::is_swappable<C>::value, ""); + { + // test non-referencable types + static_assert(!std::is_swappable<void>::value, ""); + static_assert(!std::is_swappable<int() const>::value, ""); + static_assert(!std::is_swappable<int() &>::value, ""); + } + { + // test for presense of is_swappable_v + static_assert(std::is_swappable_v<int>); + static_assert(!std::is_swappable_v<M>); + } +} diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable_include_order.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable_include_order.pass.cpp new file mode 100644 index 00000000000..8bd5614065d --- /dev/null +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable_include_order.pass.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// type_traits + +// is_swappable + +// IMPORTANT: The include order is part of the test. We want to pick up +// the following definitions in this order: +// 1) is_swappable, is_nothrow_swappable +// 2) iter_swap, swap_ranges +// 3) swap(T (&)[N], T(&)[N] +// This test checks that (1) and (2) see forward declarations +// for (3). +#include <type_traits> +#include <algorithm> +#include <utility> + +#include "test_macros.h" + +int main() +{ + // Use a builtin type so we don't get ADL lookup. + typedef double T[42][50]; + { + static_assert(std::__is_swappable<T>::value, ""); +#if TEST_STD_VER > 14 + static_assert(std::is_swappable_v<T>); +#endif + } + { + T t1 = {}; + T t2 = {}; + std::iter_swap(t1, t2); + std::swap_ranges(t1, t1 + 42, t2); + } +} diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable_with.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable_with.pass.cpp new file mode 100644 index 00000000000..9d470c156dc --- /dev/null +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable_with.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// type_traits + +// is_swappable_with + +#include <type_traits> +#include <vector> +#include "test_macros.h" + +namespace MyNS { + +struct A { + A(A const&) = delete; + A& operator=(A const&) = delete; +}; + +struct B { + B(B const&) = delete; + B& operator=(B const&) = delete; +}; + +struct C {}; +struct D {}; + +void swap(A&, A&) {} + +void swap(A&, B&) {} +void swap(B&, A&) {} + +void swap(A&, C&) {} // missing swap(C, A) +void swap(D&, C&) {} + +struct M {}; + +void swap(M&&, M&&) {} + +} // namespace MyNS + +int main() +{ + using namespace MyNS; + { + // Test that is_swappable_with doesn't apply an lvalue reference + // to the type. Instead it is up to the user. + static_assert(!std::is_swappable_with<int, int>::value, ""); + static_assert(std::is_swappable_with<int&, int&>::value, ""); + static_assert(std::is_swappable_with<M, M>::value, ""); + static_assert(std::is_swappable_with<A&, A&>::value, ""); + } + { + // test that heterogeneous swap is allowed only if both 'swap(A, B)' and + // 'swap(B, A)' are valid. + static_assert(std::is_swappable_with<A&, B&>::value, ""); + static_assert(!std::is_swappable_with<A&, C&>::value, ""); + static_assert(!std::is_swappable_with<D&, C&>::value, ""); + } + { + // test that cv void is guarded against as required. + static_assert(!std::is_swappable_with_v<void, int>); + static_assert(!std::is_swappable_with_v<int, void>); + static_assert(!std::is_swappable_with_v<const void, const volatile void>); + } + { + // test for presence of is_swappable_with_v + static_assert(std::is_swappable_with_v<int&, int&>); + static_assert(!std::is_swappable_with_v<D&, C&>); + } +} diff --git a/libcxx/test/std/utilities/utility/utility.swap/swap.pass.cpp b/libcxx/test/std/utilities/utility/utility.swap/swap.pass.cpp index 8606611f660..c9c9f3b5276 100644 --- a/libcxx/test/std/utilities/utility/utility.swap/swap.pass.cpp +++ b/libcxx/test/std/utilities/utility/utility.swap/swap.pass.cpp @@ -16,38 +16,88 @@ #include <utility> #include <cassert> -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #include <memory> -#endif -void -test() -{ - int i = 1; - int j = 2; - std::swap(i, j); - assert(i == 2); - assert(j == 1); -} +#include "test_macros.h" -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if TEST_STD_VER >= 11 +struct CopyOnly { + CopyOnly() {} + CopyOnly(CopyOnly const&) noexcept {} + CopyOnly& operator=(CopyOnly const&) { return *this; } +}; -void -test1() -{ - std::unique_ptr<int> i(new int(1)); - std::unique_ptr<int> j(new int(2)); - std::swap(i, j); - assert(*i == 2); - assert(*j == 1); -} +struct MoveOnly { + MoveOnly() {} + MoveOnly(MoveOnly&&) {} + MoveOnly& operator=(MoveOnly&&) noexcept { return *this; } +}; + +struct NoexceptMoveOnly { + NoexceptMoveOnly() {} + NoexceptMoveOnly(NoexceptMoveOnly&&) noexcept {} + NoexceptMoveOnly& operator=(NoexceptMoveOnly&&) noexcept { return *this; } +}; + +struct NotMoveConstructible { + NotMoveConstructible& operator=(NotMoveConstructible&&) { return *this; } +private: + NotMoveConstructible(NotMoveConstructible&&); +}; + +struct NotMoveAssignable { + NotMoveAssignable(NotMoveAssignable&&); +private: + NotMoveAssignable& operator=(NotMoveAssignable&&); +}; + +template <class Tp> +auto can_swap_test(int) -> decltype(std::swap(std::declval<Tp>(), std::declval<Tp>())); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES +template <class Tp> +auto can_swap_test(...) -> std::false_type; + +template <class Tp> +constexpr bool can_swap() { + return std::is_same<decltype(can_swap_test<Tp>(0)), void>::value; +} +#endif int main() { - test(); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - test1(); + + { + int i = 1; + int j = 2; + std::swap(i, j); + assert(i == 2); + assert(j == 1); + } +#if TEST_STD_VER >= 11 + { + + std::unique_ptr<int> i(new int(1)); + std::unique_ptr<int> j(new int(2)); + std::swap(i, j); + assert(*i == 2); + assert(*j == 1); + + } + { + // test that the swap + static_assert(can_swap<CopyOnly&>(), ""); + static_assert(can_swap<MoveOnly&>(), ""); + static_assert(can_swap<NoexceptMoveOnly&>(), ""); + + static_assert(!can_swap<NotMoveConstructible&>(), ""); + static_assert(!can_swap<NotMoveAssignable&>(), ""); + + CopyOnly c; + MoveOnly m; + NoexceptMoveOnly nm; + static_assert(!noexcept(std::swap(c, c)), ""); + static_assert(!noexcept(std::swap(m, m)), ""); + static_assert(noexcept(std::swap(nm, nm)), ""); + } #endif } diff --git a/libcxx/test/std/utilities/utility/utility.swap/swap_array.pass.cpp b/libcxx/test/std/utilities/utility/utility.swap/swap_array.pass.cpp index b1209c3c365..ad39934b20c 100644 --- a/libcxx/test/std/utilities/utility/utility.swap/swap_array.pass.cpp +++ b/libcxx/test/std/utilities/utility/utility.swap/swap_array.pass.cpp @@ -16,50 +16,86 @@ #include <utility> #include <cassert> -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #include <memory> -#endif -void -test() -{ - int i[3] = {1, 2, 3}; - int j[3] = {4, 5, 6}; - std::swap(i, j); - assert(i[0] == 4); - assert(i[1] == 5); - assert(i[2] == 6); - assert(j[0] == 1); - assert(j[1] == 2); - assert(j[2] == 3); -} +#include "test_macros.h" -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES -void -test1() -{ - std::unique_ptr<int> i[3]; - for (int k = 0; k < 3; ++k) - i[k].reset(new int(k+1)); - std::unique_ptr<int> j[3]; - for (int k = 0; k < 3; ++k) - j[k].reset(new int(k+4)); - std::swap(i, j); - assert(*i[0] == 4); - assert(*i[1] == 5); - assert(*i[2] == 6); - assert(*j[0] == 1); - assert(*j[1] == 2); - assert(*j[2] == 3); +#if TEST_STD_VER >= 11 +struct CopyOnly { + CopyOnly() {} + CopyOnly(CopyOnly const&) noexcept {} + CopyOnly& operator=(CopyOnly const&) { return *this; } +}; + + +struct NoexceptMoveOnly { + NoexceptMoveOnly() {} + NoexceptMoveOnly(NoexceptMoveOnly&&) noexcept {} + NoexceptMoveOnly& operator=(NoexceptMoveOnly&&) noexcept { return *this; } +}; + +struct NotMoveConstructible { + NotMoveConstructible() {} + NotMoveConstructible& operator=(NotMoveConstructible&&) { return *this; } +private: + NotMoveConstructible(NotMoveConstructible&&); +}; + +template <class Tp> +auto can_swap_test(int) -> decltype(std::swap(std::declval<Tp>(), std::declval<Tp>())); + +template <class Tp> +auto can_swap_test(...) -> std::false_type; + +template <class Tp> +constexpr bool can_swap() { + return std::is_same<decltype(can_swap_test<Tp>(0)), void>::value; } +#endif -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES int main() { - test(); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - test1(); + { + int i[3] = {1, 2, 3}; + int j[3] = {4, 5, 6}; + std::swap(i, j); + assert(i[0] == 4); + assert(i[1] == 5); + assert(i[2] == 6); + assert(j[0] == 1); + assert(j[1] == 2); + assert(j[2] == 3); + } +#if TEST_STD_VER >= 11 + { + std::unique_ptr<int> i[3]; + for (int k = 0; k < 3; ++k) + i[k].reset(new int(k+1)); + std::unique_ptr<int> j[3]; + for (int k = 0; k < 3; ++k) + j[k].reset(new int(k+4)); + std::swap(i, j); + assert(*i[0] == 4); + assert(*i[1] == 5); + assert(*i[2] == 6); + assert(*j[0] == 1); + assert(*j[1] == 2); + assert(*j[2] == 3); + } + { + using CA = CopyOnly[42]; + using MA = NoexceptMoveOnly[42]; + using NA = NotMoveConstructible[42]; + static_assert(can_swap<CA&>(), ""); + static_assert(can_swap<MA&>(), ""); + static_assert(!can_swap<NA&>(), ""); + + CA ca; + MA ma; + static_assert(!noexcept(std::swap(ca, ca)), ""); + static_assert(noexcept(std::swap(ma, ma)), ""); + } #endif } |