[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
This commit is contained in:
@@ -105,8 +105,8 @@ namespace std {
|
|||||||
|
|
||||||
// 23.6.3.3, assignment
|
// 23.6.3.3, assignment
|
||||||
optional &operator=(nullopt_t) noexcept;
|
optional &operator=(nullopt_t) noexcept;
|
||||||
optional &operator=(const optional &);
|
optional &operator=(const optional &); // constexpr in C++20
|
||||||
optional &operator=(optional &&) noexcept(see below );
|
optional &operator=(optional &&) noexcept(see below); // constexpr in C++20
|
||||||
template <class U = T> optional &operator=(U &&);
|
template <class U = T> optional &operator=(U &&);
|
||||||
template <class U> optional &operator=(const optional<U> &);
|
template <class U> optional &operator=(const optional<U> &);
|
||||||
template <class U> optional &operator=(optional<U> &&);
|
template <class U> optional &operator=(optional<U> &&);
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ namespace std {
|
|||||||
|
|
||||||
// 20.7.2.1, constructors
|
// 20.7.2.1, constructors
|
||||||
constexpr variant() noexcept(see below);
|
constexpr variant() noexcept(see below);
|
||||||
variant(const variant&);
|
variant(const variant&); // constexpr in C++20
|
||||||
variant(variant&&) noexcept(see below);
|
variant(variant&&) noexcept(see below); // constexpr in C++20
|
||||||
|
|
||||||
template <class T> constexpr variant(T&&) noexcept(see below);
|
template <class T> constexpr variant(T&&) noexcept(see below);
|
||||||
|
|
||||||
@@ -46,8 +46,8 @@ namespace std {
|
|||||||
~variant();
|
~variant();
|
||||||
|
|
||||||
// 20.7.2.3, assignment
|
// 20.7.2.3, assignment
|
||||||
variant& operator=(const variant&);
|
variant& operator=(const variant&); // constexpr in C++20
|
||||||
variant& operator=(variant&&) noexcept(see below);
|
variant& operator=(variant&&) noexcept(see below); // constexpr in C++20
|
||||||
|
|
||||||
template <class T> variant& operator=(T&&) noexcept(see below);
|
template <class T> variant& operator=(T&&) noexcept(see below);
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,18 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
// <optional>
|
// <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 <optional>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@@ -21,41 +31,27 @@ template <class T>
|
|||||||
struct SpecialMemberTest {
|
struct SpecialMemberTest {
|
||||||
using O = std::optional<T>;
|
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> ==
|
static_assert(std::is_trivially_destructible_v<O> ==
|
||||||
std::is_trivially_destructible_v<T>,
|
std::is_trivially_destructible_v<T>,
|
||||||
"optional<T> is trivially destructible if and only if T is.");
|
"optional<T> is trivially destructible if and only if T is.");
|
||||||
|
|
||||||
static_assert(std::is_trivially_copy_constructible_v<O> ==
|
static_assert(std::is_trivially_copy_constructible_v<O> ==
|
||||||
std::is_trivially_copy_constructible_v<T>,
|
std::is_trivially_copy_constructible_v<T>,
|
||||||
"optional<T> is trivially copy constructible if and only if T is.");
|
"optional<T> is trivially copy constructible if and only if T is.");
|
||||||
|
|
||||||
static_assert(std::is_trivially_move_constructible_v<O> ==
|
static_assert(std::is_trivially_move_constructible_v<O> ==
|
||||||
std::is_trivially_move_constructible_v<T> ||
|
std::is_trivially_move_constructible_v<T> ||
|
||||||
(!std::is_move_constructible_v<T> && std::is_trivially_copy_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, "
|
"optional<T> is trivially move constructible if T is trivially move constructible, "
|
||||||
"or if T is trivially copy constructible and is not move constructible.");
|
"or if T is trivially copy constructible and is not move constructible.");
|
||||||
|
|
||||||
static_assert(std::is_trivially_copy_assignable_v<O> ==
|
static_assert(std::is_trivially_copy_assignable_v<O> ==
|
||||||
(std::is_trivially_destructible_v<T> &&
|
(std::is_trivially_destructible_v<T> &&
|
||||||
std::is_trivially_copy_constructible_v<T> &&
|
std::is_trivially_copy_constructible_v<T> &&
|
||||||
std::is_trivially_copy_assignable_v<T>),
|
std::is_trivially_copy_assignable_v<T>),
|
||||||
"optional<T> is trivially copy assignable if and only if T is trivially destructible, "
|
"optional<T> is trivially copy assignable if and only if T is trivially destructible, "
|
||||||
"trivially copy constructible, and trivially copy assignable.");
|
"trivially copy constructible, and trivially copy assignable.");
|
||||||
|
|
||||||
static_assert(std::is_trivially_move_assignable_v<O> ==
|
static_assert(std::is_trivially_move_assignable_v<O> ==
|
||||||
(std::is_trivially_destructible_v<T> &&
|
(std::is_trivially_destructible_v<T> &&
|
||||||
((std::is_trivially_move_constructible_v<T> && std::is_trivially_move_assignable_v<T>) ||
|
((std::is_trivially_move_constructible_v<T> && std::is_trivially_move_assignable_v<T>) ||
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
// <optional>
|
// <optional>
|
||||||
|
|
||||||
// optional<T>& operator=(const optional<T>& rhs);
|
// optional<T>& operator=(const optional<T>& rhs); // constexpr in C++20
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@@ -53,15 +53,19 @@ int main()
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
using O = optional<int>;
|
using O = optional<int>;
|
||||||
|
#if TEST_STD_VER > 17
|
||||||
LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
|
LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
|
||||||
LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
|
LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
|
||||||
|
#endif
|
||||||
assert(assign_empty(O{42}));
|
assert(assign_empty(O{42}));
|
||||||
assert(assign_value(O{42}));
|
assert(assign_value(O{42}));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using O = optional<TrivialTestTypes::TestType>;
|
using O = optional<TrivialTestTypes::TestType>;
|
||||||
|
#if TEST_STD_VER > 17
|
||||||
LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
|
LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
|
||||||
LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
|
LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
|
||||||
|
#endif
|
||||||
assert(assign_empty(O{42}));
|
assert(assign_empty(O{42}));
|
||||||
assert(assign_value(O{42}));
|
assert(assign_value(O{42}));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,12 @@
|
|||||||
|
|
||||||
// optional<T>& operator=(optional<T>&& rhs)
|
// optional<T>& operator=(optional<T>&& rhs)
|
||||||
// noexcept(is_nothrow_move_assignable<T>::value &&
|
// 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 <optional>
|
||||||
#include <type_traits>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
#include "archetypes.hpp"
|
#include "archetypes.hpp"
|
||||||
@@ -51,6 +52,21 @@ struct Y {};
|
|||||||
bool X::throw_now = false;
|
bool X::throw_now = false;
|
||||||
int X::alive = 0;
|
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()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -97,6 +113,24 @@ int main()
|
|||||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||||
assert(*opt == *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
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||||
{
|
{
|
||||||
static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
|
static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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>{}
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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>{}
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
// template <class ...Types> class variant;
|
// template <class ...Types> class variant;
|
||||||
|
|
||||||
// variant& operator=(variant const&);
|
// variant& operator=(variant const&); // constexpr in C++20
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -240,7 +240,8 @@ void test_copy_assignment_sfinae() {
|
|||||||
static_assert(!std::is_copy_assignable<V>::value, "");
|
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>;
|
using V = std::variant<int, long>;
|
||||||
static_assert(std::is_trivially_copy_assignable<V>::value, "");
|
static_assert(std::is_trivially_copy_assignable<V>::value, "");
|
||||||
@@ -262,6 +263,7 @@ void test_copy_assignment_sfinae() {
|
|||||||
using V = std::variant<int, CopyOnly>;
|
using V = std::variant<int, CopyOnly>;
|
||||||
static_assert(std::is_trivially_copy_assignable<V>::value, "");
|
static_assert(std::is_trivially_copy_assignable<V>::value, "");
|
||||||
}
|
}
|
||||||
|
#endif // > C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_copy_assignment_empty_empty() {
|
void test_copy_assignment_empty_empty() {
|
||||||
@@ -384,7 +386,8 @@ void test_copy_assignment_same_index() {
|
|||||||
}
|
}
|
||||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
#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 {
|
struct {
|
||||||
constexpr Result<int> operator()() const {
|
constexpr Result<int> operator()() const {
|
||||||
@@ -441,6 +444,7 @@ void test_copy_assignment_same_index() {
|
|||||||
static_assert(result.index == 1, "");
|
static_assert(result.index == 1, "");
|
||||||
static_assert(result.value == 42, "");
|
static_assert(result.value == 42, "");
|
||||||
}
|
}
|
||||||
|
#endif // > C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_copy_assignment_different_index() {
|
void test_copy_assignment_different_index() {
|
||||||
@@ -530,7 +534,8 @@ void test_copy_assignment_different_index() {
|
|||||||
}
|
}
|
||||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
#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 {
|
struct {
|
||||||
constexpr Result<long> operator()() const {
|
constexpr Result<long> operator()() const {
|
||||||
@@ -559,10 +564,11 @@ void test_copy_assignment_different_index() {
|
|||||||
static_assert(result.index == 1, "");
|
static_assert(result.index == 1, "");
|
||||||
static_assert(result.value == 42, "");
|
static_assert(result.value == 42, "");
|
||||||
}
|
}
|
||||||
|
#endif // > C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t NewIdx, class ValueType>
|
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>&& v, ValueType&& new_value)
|
||||||
{
|
{
|
||||||
const std::variant<long, void*, int> cp(
|
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);
|
std::get<NewIdx>(v) == std::get<NewIdx>(cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_constexpr_copy_assignment_extension() {
|
void test_constexpr_copy_assignment() {
|
||||||
// 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
|
||||||
using V = std::variant<long, void*, int>;
|
using V = std::variant<long, void*, int>;
|
||||||
static_assert(std::is_trivially_copyable<V>::value, "");
|
static_assert(std::is_trivially_copyable<V>::value, "");
|
||||||
static_assert(std::is_trivially_copy_assignable<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_imp<0>(V(42l), 101l), "");
|
||||||
static_assert(test_constexpr_assign_extension_imp<0>(V(nullptr), 101l), "");
|
static_assert(test_constexpr_assign_imp<0>(V(nullptr), 101l), "");
|
||||||
static_assert(test_constexpr_assign_extension_imp<1>(V(42l), nullptr), "");
|
static_assert(test_constexpr_assign_imp<1>(V(42l), nullptr), "");
|
||||||
static_assert(test_constexpr_assign_extension_imp<2>(V(42l), 101), "");
|
static_assert(test_constexpr_assign_imp<2>(V(42l), 101), "");
|
||||||
|
#endif // > C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
@@ -591,5 +599,5 @@ int main() {
|
|||||||
test_copy_assignment_different_index();
|
test_copy_assignment_different_index();
|
||||||
test_copy_assignment_sfinae();
|
test_copy_assignment_sfinae();
|
||||||
test_copy_assignment_not_noexcept();
|
test_copy_assignment_not_noexcept();
|
||||||
test_constexpr_copy_assignment_extension();
|
test_constexpr_copy_assignment();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
// template <class ...Types> class variant;
|
// template <class ...Types> class variant;
|
||||||
|
|
||||||
// variant& operator=(variant&&) noexcept(see below);
|
// variant& operator=(variant&&) noexcept(see below); // constexpr in C++20
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -206,7 +206,8 @@ void test_move_assignment_sfinae() {
|
|||||||
static_assert(!std::is_move_assignable<V>::value, "");
|
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>;
|
using V = std::variant<int, long>;
|
||||||
static_assert(std::is_trivially_move_assignable<V>::value, "");
|
static_assert(std::is_trivially_move_assignable<V>::value, "");
|
||||||
@@ -232,6 +233,7 @@ void test_move_assignment_sfinae() {
|
|||||||
using V = std::variant<int, CopyOnly>;
|
using V = std::variant<int, CopyOnly>;
|
||||||
static_assert(std::is_trivially_move_assignable<V>::value, "");
|
static_assert(std::is_trivially_move_assignable<V>::value, "");
|
||||||
}
|
}
|
||||||
|
#endif // > C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_move_assignment_empty_empty() {
|
void test_move_assignment_empty_empty() {
|
||||||
@@ -353,7 +355,8 @@ void test_move_assignment_same_index() {
|
|||||||
}
|
}
|
||||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
#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 {
|
struct {
|
||||||
constexpr Result<int> operator()() const {
|
constexpr Result<int> operator()() const {
|
||||||
@@ -396,6 +399,7 @@ void test_move_assignment_same_index() {
|
|||||||
static_assert(result.index == 1, "");
|
static_assert(result.index == 1, "");
|
||||||
static_assert(result.value == 42, "");
|
static_assert(result.value == 42, "");
|
||||||
}
|
}
|
||||||
|
#endif // > C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_move_assignment_different_index() {
|
void test_move_assignment_different_index() {
|
||||||
@@ -445,7 +449,8 @@ void test_move_assignment_different_index() {
|
|||||||
}
|
}
|
||||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
#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 {
|
struct {
|
||||||
constexpr Result<long> operator()() const {
|
constexpr Result<long> operator()() const {
|
||||||
@@ -474,10 +479,11 @@ void test_move_assignment_different_index() {
|
|||||||
static_assert(result.index == 1, "");
|
static_assert(result.index == 1, "");
|
||||||
static_assert(result.value == 42, "");
|
static_assert(result.value == 42, "");
|
||||||
}
|
}
|
||||||
|
#endif // > C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t NewIdx, class ValueType>
|
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>&& v, ValueType&& new_value)
|
||||||
{
|
{
|
||||||
std::variant<long, void*, int> v2(
|
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);
|
std::get<NewIdx>(v) == std::get<NewIdx>(cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_constexpr_move_assignment_extension() {
|
void test_constexpr_move_assignment() {
|
||||||
// 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
|
||||||
using V = std::variant<long, void*, int>;
|
using V = std::variant<long, void*, int>;
|
||||||
static_assert(std::is_trivially_copyable<V>::value, "");
|
static_assert(std::is_trivially_copyable<V>::value, "");
|
||||||
static_assert(std::is_trivially_move_assignable<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_imp<0>(V(42l), 101l), "");
|
||||||
static_assert(test_constexpr_assign_extension_imp<0>(V(nullptr), 101l), "");
|
static_assert(test_constexpr_assign_imp<0>(V(nullptr), 101l), "");
|
||||||
static_assert(test_constexpr_assign_extension_imp<1>(V(42l), nullptr), "");
|
static_assert(test_constexpr_assign_imp<1>(V(42l), nullptr), "");
|
||||||
static_assert(test_constexpr_assign_extension_imp<2>(V(42l), 101), "");
|
static_assert(test_constexpr_assign_imp<2>(V(42l), 101), "");
|
||||||
|
#endif // > C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
@@ -507,5 +515,5 @@ int main() {
|
|||||||
test_move_assignment_different_index();
|
test_move_assignment_different_index();
|
||||||
test_move_assignment_sfinae();
|
test_move_assignment_sfinae();
|
||||||
test_move_assignment_noexcept();
|
test_move_assignment_noexcept();
|
||||||
test_constexpr_move_assignment_extension();
|
test_constexpr_move_assignment();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
// template <class ...Types> class variant;
|
// template <class ...Types> class variant;
|
||||||
|
|
||||||
// variant(variant const&);
|
// variant(variant const&); // constexpr in C++20
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@@ -126,7 +126,8 @@ void test_copy_ctor_sfinae() {
|
|||||||
static_assert(!std::is_copy_constructible<V>::value, "");
|
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>;
|
using V = std::variant<int, long>;
|
||||||
static_assert(std::is_trivially_copy_constructible<V>::value, "");
|
static_assert(std::is_trivially_copy_constructible<V>::value, "");
|
||||||
@@ -144,6 +145,7 @@ void test_copy_ctor_sfinae() {
|
|||||||
using V = std::variant<int, TCopyNTMove>;
|
using V = std::variant<int, TCopyNTMove>;
|
||||||
static_assert(std::is_trivially_copy_constructible<V>::value, "");
|
static_assert(std::is_trivially_copy_constructible<V>::value, "");
|
||||||
}
|
}
|
||||||
|
#endif // > C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_copy_ctor_basic() {
|
void test_copy_ctor_basic() {
|
||||||
@@ -174,7 +176,8 @@ void test_copy_ctor_basic() {
|
|||||||
assert(std::get<1>(v2).value == 42);
|
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);
|
constexpr std::variant<int> v(std::in_place_index<0>, 42);
|
||||||
static_assert(v.index() == 0, "");
|
static_assert(v.index() == 0, "");
|
||||||
@@ -217,6 +220,7 @@ void test_copy_ctor_basic() {
|
|||||||
static_assert(v2.index() == 1, "");
|
static_assert(v2.index() == 1, "");
|
||||||
static_assert(std::get<1>(v2).value == 42, "");
|
static_assert(std::get<1>(v2).value == 42, "");
|
||||||
}
|
}
|
||||||
|
#endif // > C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_copy_ctor_valueless_by_exception() {
|
void test_copy_ctor_valueless_by_exception() {
|
||||||
@@ -231,17 +235,16 @@ void test_copy_ctor_valueless_by_exception() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <size_t Idx>
|
template <size_t Idx>
|
||||||
constexpr bool test_constexpr_copy_ctor_extension_imp(
|
constexpr bool test_constexpr_copy_ctor_imp(std::variant<long, void*, const int> const& v) {
|
||||||
std::variant<long, void*, const int> const& v)
|
|
||||||
{
|
|
||||||
auto v2 = v;
|
auto v2 = v;
|
||||||
return v2.index() == v.index() &&
|
return v2.index() == v.index() &&
|
||||||
v2.index() == Idx &&
|
v2.index() == Idx &&
|
||||||
std::get<Idx>(v2) == std::get<Idx>(v);
|
std::get<Idx>(v2) == std::get<Idx>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_constexpr_copy_ctor_extension() {
|
void test_constexpr_copy_ctor() {
|
||||||
// NOTE: This test is for not yet standardized behavior. (P0602)
|
// 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>;
|
using V = std::variant<long, void*, const int>;
|
||||||
#ifdef TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
|
#ifdef TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
|
||||||
static_assert(std::is_trivially_destructible<V>::value, "");
|
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
|
#else // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
|
||||||
static_assert(std::is_trivially_copyable<V>::value, "");
|
static_assert(std::is_trivially_copyable<V>::value, "");
|
||||||
#endif // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
|
#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_imp<0>(V(42l)), "");
|
||||||
static_assert(test_constexpr_copy_ctor_extension_imp<1>(V(nullptr)), "");
|
static_assert(test_constexpr_copy_ctor_imp<1>(V(nullptr)), "");
|
||||||
static_assert(test_constexpr_copy_ctor_extension_imp<2>(V(101)), "");
|
static_assert(test_constexpr_copy_ctor_imp<2>(V(101)), "");
|
||||||
|
#endif // > C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
test_copy_ctor_basic();
|
test_copy_ctor_basic();
|
||||||
test_copy_ctor_valueless_by_exception();
|
test_copy_ctor_valueless_by_exception();
|
||||||
test_copy_ctor_sfinae();
|
test_copy_ctor_sfinae();
|
||||||
test_constexpr_copy_ctor_extension();
|
test_constexpr_copy_ctor();
|
||||||
#if 0
|
#if 0
|
||||||
// disable this for the moment; it fails on older compilers.
|
// disable this for the moment; it fails on older compilers.
|
||||||
// Need to figure out which compilers will support it.
|
// Need to figure out which compilers will support it.
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
// template <class ...Types> class variant;
|
// template <class ...Types> class variant;
|
||||||
|
|
||||||
// variant(variant&&) noexcept(see below);
|
// variant(variant&&) noexcept(see below); // constexpr in C++20
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -147,7 +147,8 @@ void test_move_ctor_sfinae() {
|
|||||||
static_assert(!std::is_move_constructible<V>::value, "");
|
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>;
|
using V = std::variant<int, long>;
|
||||||
static_assert(std::is_trivially_move_constructible<V>::value, "");
|
static_assert(std::is_trivially_move_constructible<V>::value, "");
|
||||||
@@ -165,6 +166,7 @@ void test_move_ctor_sfinae() {
|
|||||||
using V = std::variant<int, TMoveNTCopy>;
|
using V = std::variant<int, TMoveNTCopy>;
|
||||||
static_assert(std::is_trivially_move_constructible<V>::value, "");
|
static_assert(std::is_trivially_move_constructible<V>::value, "");
|
||||||
}
|
}
|
||||||
|
#endif // > C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -214,7 +216,8 @@ void test_move_ctor_basic() {
|
|||||||
assert(std::get<1>(v2).value == 42);
|
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 {
|
struct {
|
||||||
constexpr Result<int> operator()() const {
|
constexpr Result<int> operator()() const {
|
||||||
@@ -287,6 +290,7 @@ void test_move_ctor_basic() {
|
|||||||
static_assert(result.index == 1, "");
|
static_assert(result.index == 1, "");
|
||||||
static_assert(result.value.value == 42, "");
|
static_assert(result.value.value == 42, "");
|
||||||
}
|
}
|
||||||
|
#endif // > C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_move_ctor_valueless_by_exception() {
|
void test_move_ctor_valueless_by_exception() {
|
||||||
@@ -300,9 +304,7 @@ void test_move_ctor_valueless_by_exception() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <size_t Idx>
|
template <size_t Idx>
|
||||||
constexpr bool test_constexpr_ctor_extension_imp(
|
constexpr bool test_constexpr_ctor_imp(std::variant<long, void*, const int> const& v) {
|
||||||
std::variant<long, void*, const int> const& v)
|
|
||||||
{
|
|
||||||
auto copy = v;
|
auto copy = v;
|
||||||
auto v2 = std::move(copy);
|
auto v2 = std::move(copy);
|
||||||
return v2.index() == v.index() &&
|
return v2.index() == v.index() &&
|
||||||
@@ -310,8 +312,9 @@ constexpr bool test_constexpr_ctor_extension_imp(
|
|||||||
std::get<Idx>(v2) == std::get<Idx>(v);
|
std::get<Idx>(v2) == std::get<Idx>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_constexpr_move_ctor_extension() {
|
void test_constexpr_move_ctor() {
|
||||||
// NOTE: This test is for not yet standardized behavior. (P0602)
|
// 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>;
|
using V = std::variant<long, void*, const int>;
|
||||||
#ifdef TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
|
#ifdef TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
|
||||||
static_assert(std::is_trivially_destructible<V>::value, "");
|
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, "");
|
static_assert(std::is_trivially_copyable<V>::value, "");
|
||||||
#endif // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
|
#endif // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
|
||||||
static_assert(std::is_trivially_move_constructible<V>::value, "");
|
static_assert(std::is_trivially_move_constructible<V>::value, "");
|
||||||
static_assert(test_constexpr_ctor_extension_imp<0>(V(42l)), "");
|
static_assert(test_constexpr_ctor_imp<0>(V(42l)), "");
|
||||||
static_assert(test_constexpr_ctor_extension_imp<1>(V(nullptr)), "");
|
static_assert(test_constexpr_ctor_imp<1>(V(nullptr)), "");
|
||||||
static_assert(test_constexpr_ctor_extension_imp<2>(V(101)), "");
|
static_assert(test_constexpr_ctor_imp<2>(V(101)), "");
|
||||||
|
#endif // > C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
@@ -333,5 +337,5 @@ int main() {
|
|||||||
test_move_ctor_valueless_by_exception();
|
test_move_ctor_valueless_by_exception();
|
||||||
test_move_noexcept();
|
test_move_noexcept();
|
||||||
test_move_ctor_sfinae();
|
test_move_ctor_sfinae();
|
||||||
test_constexpr_move_ctor_extension();
|
test_constexpr_move_ctor();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/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/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/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/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/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>
|
<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>
|
||||||
|
|||||||
Reference in New Issue
Block a user