diff options
author | Louis Dionne <ldionne@apple.com> | 2019-01-10 20:06:11 +0000 |
---|---|---|
committer | Louis Dionne <ldionne@apple.com> | 2019-01-10 20:06:11 +0000 |
commit | 134a848236518442cc6b4b8006a2927db2e6636b (patch) | |
tree | 219bd90e96ab3cd8c7c67a9ec124ca6f7a1842a7 | |
parent | 4fb9e8f89a5ade3e80def4a5d4d033852901be35 (diff) | |
download | external_libcxx-134a848236518442cc6b4b8006a2927db2e6636b.tar.gz external_libcxx-134a848236518442cc6b4b8006a2927db2e6636b.tar.bz2 external_libcxx-134a848236518442cc6b4b8006a2927db2e6636b.zip |
[libcxx] Reorganize tests since the application of P0602R4
Summary:
P0602R4 makes the special member functions of optional and variant
conditionally trivial based on the types in the optional/variant.
We already implemented that, but the tests were organized as if this
were a non-standard extension. This patch reorganizes the tests in a
way that makes more sense since this is not an extension anymore.
Reviewers: EricWF, mpark, mclow.lists
Subscribers: christof, jkorous, dexonsmith, libcxx-commits
Differential Revision: https://reviews.llvm.org/D54772
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@350884 91177308-0d34-0410-b5e6-96231b3b80d8
13 files changed, 294 insertions, 112 deletions
diff --git a/include/optional b/include/optional index 544140f23..70422068e 100644 --- a/include/optional +++ b/include/optional @@ -105,8 +105,8 @@ namespace std { // 23.6.3.3, assignment optional &operator=(nullopt_t) noexcept; - optional &operator=(const optional &); - optional &operator=(optional &&) noexcept(see below ); + optional &operator=(const optional &); // constexpr in C++20 + optional &operator=(optional &&) noexcept(see below); // constexpr in C++20 template <class U = T> optional &operator=(U &&); template <class U> optional &operator=(const optional<U> &); template <class U> optional &operator=(optional<U> &&); diff --git a/include/variant b/include/variant index 4a771dc63..a4339de6c 100644 --- a/include/variant +++ b/include/variant @@ -23,8 +23,8 @@ namespace std { // 20.7.2.1, constructors constexpr variant() noexcept(see below); - variant(const variant&); - variant(variant&&) noexcept(see below); + variant(const variant&); // constexpr in C++20 + variant(variant&&) noexcept(see below); // constexpr in C++20 template <class T> constexpr variant(T&&) noexcept(see below); @@ -46,8 +46,8 @@ namespace std { ~variant(); // 20.7.2.3, assignment - variant& operator=(const variant&); - variant& operator=(variant&&) noexcept(see below); + variant& operator=(const variant&); // constexpr in C++20 + variant& operator=(variant&&) noexcept(see below); // constexpr in C++20 template <class T> variant& operator=(T&&) noexcept(see below); diff --git a/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp b/test/libcxx/utilities/optional/optional.object/triviality.abi.pass.cpp index 0b9b6e717..cdfb02736 100644 --- a/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp +++ b/test/libcxx/utilities/optional/optional.object/triviality.abi.pass.cpp @@ -8,8 +8,18 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++98, c++03, c++11, c++14 + // <optional> +// This test asserts the triviality of special member functions of optional<T> +// whenever T has these special member functions trivial. The goal of this test +// is to make sure that we do not change the triviality of those, since that +// constitues an ABI break (small enough optionals would be passed by registers). +// +// constexpr optional(const optional& rhs); +// constexpr optional(optional&& rhs) noexcept(see below); +// constexpr optional<T>& operator=(const optional& rhs); +// constexpr optional<T>& operator=(optional&& rhs) noexcept(see below); #include <optional> #include <type_traits> @@ -21,41 +31,27 @@ template <class T> struct SpecialMemberTest { using O = std::optional<T>; - static_assert(std::is_default_constructible_v<O>, - "optional is always default constructible."); - static_assert(std::is_copy_constructible_v<O> == std::is_copy_constructible_v<T>, - "optional<T> is copy constructible if and only if T is copy constructible."); - static_assert(std::is_move_constructible_v<O> == - (std::is_copy_constructible_v<T> || std::is_move_constructible_v<T>), - "optional<T> is move constructible if and only if T is copy or move constructible."); - static_assert(std::is_copy_assignable_v<O> == - (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>), - "optional<T> is copy assignable if and only if T is both copy " - "constructible and copy assignable."); - static_assert(std::is_move_assignable_v<O> == - ((std::is_move_constructible_v<T> && std::is_move_assignable_v<T>) || - (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>)), - "optional<T> is move assignable if and only if T is both move constructible and " - "move assignable, or both copy constructible and copy assignable."); - - // The following tests are for not-yet-standardized behavior (P0602): static_assert(std::is_trivially_destructible_v<O> == std::is_trivially_destructible_v<T>, "optional<T> is trivially destructible if and only if T is."); + static_assert(std::is_trivially_copy_constructible_v<O> == std::is_trivially_copy_constructible_v<T>, "optional<T> is trivially copy constructible if and only if T is."); + static_assert(std::is_trivially_move_constructible_v<O> == std::is_trivially_move_constructible_v<T> || (!std::is_move_constructible_v<T> && std::is_trivially_copy_constructible_v<T>), "optional<T> is trivially move constructible if T is trivially move constructible, " "or if T is trivially copy constructible and is not move constructible."); + static_assert(std::is_trivially_copy_assignable_v<O> == (std::is_trivially_destructible_v<T> && std::is_trivially_copy_constructible_v<T> && std::is_trivially_copy_assignable_v<T>), "optional<T> is trivially copy assignable if and only if T is trivially destructible, " "trivially copy constructible, and trivially copy assignable."); + static_assert(std::is_trivially_move_assignable_v<O> == (std::is_trivially_destructible_v<T> && ((std::is_trivially_move_constructible_v<T> && std::is_trivially_move_assignable_v<T>) || diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp index 98c90aa1d..bec0f09a3 100644 --- a/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp +++ b/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp @@ -10,7 +10,7 @@ // UNSUPPORTED: c++98, c++03, c++11, c++14 // <optional> -// optional<T>& operator=(const optional<T>& rhs); +// optional<T>& operator=(const optional<T>& rhs); // constexpr in C++20 #include <optional> #include <type_traits> @@ -53,15 +53,19 @@ int main() { { using O = optional<int>; +#if TEST_STD_VER > 17 LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); +#endif assert(assign_empty(O{42})); assert(assign_value(O{42})); } { using O = optional<TrivialTestTypes::TestType>; +#if TEST_STD_VER > 17 LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); +#endif assert(assign_empty(O{42})); assert(assign_value(O{42})); } diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp index ed8b433da..c41674f13 100644 --- a/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp +++ b/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp @@ -12,11 +12,12 @@ // optional<T>& operator=(optional<T>&& rhs) // noexcept(is_nothrow_move_assignable<T>::value && -// is_nothrow_move_constructible<T>::value); +// is_nothrow_move_constructible<T>::value); // constexpr in C++20 #include <optional> -#include <type_traits> #include <cassert> +#include <type_traits> +#include <utility> #include "test_macros.h" #include "archetypes.hpp" @@ -51,6 +52,21 @@ struct Y {}; bool X::throw_now = false; int X::alive = 0; + +template <class Tp> +constexpr bool assign_empty(optional<Tp>&& lhs) { + optional<Tp> rhs; + lhs = std::move(rhs); + return !lhs.has_value() && !rhs.has_value(); +} + +template <class Tp> +constexpr bool assign_value(optional<Tp>&& lhs) { + optional<Tp> rhs(101); + lhs = std::move(rhs); + return lhs.has_value() && rhs.has_value() && *lhs == Tp{101}; +} + int main() { { @@ -97,6 +113,24 @@ int main() assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); assert(*opt == *opt2); } + { + using O = optional<int>; +#if TEST_STD_VER > 17 + LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); + LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); +#endif + assert(assign_empty(O{42})); + assert(assign_value(O{42})); + } + { + using O = optional<TrivialTestTypes::TestType>; +#if TEST_STD_VER > 17 + LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); + LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); +#endif + assert(assign_empty(O{42})); + assert(assign_value(O{42})); + } #ifndef TEST_HAS_NO_EXCEPTIONS { static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, ""); diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/copy.fail.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/copy.fail.cpp deleted file mode 100644 index 593368348..000000000 --- a/test/std/utilities/optional/optional.object/optional.object.ctor/copy.fail.cpp +++ /dev/null @@ -1,36 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 -// <optional> - -// constexpr optional(const optional<T>& rhs); -// If is_trivially_copy_constructible_v<T> is true, -// this constructor shall be a constexpr constructor. - -#include <optional> -#include <type_traits> -#include <cassert> - -#include "test_macros.h" - -struct S { - constexpr S() : v_(0) {} - S(int v) : v_(v) {} - S(const S &rhs) : v_(rhs.v_) {} // make it not trivially copyable - int v_; -}; - - -int main() -{ - static_assert (!std::is_trivially_copy_constructible_v<S>, "" ); - constexpr std::optional<S> o1; - constexpr std::optional<S> o2 = o1; // not constexpr -} diff --git a/test/std/utilities/optional/optional.object/special_members.pass.cpp b/test/std/utilities/optional/optional.object/special_members.pass.cpp new file mode 100644 index 000000000..3bc561cfe --- /dev/null +++ b/test/std/utilities/optional/optional.object/special_members.pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// <optional> + +// Make sure we properly generate special member functions for optional<T> +// based on the properties of T itself. + +#include <optional> +#include <type_traits> + +#include "archetypes.hpp" + + +template <class T> +struct SpecialMemberTest { + using O = std::optional<T>; + + static_assert(std::is_default_constructible_v<O>, + "optional is always default constructible."); + + static_assert(std::is_copy_constructible_v<O> == std::is_copy_constructible_v<T>, + "optional<T> is copy constructible if and only if T is copy constructible."); + + static_assert(std::is_move_constructible_v<O> == + (std::is_copy_constructible_v<T> || std::is_move_constructible_v<T>), + "optional<T> is move constructible if and only if T is copy or move constructible."); + + static_assert(std::is_copy_assignable_v<O> == + (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>), + "optional<T> is copy assignable if and only if T is both copy " + "constructible and copy assignable."); + + static_assert(std::is_move_assignable_v<O> == + ((std::is_move_constructible_v<T> && std::is_move_assignable_v<T>) || + (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>)), + "optional<T> is move assignable if and only if T is both move constructible and " + "move assignable, or both copy constructible and copy assignable."); +}; + +template <class ...Args> static void sink(Args&&...) {} + +template <class ...TestTypes> +struct DoTestsMetafunction { + DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); } +}; + +int main() { + sink( + ImplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + ExplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{}, + NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{} + ); +} diff --git a/test/std/utilities/optional/optional.object/triviality.pass.cpp b/test/std/utilities/optional/optional.object/triviality.pass.cpp new file mode 100644 index 000000000..c21c85aad --- /dev/null +++ b/test/std/utilities/optional/optional.object/triviality.pass.cpp @@ -0,0 +1,97 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++17 + +// <optional> + +// The following special member functions should propagate the triviality of +// the element held in the optional (see P0602R4): +// +// constexpr optional(const optional& rhs); +// constexpr optional(optional&& rhs) noexcept(see below); +// constexpr optional<T>& operator=(const optional& rhs); +// constexpr optional<T>& operator=(optional&& rhs) noexcept(see below); + + +#include <optional> +#include <type_traits> + +#include "archetypes.hpp" + + +constexpr bool implies(bool p, bool q) { + return !p || q; +} + +template <class T> +struct SpecialMemberTest { + using O = std::optional<T>; + + static_assert(implies(std::is_trivially_copy_constructible_v<T>, + std::is_trivially_copy_constructible_v<O>), + "optional<T> is trivially copy constructible if T is trivially copy constructible."); + + static_assert(implies(std::is_trivially_move_constructible_v<T>, + std::is_trivially_move_constructible_v<O>), + "optional<T> is trivially move constructible if T is trivially move constructible"); + + static_assert(implies(std::is_trivially_copy_constructible_v<T> && + std::is_trivially_copy_assignable_v<T> && + std::is_trivially_destructible_v<T>, + + std::is_trivially_copy_assignable_v<O>), + "optional<T> is trivially copy assignable if T is " + "trivially copy constructible, " + "trivially copy assignable, and " + "trivially destructible"); + + static_assert(implies(std::is_trivially_move_constructible_v<T> && + std::is_trivially_move_assignable_v<T> && + std::is_trivially_destructible_v<T>, + + std::is_trivially_move_assignable_v<O>), + "optional<T> is trivially move assignable if T is " + "trivially move constructible, " + "trivially move assignable, and" + "trivially destructible."); +}; + +template <class ...Args> static void sink(Args&&...) {} + +template <class ...TestTypes> +struct DoTestsMetafunction { + DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); } +}; + +struct TrivialMoveNonTrivialCopy { + TrivialMoveNonTrivialCopy() = default; + TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {} + TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default; + TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; } + TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default; +}; + +struct TrivialCopyNonTrivialMove { + TrivialCopyNonTrivialMove() = default; + TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default; + TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {} + TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default; + TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; } +}; + +int main() { + sink( + ImplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + ExplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{}, + NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{}, + DoTestsMetafunction<TrivialMoveNonTrivialCopy, TrivialCopyNonTrivialMove>{} + ); +} diff --git a/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp b/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp index 775ecffea..5ea7069f5 100644 --- a/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp +++ b/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp @@ -26,7 +26,7 @@ // template <class ...Types> class variant; -// variant& operator=(variant const&); +// variant& operator=(variant const&); // constexpr in C++20 #include <cassert> #include <string> @@ -240,7 +240,8 @@ void test_copy_assignment_sfinae() { static_assert(!std::is_copy_assignable<V>::value, ""); } - // The following tests are for not-yet-standardized behavior (P0602): + // Make sure we properly propagate triviality (see P0602R4). +#if TEST_STD_VER > 17 { using V = std::variant<int, long>; static_assert(std::is_trivially_copy_assignable<V>::value, ""); @@ -262,6 +263,7 @@ void test_copy_assignment_sfinae() { using V = std::variant<int, CopyOnly>; static_assert(std::is_trivially_copy_assignable<V>::value, ""); } +#endif // > C++17 } void test_copy_assignment_empty_empty() { @@ -384,7 +386,8 @@ void test_copy_assignment_same_index() { } #endif // TEST_HAS_NO_EXCEPTIONS - // The following tests are for not-yet-standardized behavior (P0602): + // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4). +#if TEST_STD_VER > 17 { struct { constexpr Result<int> operator()() const { @@ -441,6 +444,7 @@ void test_copy_assignment_same_index() { static_assert(result.index == 1, ""); static_assert(result.value == 42, ""); } +#endif // > C++17 } void test_copy_assignment_different_index() { @@ -530,7 +534,8 @@ void test_copy_assignment_different_index() { } #endif // TEST_HAS_NO_EXCEPTIONS - // The following tests are for not-yet-standardized behavior (P0602): + // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4). +#if TEST_STD_VER > 17 { struct { constexpr Result<long> operator()() const { @@ -559,10 +564,11 @@ void test_copy_assignment_different_index() { static_assert(result.index == 1, ""); static_assert(result.value == 42, ""); } +#endif // > C++17 } template <size_t NewIdx, class ValueType> -constexpr bool test_constexpr_assign_extension_imp( +constexpr bool test_constexpr_assign_imp( std::variant<long, void*, int>&& v, ValueType&& new_value) { const std::variant<long, void*, int> cp( @@ -572,15 +578,17 @@ constexpr bool test_constexpr_assign_extension_imp( std::get<NewIdx>(v) == std::get<NewIdx>(cp); } -void test_constexpr_copy_assignment_extension() { - // The following tests are for not-yet-standardized behavior (P0602): +void test_constexpr_copy_assignment() { + // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4). +#if TEST_STD_VER > 17 using V = std::variant<long, void*, int>; static_assert(std::is_trivially_copyable<V>::value, ""); static_assert(std::is_trivially_copy_assignable<V>::value, ""); - static_assert(test_constexpr_assign_extension_imp<0>(V(42l), 101l), ""); - static_assert(test_constexpr_assign_extension_imp<0>(V(nullptr), 101l), ""); - static_assert(test_constexpr_assign_extension_imp<1>(V(42l), nullptr), ""); - static_assert(test_constexpr_assign_extension_imp<2>(V(42l), 101), ""); + static_assert(test_constexpr_assign_imp<0>(V(42l), 101l), ""); + static_assert(test_constexpr_assign_imp<0>(V(nullptr), 101l), ""); + static_assert(test_constexpr_assign_imp<1>(V(42l), nullptr), ""); + static_assert(test_constexpr_assign_imp<2>(V(42l), 101), ""); +#endif // > C++17 } int main() { @@ -591,5 +599,5 @@ int main() { test_copy_assignment_different_index(); test_copy_assignment_sfinae(); test_copy_assignment_not_noexcept(); - test_constexpr_copy_assignment_extension(); + test_constexpr_copy_assignment(); } diff --git a/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp b/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp index 7b2dedd0d..cee141a8c 100644 --- a/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp +++ b/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp @@ -27,7 +27,7 @@ // template <class ...Types> class variant; -// variant& operator=(variant&&) noexcept(see below); +// variant& operator=(variant&&) noexcept(see below); // constexpr in C++20 #include <cassert> #include <string> @@ -206,7 +206,8 @@ void test_move_assignment_sfinae() { static_assert(!std::is_move_assignable<V>::value, ""); } - // The following tests are for not-yet-standardized behavior (P0602): + // Make sure we properly propagate triviality (see P0602R4). +#if TEST_STD_VER > 17 { using V = std::variant<int, long>; static_assert(std::is_trivially_move_assignable<V>::value, ""); @@ -232,6 +233,7 @@ void test_move_assignment_sfinae() { using V = std::variant<int, CopyOnly>; static_assert(std::is_trivially_move_assignable<V>::value, ""); } +#endif // > C++17 } void test_move_assignment_empty_empty() { @@ -353,7 +355,8 @@ void test_move_assignment_same_index() { } #endif // TEST_HAS_NO_EXCEPTIONS - // The following tests are for not-yet-standardized behavior (P0602): + // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4). +#if TEST_STD_VER > 17 { struct { constexpr Result<int> operator()() const { @@ -396,6 +399,7 @@ void test_move_assignment_same_index() { static_assert(result.index == 1, ""); static_assert(result.value == 42, ""); } +#endif // > C++17 } void test_move_assignment_different_index() { @@ -445,7 +449,8 @@ void test_move_assignment_different_index() { } #endif // TEST_HAS_NO_EXCEPTIONS - // The following tests are for not-yet-standardized behavior (P0602): + // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4). +#if TEST_STD_VER > 17 { struct { constexpr Result<long> operator()() const { @@ -474,10 +479,11 @@ void test_move_assignment_different_index() { static_assert(result.index == 1, ""); static_assert(result.value == 42, ""); } +#endif // > C++17 } template <size_t NewIdx, class ValueType> -constexpr bool test_constexpr_assign_extension_imp( +constexpr bool test_constexpr_assign_imp( std::variant<long, void*, int>&& v, ValueType&& new_value) { std::variant<long, void*, int> v2( @@ -488,15 +494,17 @@ constexpr bool test_constexpr_assign_extension_imp( std::get<NewIdx>(v) == std::get<NewIdx>(cp); } -void test_constexpr_move_assignment_extension() { - // The following tests are for not-yet-standardized behavior (P0602): +void test_constexpr_move_assignment() { + // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4). +#if TEST_STD_VER > 17 using V = std::variant<long, void*, int>; static_assert(std::is_trivially_copyable<V>::value, ""); static_assert(std::is_trivially_move_assignable<V>::value, ""); - static_assert(test_constexpr_assign_extension_imp<0>(V(42l), 101l), ""); - static_assert(test_constexpr_assign_extension_imp<0>(V(nullptr), 101l), ""); - static_assert(test_constexpr_assign_extension_imp<1>(V(42l), nullptr), ""); - static_assert(test_constexpr_assign_extension_imp<2>(V(42l), 101), ""); + static_assert(test_constexpr_assign_imp<0>(V(42l), 101l), ""); + static_assert(test_constexpr_assign_imp<0>(V(nullptr), 101l), ""); + static_assert(test_constexpr_assign_imp<1>(V(42l), nullptr), ""); + static_assert(test_constexpr_assign_imp<2>(V(42l), 101), ""); +#endif // > C++17 } int main() { @@ -507,5 +515,5 @@ int main() { test_move_assignment_different_index(); test_move_assignment_sfinae(); test_move_assignment_noexcept(); - test_constexpr_move_assignment_extension(); + test_constexpr_move_assignment(); } diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp index 9e1e77725..6eeec69c8 100644 --- a/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp +++ b/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp @@ -22,7 +22,7 @@ // template <class ...Types> class variant; -// variant(variant const&); +// variant(variant const&); // constexpr in C++20 #include <cassert> #include <type_traits> @@ -126,7 +126,8 @@ void test_copy_ctor_sfinae() { static_assert(!std::is_copy_constructible<V>::value, ""); } - // The following tests are for not-yet-standardized behavior (P0602): + // Make sure we properly propagate triviality (see P0602R4). +#if TEST_STD_VER > 17 { using V = std::variant<int, long>; static_assert(std::is_trivially_copy_constructible<V>::value, ""); @@ -144,6 +145,7 @@ void test_copy_ctor_sfinae() { using V = std::variant<int, TCopyNTMove>; static_assert(std::is_trivially_copy_constructible<V>::value, ""); } +#endif // > C++17 } void test_copy_ctor_basic() { @@ -174,7 +176,8 @@ void test_copy_ctor_basic() { assert(std::get<1>(v2).value == 42); } - // The following tests are for not-yet-standardized behavior (P0602): + // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4). +#if TEST_STD_VER > 17 { constexpr std::variant<int> v(std::in_place_index<0>, 42); static_assert(v.index() == 0, ""); @@ -217,6 +220,7 @@ void test_copy_ctor_basic() { static_assert(v2.index() == 1, ""); static_assert(std::get<1>(v2).value == 42, ""); } +#endif // > C++17 } void test_copy_ctor_valueless_by_exception() { @@ -231,17 +235,16 @@ void test_copy_ctor_valueless_by_exception() { } template <size_t Idx> -constexpr bool test_constexpr_copy_ctor_extension_imp( - std::variant<long, void*, const int> const& v) -{ +constexpr bool test_constexpr_copy_ctor_imp(std::variant<long, void*, const int> const& v) { auto v2 = v; return v2.index() == v.index() && v2.index() == Idx && std::get<Idx>(v2) == std::get<Idx>(v); } -void test_constexpr_copy_ctor_extension() { - // NOTE: This test is for not yet standardized behavior. (P0602) +void test_constexpr_copy_ctor() { + // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4). +#if TEST_STD_VER > 17 using V = std::variant<long, void*, const int>; #ifdef TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE static_assert(std::is_trivially_destructible<V>::value, ""); @@ -252,16 +255,17 @@ void test_constexpr_copy_ctor_extension() { #else // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE static_assert(std::is_trivially_copyable<V>::value, ""); #endif // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE - static_assert(test_constexpr_copy_ctor_extension_imp<0>(V(42l)), ""); - static_assert(test_constexpr_copy_ctor_extension_imp<1>(V(nullptr)), ""); - static_assert(test_constexpr_copy_ctor_extension_imp<2>(V(101)), ""); + static_assert(test_constexpr_copy_ctor_imp<0>(V(42l)), ""); + static_assert(test_constexpr_copy_ctor_imp<1>(V(nullptr)), ""); + static_assert(test_constexpr_copy_ctor_imp<2>(V(101)), ""); +#endif // > C++17 } int main() { test_copy_ctor_basic(); test_copy_ctor_valueless_by_exception(); test_copy_ctor_sfinae(); - test_constexpr_copy_ctor_extension(); + test_constexpr_copy_ctor(); #if 0 // disable this for the moment; it fails on older compilers. // Need to figure out which compilers will support it. diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp index e6cdb0e96..f59367109 100644 --- a/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp +++ b/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp @@ -22,7 +22,7 @@ // template <class ...Types> class variant; -// variant(variant&&) noexcept(see below); +// variant(variant&&) noexcept(see below); // constexpr in C++20 #include <cassert> #include <string> @@ -147,7 +147,8 @@ void test_move_ctor_sfinae() { static_assert(!std::is_move_constructible<V>::value, ""); } - // The following tests are for not-yet-standardized behavior (P0602): + // Make sure we properly propagate triviality (see P0602R4). +#if TEST_STD_VER > 17 { using V = std::variant<int, long>; static_assert(std::is_trivially_move_constructible<V>::value, ""); @@ -165,6 +166,7 @@ void test_move_ctor_sfinae() { using V = std::variant<int, TMoveNTCopy>; static_assert(std::is_trivially_move_constructible<V>::value, ""); } +#endif // > C++17 } template <typename T> @@ -214,7 +216,8 @@ void test_move_ctor_basic() { assert(std::get<1>(v2).value == 42); } - // The following tests are for not-yet-standardized behavior (P0602): + // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4). +#if TEST_STD_VER > 17 { struct { constexpr Result<int> operator()() const { @@ -287,6 +290,7 @@ void test_move_ctor_basic() { static_assert(result.index == 1, ""); static_assert(result.value.value == 42, ""); } +#endif // > C++17 } void test_move_ctor_valueless_by_exception() { @@ -300,9 +304,7 @@ void test_move_ctor_valueless_by_exception() { } template <size_t Idx> -constexpr bool test_constexpr_ctor_extension_imp( - std::variant<long, void*, const int> const& v) -{ +constexpr bool test_constexpr_ctor_imp(std::variant<long, void*, const int> const& v) { auto copy = v; auto v2 = std::move(copy); return v2.index() == v.index() && @@ -310,8 +312,9 @@ constexpr bool test_constexpr_ctor_extension_imp( std::get<Idx>(v2) == std::get<Idx>(v); } -void test_constexpr_move_ctor_extension() { - // NOTE: This test is for not yet standardized behavior. (P0602) +void test_constexpr_move_ctor() { + // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4). +#if TEST_STD_VER > 17 using V = std::variant<long, void*, const int>; #ifdef TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE static_assert(std::is_trivially_destructible<V>::value, ""); @@ -323,9 +326,10 @@ void test_constexpr_move_ctor_extension() { static_assert(std::is_trivially_copyable<V>::value, ""); #endif // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE static_assert(std::is_trivially_move_constructible<V>::value, ""); - static_assert(test_constexpr_ctor_extension_imp<0>(V(42l)), ""); - static_assert(test_constexpr_ctor_extension_imp<1>(V(nullptr)), ""); - static_assert(test_constexpr_ctor_extension_imp<2>(V(101)), ""); + static_assert(test_constexpr_ctor_imp<0>(V(42l)), ""); + static_assert(test_constexpr_ctor_imp<1>(V(nullptr)), ""); + static_assert(test_constexpr_ctor_imp<2>(V(101)), ""); +#endif // > C++17 } int main() { @@ -333,5 +337,5 @@ int main() { test_move_ctor_valueless_by_exception(); test_move_noexcept(); test_move_ctor_sfinae(); - test_constexpr_move_ctor_extension(); + test_constexpr_move_ctor(); } diff --git a/www/cxx2a_status.html b/www/cxx2a_status.html index 63ae029ed..a5e87ec18 100644 --- a/www/cxx2a_status.html +++ b/www/cxx2a_status.html @@ -115,7 +115,7 @@ <tr><td><a href="https://wg21.link/P0487R1">P0487R1</a></td><td>LWG</td><td>Fixing operator>>(basic_istream&, CharT*) (LWG 2499)</td><td>San Diego</td><td>Complete</td><td>8.0</td></tr> <tr><td><a href="https://wg21.link/P0591R4">P0591R4</a></td><td>LWG</td><td>Utility functions to implement uses-allocator construction</td><td>San Diego</td><td><i> </i></td><td></td></tr> <tr><td><a href="https://wg21.link/P0595R2">P0595R2</a></td><td>CWG</td><td>P0595R2 std::is_constant_evaluated()</td><td>San Diego</td><td><i> </i></td><td></td></tr> - <tr><td><a href="https://wg21.link/P0602R4">P0602R4</a></td><td>LWG</td><td>variant and optional should propagate copy/move triviality</td><td>San Diego</td><td><i> </i></td><td></td></tr> + <tr><td><a href="https://wg21.link/P0602R4">P0602R4</a></td><td>LWG</td><td>variant and optional should propagate copy/move triviality</td><td>San Diego</td><td>Complete</td><td>8.0</td></tr> <tr><td><a href="https://wg21.link/P0608R3">P0608R3</a></td><td>LWG</td><td>A sane variant converting constructor</td><td>San Diego</td><td><i> </i></td><td></td></tr> <tr><td><a href="https://wg21.link/P0655R1">P0655R1</a></td><td>LWG</td><td>visit<R>: Explicit Return Type for visit</td><td>San Diego</td><td><i> </i></td><td></td></tr> <tr><td><a href="https://wg21.link/P0771R1">P0771R1</a></td><td>LWG</td><td>std::function move constructor should be noexcept</td><td>San Diego</td><td>Complete</td><td>6.0</td></tr> |