You've already forked Zygisk-Assistant
mirror of
https://github.com/snake-4/Zygisk-Assistant.git
synced 2025-09-06 06:37:02 +00:00
Initial commit
This commit is contained in:
+285
@@ -0,0 +1,285 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// <optional>
|
||||
|
||||
// template <class U> optional<T>& operator=(U&& v);
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "archetypes.h"
|
||||
|
||||
using std::optional;
|
||||
|
||||
struct ThrowAssign {
|
||||
static int dtor_called;
|
||||
ThrowAssign() = default;
|
||||
ThrowAssign(int) { TEST_THROW(42); }
|
||||
ThrowAssign& operator=(int) {
|
||||
TEST_THROW(42);
|
||||
}
|
||||
~ThrowAssign() { ++dtor_called; }
|
||||
};
|
||||
int ThrowAssign::dtor_called = 0;
|
||||
|
||||
template <class T, class Arg = T, bool Expect = true>
|
||||
void assert_assignable() {
|
||||
static_assert(std::is_assignable<optional<T>&, Arg>::value == Expect, "");
|
||||
static_assert(!std::is_assignable<const optional<T>&, Arg>::value, "");
|
||||
}
|
||||
|
||||
struct MismatchType {
|
||||
explicit MismatchType(int) {}
|
||||
explicit MismatchType(char*) {}
|
||||
explicit MismatchType(int*) = delete;
|
||||
MismatchType& operator=(int) { return *this; }
|
||||
MismatchType& operator=(int*) { return *this; }
|
||||
MismatchType& operator=(char*) = delete;
|
||||
};
|
||||
|
||||
struct FromOptionalType {
|
||||
using Opt = std::optional<FromOptionalType>;
|
||||
FromOptionalType() = default;
|
||||
FromOptionalType(FromOptionalType const&) = delete;
|
||||
template <class Dummy = void>
|
||||
constexpr FromOptionalType(Opt&) { Dummy::BARK; }
|
||||
template <class Dummy = void>
|
||||
constexpr FromOptionalType& operator=(Opt&) { Dummy::BARK; return *this; }
|
||||
};
|
||||
|
||||
void test_sfinae() {
|
||||
using I = TestTypes::TestType;
|
||||
using E = ExplicitTestTypes::TestType;
|
||||
assert_assignable<int>();
|
||||
assert_assignable<int, int&>();
|
||||
assert_assignable<int, int const&>();
|
||||
// Implicit test type
|
||||
assert_assignable<I, I const&>();
|
||||
assert_assignable<I, I&&>();
|
||||
assert_assignable<I, int>();
|
||||
assert_assignable<I, void*, false>();
|
||||
// Explicit test type
|
||||
assert_assignable<E, E const&>();
|
||||
assert_assignable<E, E &&>();
|
||||
assert_assignable<E, int>();
|
||||
assert_assignable<E, void*, false>();
|
||||
// Mismatch type
|
||||
assert_assignable<MismatchType, int>();
|
||||
assert_assignable<MismatchType, int*, false>();
|
||||
assert_assignable<MismatchType, char*, false>();
|
||||
// Type constructible from optional
|
||||
assert_assignable<FromOptionalType, std::optional<FromOptionalType>&, false>();
|
||||
}
|
||||
|
||||
void test_with_test_type()
|
||||
{
|
||||
using T = TestTypes::TestType;
|
||||
T::reset();
|
||||
{ // to empty
|
||||
optional<T> opt;
|
||||
opt = 3;
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 1);
|
||||
assert(T::value_constructed == 1);
|
||||
assert(T::assigned == 0);
|
||||
assert(T::destroyed == 0);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(3));
|
||||
}
|
||||
{ // to existing
|
||||
optional<T> opt(42);
|
||||
T::reset_constructors();
|
||||
opt = 3;
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 0);
|
||||
assert(T::assigned == 1);
|
||||
assert(T::value_assigned == 1);
|
||||
assert(T::destroyed == 0);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(3));
|
||||
}
|
||||
{ // test default argument
|
||||
optional<T> opt;
|
||||
T::reset_constructors();
|
||||
opt = {1, 2};
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 2);
|
||||
assert(T::value_constructed == 1);
|
||||
assert(T::move_constructed == 1);
|
||||
assert(T::assigned == 0);
|
||||
assert(T::destroyed == 1);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(1, 2));
|
||||
}
|
||||
{ // test default argument
|
||||
optional<T> opt(42);
|
||||
T::reset_constructors();
|
||||
opt = {1, 2};
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 1);
|
||||
assert(T::value_constructed == 1);
|
||||
assert(T::assigned == 1);
|
||||
assert(T::move_assigned == 1);
|
||||
assert(T::destroyed == 1);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(1, 2));
|
||||
}
|
||||
{ // test default argument
|
||||
optional<T> opt;
|
||||
T::reset_constructors();
|
||||
opt = {1};
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 2);
|
||||
assert(T::value_constructed == 1);
|
||||
assert(T::move_constructed == 1);
|
||||
assert(T::assigned == 0);
|
||||
assert(T::destroyed == 1);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(1));
|
||||
}
|
||||
{ // test default argument
|
||||
optional<T> opt(42);
|
||||
T::reset_constructors();
|
||||
opt = {};
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
assert(T::alive == 0);
|
||||
assert(T::constructed == 0);
|
||||
assert(T::assigned == 0);
|
||||
assert(T::destroyed == 1);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class Value = int>
|
||||
void test_with_type() {
|
||||
{ // to empty
|
||||
optional<T> opt;
|
||||
opt = Value(3);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(3));
|
||||
}
|
||||
{ // to existing
|
||||
optional<T> opt(Value(42));
|
||||
opt = Value(3);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(3));
|
||||
}
|
||||
{ // test const
|
||||
optional<T> opt(Value(42));
|
||||
const T t(Value(3));
|
||||
opt = t;
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(3));
|
||||
}
|
||||
{ // test default argument
|
||||
optional<T> opt;
|
||||
opt = {Value(1)};
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(1));
|
||||
}
|
||||
{ // test default argument
|
||||
optional<T> opt(Value(42));
|
||||
opt = {};
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void test_with_type_multi() {
|
||||
test_with_type<T>();
|
||||
{ // test default argument
|
||||
optional<T> opt;
|
||||
opt = {1, 2};
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(1, 2));
|
||||
}
|
||||
{ // test default argument
|
||||
optional<T> opt(42);
|
||||
opt = {1, 2};
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(1, 2));
|
||||
}
|
||||
}
|
||||
|
||||
void test_throws()
|
||||
{
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
using T = ThrowAssign;
|
||||
{
|
||||
optional<T> opt;
|
||||
try {
|
||||
opt = 42;
|
||||
assert(false);
|
||||
} catch (int) {}
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
assert(T::dtor_called == 0);
|
||||
{
|
||||
T::dtor_called = 0;
|
||||
optional<T> opt(std::in_place);
|
||||
try {
|
||||
opt = 42;
|
||||
assert(false);
|
||||
} catch (int) {}
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(T::dtor_called == 0);
|
||||
}
|
||||
assert(T::dtor_called == 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
enum MyEnum { Zero, One, Two, Three, FortyTwo = 42 };
|
||||
|
||||
using Fn = void(*)();
|
||||
|
||||
// https://llvm.org/PR38638
|
||||
template <class T>
|
||||
constexpr T pr38638(T v)
|
||||
{
|
||||
std::optional<T> o;
|
||||
o = v;
|
||||
return *o + 2;
|
||||
}
|
||||
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_sfinae();
|
||||
// Test with instrumented type
|
||||
test_with_test_type();
|
||||
// Test with various scalar types
|
||||
test_with_type<int>();
|
||||
test_with_type<MyEnum, MyEnum>();
|
||||
test_with_type<int, MyEnum>();
|
||||
test_with_type<Fn, Fn>();
|
||||
// Test types with multi argument constructors
|
||||
test_with_type_multi<ConstexprTestTypes::TestType>();
|
||||
test_with_type_multi<TrivialTestTypes::TestType>();
|
||||
// Test move only types
|
||||
{
|
||||
optional<std::unique_ptr<int>> opt;
|
||||
opt = std::unique_ptr<int>(new int(3));
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(**opt == 3);
|
||||
}
|
||||
{
|
||||
optional<std::unique_ptr<int>> opt(std::unique_ptr<int>(new int(2)));
|
||||
opt = std::unique_ptr<int>(new int(3));
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(**opt == 3);
|
||||
}
|
||||
test_throws();
|
||||
|
||||
static_assert(pr38638(3) == 5, "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// <optional>
|
||||
|
||||
// From LWG2451:
|
||||
// template<class U>
|
||||
// optional<T>& operator=(const optional<U>& rhs);
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "archetypes.h"
|
||||
|
||||
using std::optional;
|
||||
|
||||
struct X
|
||||
{
|
||||
static bool throw_now;
|
||||
|
||||
X() = default;
|
||||
X(int)
|
||||
{
|
||||
if (throw_now)
|
||||
TEST_THROW(6);
|
||||
}
|
||||
};
|
||||
|
||||
bool X::throw_now = false;
|
||||
|
||||
struct Y1
|
||||
{
|
||||
Y1() = default;
|
||||
Y1(const int&) {}
|
||||
Y1& operator=(const Y1&) = delete;
|
||||
};
|
||||
|
||||
struct Y2
|
||||
{
|
||||
Y2() = default;
|
||||
Y2(const int&) = delete;
|
||||
Y2& operator=(const int&) { return *this; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct AssignableFrom {
|
||||
static int type_constructed;
|
||||
static int type_assigned;
|
||||
static int int_constructed;
|
||||
static int int_assigned;
|
||||
|
||||
static void reset() {
|
||||
type_constructed = int_constructed = 0;
|
||||
type_assigned = int_assigned = 0;
|
||||
}
|
||||
|
||||
AssignableFrom() = default;
|
||||
|
||||
explicit AssignableFrom(T) { ++type_constructed; }
|
||||
AssignableFrom& operator=(T) { ++type_assigned; return *this; }
|
||||
|
||||
AssignableFrom(int) { ++int_constructed; }
|
||||
AssignableFrom& operator=(int) { ++int_assigned; return *this; }
|
||||
private:
|
||||
AssignableFrom(AssignableFrom const&) = delete;
|
||||
AssignableFrom& operator=(AssignableFrom const&) = delete;
|
||||
};
|
||||
|
||||
template <class T> int AssignableFrom<T>::type_constructed = 0;
|
||||
template <class T> int AssignableFrom<T>::type_assigned = 0;
|
||||
template <class T> int AssignableFrom<T>::int_constructed = 0;
|
||||
template <class T> int AssignableFrom<T>::int_assigned = 0;
|
||||
|
||||
|
||||
void test_with_test_type() {
|
||||
using T = TestTypes::TestType;
|
||||
T::reset();
|
||||
{ // non-empty to empty
|
||||
T::reset_constructors();
|
||||
optional<T> opt;
|
||||
const optional<int> other(42);
|
||||
opt = other;
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 1);
|
||||
assert(T::value_constructed == 1);
|
||||
assert(T::assigned == 0);
|
||||
assert(T::destroyed == 0);
|
||||
assert(static_cast<bool>(other) == true);
|
||||
assert(*other == 42);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(42));
|
||||
}
|
||||
assert(T::alive == 0);
|
||||
{ // non-empty to non-empty
|
||||
optional<T> opt(101);
|
||||
const optional<int> other(42);
|
||||
T::reset_constructors();
|
||||
opt = other;
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 0);
|
||||
assert(T::assigned == 1);
|
||||
assert(T::value_assigned == 1);
|
||||
assert(T::destroyed == 0);
|
||||
assert(static_cast<bool>(other) == true);
|
||||
assert(*other == 42);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(42));
|
||||
}
|
||||
assert(T::alive == 0);
|
||||
{ // empty to non-empty
|
||||
optional<T> opt(101);
|
||||
const optional<int> other;
|
||||
T::reset_constructors();
|
||||
opt = other;
|
||||
assert(T::alive == 0);
|
||||
assert(T::constructed == 0);
|
||||
assert(T::assigned == 0);
|
||||
assert(T::destroyed == 1);
|
||||
assert(static_cast<bool>(other) == false);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
assert(T::alive == 0);
|
||||
{ // empty to empty
|
||||
optional<T> opt;
|
||||
const optional<int> other;
|
||||
T::reset_constructors();
|
||||
opt = other;
|
||||
assert(T::alive == 0);
|
||||
assert(T::constructed == 0);
|
||||
assert(T::assigned == 0);
|
||||
assert(T::destroyed == 0);
|
||||
assert(static_cast<bool>(other) == false);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
assert(T::alive == 0);
|
||||
}
|
||||
|
||||
void test_ambiguous_assign() {
|
||||
using OptInt = std::optional<int>;
|
||||
{
|
||||
using T = AssignableFrom<OptInt const&>;
|
||||
const OptInt a(42);
|
||||
T::reset();
|
||||
{
|
||||
std::optional<T> t;
|
||||
t = a;
|
||||
assert(T::type_constructed == 1);
|
||||
assert(T::type_assigned == 0);
|
||||
assert(T::int_constructed == 0);
|
||||
assert(T::int_assigned == 0);
|
||||
}
|
||||
T::reset();
|
||||
{
|
||||
std::optional<T> t(42);
|
||||
t = a;
|
||||
assert(T::type_constructed == 0);
|
||||
assert(T::type_assigned == 1);
|
||||
assert(T::int_constructed == 1);
|
||||
assert(T::int_assigned == 0);
|
||||
}
|
||||
T::reset();
|
||||
{
|
||||
std::optional<T> t(42);
|
||||
t = std::move(a);
|
||||
assert(T::type_constructed == 0);
|
||||
assert(T::type_assigned == 1);
|
||||
assert(T::int_constructed == 1);
|
||||
assert(T::int_assigned == 0);
|
||||
}
|
||||
}
|
||||
{
|
||||
using T = AssignableFrom<OptInt&>;
|
||||
OptInt a(42);
|
||||
T::reset();
|
||||
{
|
||||
std::optional<T> t;
|
||||
t = a;
|
||||
assert(T::type_constructed == 1);
|
||||
assert(T::type_assigned == 0);
|
||||
assert(T::int_constructed == 0);
|
||||
assert(T::int_assigned == 0);
|
||||
}
|
||||
{
|
||||
using Opt = std::optional<T>;
|
||||
static_assert(!std::is_assignable_v<Opt&, OptInt const&>, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_with_test_type();
|
||||
test_ambiguous_assign();
|
||||
{
|
||||
optional<int> opt;
|
||||
constexpr optional<short> opt2;
|
||||
opt = opt2;
|
||||
static_assert(static_cast<bool>(opt2) == false, "");
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
}
|
||||
{
|
||||
optional<int> opt;
|
||||
constexpr optional<short> opt2(short{2});
|
||||
opt = opt2;
|
||||
static_assert(static_cast<bool>(opt2) == true, "");
|
||||
static_assert(*opt2 == 2, "");
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
assert(*opt == *opt2);
|
||||
}
|
||||
{
|
||||
optional<int> opt(3);
|
||||
constexpr optional<short> opt2;
|
||||
opt = opt2;
|
||||
static_assert(static_cast<bool>(opt2) == false, "");
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
}
|
||||
{
|
||||
optional<int> opt(3);
|
||||
constexpr optional<short> opt2(short{2});
|
||||
opt = opt2;
|
||||
static_assert(static_cast<bool>(opt2) == true, "");
|
||||
static_assert(*opt2 == 2, "");
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
assert(*opt == *opt2);
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
{
|
||||
optional<X> opt;
|
||||
optional<int> opt2(42);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
try
|
||||
{
|
||||
X::throw_now = true;
|
||||
opt = opt2;
|
||||
assert(false);
|
||||
}
|
||||
catch (int i)
|
||||
{
|
||||
assert(i == 6);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// <optional>
|
||||
|
||||
// optional<T>& operator=(const optional<T>& rhs); // constexpr in C++20
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "archetypes.h"
|
||||
|
||||
using std::optional;
|
||||
|
||||
struct X
|
||||
{
|
||||
static bool throw_now;
|
||||
|
||||
X() = default;
|
||||
X(const X&)
|
||||
{
|
||||
if (throw_now)
|
||||
TEST_THROW(6);
|
||||
}
|
||||
X& operator=(X const&) = default;
|
||||
};
|
||||
|
||||
bool X::throw_now = false;
|
||||
|
||||
template <class Tp>
|
||||
constexpr bool assign_empty(optional<Tp>&& lhs) {
|
||||
const optional<Tp> rhs;
|
||||
lhs = rhs;
|
||||
return !lhs.has_value() && !rhs.has_value();
|
||||
}
|
||||
|
||||
template <class Tp>
|
||||
constexpr bool assign_value(optional<Tp>&& lhs) {
|
||||
const optional<Tp> rhs(101);
|
||||
lhs = rhs;
|
||||
return lhs.has_value() && rhs.has_value() && *lhs == *rhs;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
{
|
||||
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}));
|
||||
}
|
||||
{
|
||||
using O = optional<TestTypes::TestType>;
|
||||
assert(assign_empty(O{42}));
|
||||
assert(assign_value(O{42}));
|
||||
}
|
||||
{
|
||||
using T = TestTypes::TestType;
|
||||
T::reset();
|
||||
optional<T> opt(3);
|
||||
const optional<T> opt2;
|
||||
assert(T::alive == 1);
|
||||
opt = opt2;
|
||||
assert(T::alive == 0);
|
||||
assert(!opt2.has_value());
|
||||
assert(!opt.has_value());
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
{
|
||||
optional<X> opt;
|
||||
optional<X> opt2(X{});
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
try
|
||||
{
|
||||
X::throw_now = true;
|
||||
opt = opt2;
|
||||
assert(false);
|
||||
}
|
||||
catch (int i)
|
||||
{
|
||||
assert(i == 6);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
+295
@@ -0,0 +1,295 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// <optional>
|
||||
|
||||
// template <class... Args> T& optional<T>::emplace(Args&&... args);
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "archetypes.h"
|
||||
|
||||
using std::optional;
|
||||
|
||||
class X
|
||||
{
|
||||
int i_;
|
||||
int j_ = 0;
|
||||
public:
|
||||
constexpr X() : i_(0) {}
|
||||
constexpr X(int i) : i_(i) {}
|
||||
constexpr X(int i, int j) : i_(i), j_(j) {}
|
||||
|
||||
friend constexpr bool operator==(const X& x, const X& y)
|
||||
{return x.i_ == y.i_ && x.j_ == y.j_;}
|
||||
};
|
||||
|
||||
class Y
|
||||
{
|
||||
public:
|
||||
static bool dtor_called;
|
||||
Y() = default;
|
||||
Y(int) { TEST_THROW(6);}
|
||||
~Y() {dtor_called = true;}
|
||||
};
|
||||
|
||||
bool Y::dtor_called = false;
|
||||
|
||||
template <class T>
|
||||
constexpr bool test_one_arg() {
|
||||
using Opt = std::optional<T>;
|
||||
{
|
||||
Opt opt;
|
||||
auto & v = opt.emplace();
|
||||
static_assert( std::is_same_v<T&, decltype(v)>, "" );
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(0));
|
||||
assert(&v == &*opt);
|
||||
}
|
||||
{
|
||||
Opt opt;
|
||||
auto & v = opt.emplace(1);
|
||||
static_assert( std::is_same_v<T&, decltype(v)>, "" );
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(1));
|
||||
assert(&v == &*opt);
|
||||
}
|
||||
{
|
||||
Opt opt(2);
|
||||
auto & v = opt.emplace();
|
||||
static_assert( std::is_same_v<T&, decltype(v)>, "" );
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(0));
|
||||
assert(&v == &*opt);
|
||||
}
|
||||
{
|
||||
Opt opt(2);
|
||||
auto & v = opt.emplace(1);
|
||||
static_assert( std::is_same_v<T&, decltype(v)>, "" );
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(1));
|
||||
assert(&v == &*opt);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
constexpr bool test_multi_arg()
|
||||
{
|
||||
test_one_arg<T>();
|
||||
using Opt = std::optional<T>;
|
||||
{
|
||||
Opt opt;
|
||||
auto &v = opt.emplace(101, 41);
|
||||
static_assert( std::is_same_v<T&, decltype(v)>, "" );
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert( v == T(101, 41));
|
||||
assert(*opt == T(101, 41));
|
||||
}
|
||||
{
|
||||
Opt opt;
|
||||
auto &v = opt.emplace({1, 2, 3, 4});
|
||||
static_assert( std::is_same_v<T&, decltype(v)>, "" );
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert( v == T(4)); // T sets its value to the size of the init list
|
||||
assert(*opt == T(4));
|
||||
}
|
||||
{
|
||||
Opt opt;
|
||||
auto &v = opt.emplace({1, 2, 3, 4, 5}, 6);
|
||||
static_assert( std::is_same_v<T&, decltype(v)>, "" );
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert( v == T(5)); // T sets its value to the size of the init list
|
||||
assert(*opt == T(5)); // T sets its value to the size of the init list
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void test_on_test_type() {
|
||||
|
||||
T::reset();
|
||||
optional<T> opt;
|
||||
assert(T::alive == 0);
|
||||
{
|
||||
T::reset_constructors();
|
||||
auto &v = opt.emplace();
|
||||
static_assert( std::is_same_v<T&, decltype(v)>, "" );
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 1);
|
||||
assert(T::default_constructed == 1);
|
||||
assert(T::destroyed == 0);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T());
|
||||
assert(&v == &*opt);
|
||||
}
|
||||
{
|
||||
T::reset_constructors();
|
||||
auto &v = opt.emplace();
|
||||
static_assert( std::is_same_v<T&, decltype(v)>, "" );
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 1);
|
||||
assert(T::default_constructed == 1);
|
||||
assert(T::destroyed == 1);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T());
|
||||
assert(&v == &*opt);
|
||||
}
|
||||
{
|
||||
T::reset_constructors();
|
||||
auto &v = opt.emplace(101);
|
||||
static_assert( std::is_same_v<T&, decltype(v)>, "" );
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 1);
|
||||
assert(T::value_constructed == 1);
|
||||
assert(T::destroyed == 1);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(101));
|
||||
assert(&v == &*opt);
|
||||
}
|
||||
{
|
||||
T::reset_constructors();
|
||||
auto &v = opt.emplace(-10, 99);
|
||||
static_assert( std::is_same_v<T&, decltype(v)>, "" );
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 1);
|
||||
assert(T::value_constructed == 1);
|
||||
assert(T::destroyed == 1);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(-10, 99));
|
||||
assert(&v == &*opt);
|
||||
}
|
||||
{
|
||||
T::reset_constructors();
|
||||
auto &v = opt.emplace(-10, 99);
|
||||
static_assert( std::is_same_v<T&, decltype(v)>, "" );
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 1);
|
||||
assert(T::value_constructed == 1);
|
||||
assert(T::destroyed == 1);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(-10, 99));
|
||||
assert(&v == &*opt);
|
||||
}
|
||||
{
|
||||
T::reset_constructors();
|
||||
auto &v = opt.emplace({-10, 99, 42, 1});
|
||||
static_assert( std::is_same_v<T&, decltype(v)>, "" );
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 1);
|
||||
assert(T::value_constructed == 1);
|
||||
assert(T::destroyed == 1);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(4)); // size of the initializer list
|
||||
assert(&v == &*opt);
|
||||
}
|
||||
{
|
||||
T::reset_constructors();
|
||||
auto &v = opt.emplace({-10, 99, 42, 1}, 42);
|
||||
static_assert( std::is_same_v<T&, decltype(v)>, "" );
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 1);
|
||||
assert(T::value_constructed == 1);
|
||||
assert(T::destroyed == 1);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(4)); // size of the initializer list
|
||||
assert(&v == &*opt);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool test_empty_emplace()
|
||||
{
|
||||
optional<const int> opt;
|
||||
auto &v = opt.emplace(42);
|
||||
static_assert( std::is_same_v<const int&, decltype(v)>, "" );
|
||||
assert(*opt == 42);
|
||||
assert( v == 42);
|
||||
opt.emplace();
|
||||
assert(*opt == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
{
|
||||
test_on_test_type<TestTypes::TestType>();
|
||||
test_on_test_type<ExplicitTestTypes::TestType>();
|
||||
}
|
||||
{
|
||||
using T = int;
|
||||
test_one_arg<T>();
|
||||
test_one_arg<const T>();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_one_arg<T>());
|
||||
static_assert(test_one_arg<const T>());
|
||||
#endif
|
||||
}
|
||||
{
|
||||
using T = ConstexprTestTypes::TestType;
|
||||
test_multi_arg<T>();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_multi_arg<T>());
|
||||
#endif
|
||||
}
|
||||
{
|
||||
using T = ExplicitConstexprTestTypes::TestType;
|
||||
test_multi_arg<T>();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_multi_arg<T>());
|
||||
#endif
|
||||
}
|
||||
{
|
||||
using T = TrivialTestTypes::TestType;
|
||||
test_multi_arg<T>();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_multi_arg<T>());
|
||||
#endif
|
||||
}
|
||||
{
|
||||
using T = ExplicitTrivialTestTypes::TestType;
|
||||
test_multi_arg<T>();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_multi_arg<T>());
|
||||
#endif
|
||||
}
|
||||
{
|
||||
test_empty_emplace();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_empty_emplace());
|
||||
#endif
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
Y::dtor_called = false;
|
||||
{
|
||||
Y y;
|
||||
optional<Y> opt(y);
|
||||
try
|
||||
{
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(Y::dtor_called == false);
|
||||
auto &v = opt.emplace(1);
|
||||
static_assert( std::is_same_v<Y&, decltype(v)>, "" );
|
||||
assert(false);
|
||||
}
|
||||
catch (int i)
|
||||
{
|
||||
assert(i == 6);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
assert(Y::dtor_called == true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// <optional>
|
||||
|
||||
// template <class U, class... Args>
|
||||
// T& optional<T>::emplace(initializer_list<U> il, Args&&... args);
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
using std::optional;
|
||||
|
||||
class X
|
||||
{
|
||||
int i_;
|
||||
int j_ = 0;
|
||||
bool* dtor_called_;
|
||||
public:
|
||||
constexpr X(bool& dtor_called) : i_(0), dtor_called_(&dtor_called) {}
|
||||
constexpr X(int i, bool& dtor_called) : i_(i), dtor_called_(&dtor_called) {}
|
||||
constexpr X(std::initializer_list<int> il, bool& dtor_called)
|
||||
: i_(il.begin()[0]), j_(il.begin()[1]), dtor_called_(&dtor_called) {}
|
||||
TEST_CONSTEXPR_CXX20 ~X() {*dtor_called_ = true;}
|
||||
|
||||
friend constexpr bool operator==(const X& x, const X& y)
|
||||
{return x.i_ == y.i_ && x.j_ == y.j_;}
|
||||
};
|
||||
|
||||
class Y
|
||||
{
|
||||
int i_;
|
||||
int j_ = 0;
|
||||
public:
|
||||
constexpr Y() : i_(0) {}
|
||||
constexpr Y(int i) : i_(i) {}
|
||||
constexpr Y(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {}
|
||||
|
||||
friend constexpr bool operator==(const Y& x, const Y& y)
|
||||
{return x.i_ == y.i_ && x.j_ == y.j_;}
|
||||
};
|
||||
|
||||
class Z
|
||||
{
|
||||
int i_;
|
||||
int j_ = 0;
|
||||
public:
|
||||
static bool dtor_called;
|
||||
Z() : i_(0) {}
|
||||
Z(int i) : i_(i) {}
|
||||
Z(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1])
|
||||
{ TEST_THROW(6);}
|
||||
~Z() {dtor_called = true;}
|
||||
|
||||
friend bool operator==(const Z& x, const Z& y)
|
||||
{return x.i_ == y.i_ && x.j_ == y.j_;}
|
||||
};
|
||||
|
||||
bool Z::dtor_called = false;
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool check_X()
|
||||
{
|
||||
bool dtor_called = false;
|
||||
X x(dtor_called);
|
||||
optional<X> opt(x);
|
||||
assert(dtor_called == false);
|
||||
auto &v = opt.emplace({1, 2}, dtor_called);
|
||||
static_assert( std::is_same_v<X&, decltype(v)>, "" );
|
||||
assert(dtor_called);
|
||||
assert(*opt == X({1, 2}, dtor_called));
|
||||
assert(&v == &*opt);
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool check_Y()
|
||||
{
|
||||
optional<Y> opt;
|
||||
auto &v = opt.emplace({1, 2});
|
||||
static_assert( std::is_same_v<Y&, decltype(v)>, "" );
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == Y({1, 2}));
|
||||
assert(&v == &*opt);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
{
|
||||
check_X();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(check_X());
|
||||
#endif
|
||||
}
|
||||
{
|
||||
optional<std::vector<int>> opt;
|
||||
auto &v = opt.emplace({1, 2, 3}, std::allocator<int>());
|
||||
static_assert( std::is_same_v<std::vector<int>&, decltype(v)>, "" );
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == std::vector<int>({1, 2, 3}));
|
||||
assert(&v == &*opt);
|
||||
}
|
||||
{
|
||||
check_Y();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(check_Y());
|
||||
#endif
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
{
|
||||
Z z;
|
||||
optional<Z> opt(z);
|
||||
try
|
||||
{
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(Z::dtor_called == false);
|
||||
auto &v = opt.emplace({1, 2});
|
||||
static_assert( std::is_same_v<Z&, decltype(v)>, "" );
|
||||
assert(false);
|
||||
}
|
||||
catch (int i)
|
||||
{
|
||||
assert(i == 6);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
assert(Z::dtor_called == true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// <optional>
|
||||
|
||||
// optional<T>& operator=(optional<T>&& rhs)
|
||||
// noexcept(is_nothrow_move_assignable<T>::value &&
|
||||
// is_nothrow_move_constructible<T>::value); // constexpr in C++20
|
||||
|
||||
#include <optional>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "archetypes.h"
|
||||
|
||||
using std::optional;
|
||||
|
||||
struct X
|
||||
{
|
||||
static bool throw_now;
|
||||
static int alive;
|
||||
|
||||
X() { ++alive; }
|
||||
X(X&&)
|
||||
{
|
||||
if (throw_now)
|
||||
TEST_THROW(6);
|
||||
++alive;
|
||||
}
|
||||
|
||||
X& operator=(X&&)
|
||||
{
|
||||
if (throw_now)
|
||||
TEST_THROW(42);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~X() { assert(alive > 0); --alive; }
|
||||
};
|
||||
|
||||
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(int, char**)
|
||||
{
|
||||
{
|
||||
static_assert(std::is_nothrow_move_assignable<optional<int>>::value, "");
|
||||
optional<int> opt;
|
||||
constexpr optional<int> opt2;
|
||||
opt = std::move(opt2);
|
||||
static_assert(static_cast<bool>(opt2) == false, "");
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
}
|
||||
{
|
||||
optional<int> opt;
|
||||
constexpr optional<int> opt2(2);
|
||||
opt = std::move(opt2);
|
||||
static_assert(static_cast<bool>(opt2) == true, "");
|
||||
static_assert(*opt2 == 2, "");
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
assert(*opt == *opt2);
|
||||
}
|
||||
{
|
||||
optional<int> opt(3);
|
||||
constexpr optional<int> opt2;
|
||||
opt = std::move(opt2);
|
||||
static_assert(static_cast<bool>(opt2) == false, "");
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
}
|
||||
{
|
||||
using T = TestTypes::TestType;
|
||||
T::reset();
|
||||
optional<T> opt(3);
|
||||
optional<T> opt2;
|
||||
assert(T::alive == 1);
|
||||
opt = std::move(opt2);
|
||||
assert(T::alive == 0);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
}
|
||||
{
|
||||
optional<int> opt(3);
|
||||
constexpr optional<int> opt2(2);
|
||||
opt = std::move(opt2);
|
||||
static_assert(static_cast<bool>(opt2) == true, "");
|
||||
static_assert(*opt2 == 2, "");
|
||||
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, "");
|
||||
X::alive = 0;
|
||||
X::throw_now = false;
|
||||
optional<X> opt;
|
||||
optional<X> opt2(X{});
|
||||
assert(X::alive == 1);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
try
|
||||
{
|
||||
X::throw_now = true;
|
||||
opt = std::move(opt2);
|
||||
assert(false);
|
||||
}
|
||||
catch (int i)
|
||||
{
|
||||
assert(i == 6);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
assert(X::alive == 1);
|
||||
}
|
||||
assert(X::alive == 0);
|
||||
{
|
||||
static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
|
||||
X::throw_now = false;
|
||||
optional<X> opt(X{});
|
||||
optional<X> opt2(X{});
|
||||
assert(X::alive == 2);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
try
|
||||
{
|
||||
X::throw_now = true;
|
||||
opt = std::move(opt2);
|
||||
assert(false);
|
||||
}
|
||||
catch (int i)
|
||||
{
|
||||
assert(i == 42);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
}
|
||||
assert(X::alive == 2);
|
||||
}
|
||||
assert(X::alive == 0);
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
{
|
||||
static_assert(std::is_nothrow_move_assignable<optional<Y>>::value, "");
|
||||
}
|
||||
{
|
||||
struct ThrowsMove {
|
||||
ThrowsMove() noexcept {}
|
||||
ThrowsMove(ThrowsMove const&) noexcept {}
|
||||
ThrowsMove(ThrowsMove &&) noexcept(false) {}
|
||||
ThrowsMove& operator=(ThrowsMove const&) noexcept { return *this; }
|
||||
ThrowsMove& operator=(ThrowsMove &&) noexcept { return *this; }
|
||||
};
|
||||
static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMove>>::value, "");
|
||||
struct ThrowsMoveAssign {
|
||||
ThrowsMoveAssign() noexcept {}
|
||||
ThrowsMoveAssign(ThrowsMoveAssign const&) noexcept {}
|
||||
ThrowsMoveAssign(ThrowsMoveAssign &&) noexcept {}
|
||||
ThrowsMoveAssign& operator=(ThrowsMoveAssign const&) noexcept { return *this; }
|
||||
ThrowsMoveAssign& operator=(ThrowsMoveAssign &&) noexcept(false) { return *this; }
|
||||
};
|
||||
static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMoveAssign>>::value, "");
|
||||
struct NoThrowMove {
|
||||
NoThrowMove() noexcept(false) {}
|
||||
NoThrowMove(NoThrowMove const&) noexcept(false) {}
|
||||
NoThrowMove(NoThrowMove &&) noexcept {}
|
||||
NoThrowMove& operator=(NoThrowMove const&) noexcept { return *this; }
|
||||
NoThrowMove& operator=(NoThrowMove&&) noexcept { return *this; }
|
||||
};
|
||||
static_assert(std::is_nothrow_move_assignable<optional<NoThrowMove>>::value, "");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// <optional>
|
||||
|
||||
// optional<T>& operator=(nullopt_t) noexcept;
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "archetypes.h"
|
||||
|
||||
using std::optional;
|
||||
using std::nullopt_t;
|
||||
using std::nullopt;
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test()
|
||||
{
|
||||
enum class State { inactive, constructed, destroyed };
|
||||
State state = State::inactive;
|
||||
|
||||
struct StateTracker {
|
||||
TEST_CONSTEXPR_CXX20 StateTracker(State& s)
|
||||
: state_(&s)
|
||||
{
|
||||
s = State::constructed;
|
||||
}
|
||||
TEST_CONSTEXPR_CXX20 ~StateTracker() { *state_ = State::destroyed; }
|
||||
|
||||
State* state_;
|
||||
};
|
||||
{
|
||||
optional<int> opt;
|
||||
static_assert(noexcept(opt = nullopt) == true, "");
|
||||
opt = nullopt;
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
{
|
||||
optional<int> opt(3);
|
||||
opt = nullopt;
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
{
|
||||
optional<StateTracker> opt;
|
||||
opt = nullopt;
|
||||
assert(state == State::inactive);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
{
|
||||
optional<StateTracker> opt(state);
|
||||
assert(state == State::constructed);
|
||||
opt = nullopt;
|
||||
assert(state == State::destroyed);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test());
|
||||
#endif
|
||||
test();
|
||||
using TT = TestTypes::TestType;
|
||||
TT::reset();
|
||||
{
|
||||
optional<TT> opt;
|
||||
static_assert(noexcept(opt = nullopt) == true, "");
|
||||
assert(TT::destroyed == 0);
|
||||
opt = nullopt;
|
||||
assert(TT::constructed == 0);
|
||||
assert(TT::alive == 0);
|
||||
assert(TT::destroyed == 0);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
assert(TT::alive == 0);
|
||||
assert(TT::destroyed == 0);
|
||||
TT::reset();
|
||||
{
|
||||
optional<TT> opt(42);
|
||||
assert(TT::destroyed == 0);
|
||||
TT::reset_constructors();
|
||||
opt = nullopt;
|
||||
assert(TT::constructed == 0);
|
||||
assert(TT::alive == 0);
|
||||
assert(TT::destroyed == 1);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
assert(TT::alive == 0);
|
||||
assert(TT::destroyed == 1);
|
||||
TT::reset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
+338
@@ -0,0 +1,338 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// <optional>
|
||||
|
||||
// From LWG2451:
|
||||
// template <class U>
|
||||
// optional<T>& operator=(optional<U>&& rhs);
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "archetypes.h"
|
||||
|
||||
using std::optional;
|
||||
|
||||
struct X
|
||||
{
|
||||
static bool throw_now;
|
||||
|
||||
X() = default;
|
||||
X(int &&)
|
||||
{
|
||||
if (throw_now)
|
||||
TEST_THROW(6);
|
||||
}
|
||||
};
|
||||
|
||||
bool X::throw_now = false;
|
||||
|
||||
struct Y1
|
||||
{
|
||||
Y1() = default;
|
||||
Y1(const int&) {}
|
||||
Y1& operator=(const Y1&) = delete;
|
||||
};
|
||||
|
||||
struct Y2
|
||||
{
|
||||
Y2() = default;
|
||||
Y2(const int&) = delete;
|
||||
Y2& operator=(const int&) { return *this; }
|
||||
};
|
||||
|
||||
struct B { virtual ~B() = default; };
|
||||
class D : public B {};
|
||||
|
||||
|
||||
template <class T>
|
||||
struct AssignableFrom {
|
||||
static int type_constructed;
|
||||
static int type_assigned;
|
||||
static int int_constructed;
|
||||
static int int_assigned;
|
||||
|
||||
static void reset() {
|
||||
type_constructed = int_constructed = 0;
|
||||
type_assigned = int_assigned = 0;
|
||||
}
|
||||
|
||||
AssignableFrom() = default;
|
||||
|
||||
explicit AssignableFrom(T) { ++type_constructed; }
|
||||
AssignableFrom& operator=(T) { ++type_assigned; return *this; }
|
||||
|
||||
AssignableFrom(int) { ++int_constructed; }
|
||||
AssignableFrom& operator=(int) { ++int_assigned; return *this; }
|
||||
private:
|
||||
AssignableFrom(AssignableFrom const&) = delete;
|
||||
AssignableFrom& operator=(AssignableFrom const&) = delete;
|
||||
};
|
||||
|
||||
template <class T> int AssignableFrom<T>::type_constructed = 0;
|
||||
template <class T> int AssignableFrom<T>::type_assigned = 0;
|
||||
template <class T> int AssignableFrom<T>::int_constructed = 0;
|
||||
template <class T> int AssignableFrom<T>::int_assigned = 0;
|
||||
|
||||
void test_with_test_type() {
|
||||
using T = TestTypes::TestType;
|
||||
T::reset();
|
||||
{ // non-empty to empty
|
||||
T::reset_constructors();
|
||||
optional<T> opt;
|
||||
optional<int> other(42);
|
||||
opt = std::move(other);
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 1);
|
||||
assert(T::value_constructed == 1);
|
||||
assert(T::assigned == 0);
|
||||
assert(T::destroyed == 0);
|
||||
assert(static_cast<bool>(other) == true);
|
||||
assert(*other == 42);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(42));
|
||||
}
|
||||
assert(T::alive == 0);
|
||||
{ // non-empty to non-empty
|
||||
optional<T> opt(101);
|
||||
optional<int> other(42);
|
||||
T::reset_constructors();
|
||||
opt = std::move(other);
|
||||
assert(T::alive == 1);
|
||||
assert(T::constructed == 0);
|
||||
assert(T::assigned == 1);
|
||||
assert(T::value_assigned == 1);
|
||||
assert(T::destroyed == 0);
|
||||
assert(static_cast<bool>(other) == true);
|
||||
assert(*other == 42);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == T(42));
|
||||
}
|
||||
assert(T::alive == 0);
|
||||
{ // empty to non-empty
|
||||
optional<T> opt(101);
|
||||
optional<int> other;
|
||||
T::reset_constructors();
|
||||
opt = std::move(other);
|
||||
assert(T::alive == 0);
|
||||
assert(T::constructed == 0);
|
||||
assert(T::assigned == 0);
|
||||
assert(T::destroyed == 1);
|
||||
assert(static_cast<bool>(other) == false);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
assert(T::alive == 0);
|
||||
{ // empty to empty
|
||||
optional<T> opt;
|
||||
optional<int> other;
|
||||
T::reset_constructors();
|
||||
opt = std::move(other);
|
||||
assert(T::alive == 0);
|
||||
assert(T::constructed == 0);
|
||||
assert(T::assigned == 0);
|
||||
assert(T::destroyed == 0);
|
||||
assert(static_cast<bool>(other) == false);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
assert(T::alive == 0);
|
||||
}
|
||||
|
||||
|
||||
void test_ambiguous_assign() {
|
||||
using OptInt = std::optional<int>;
|
||||
{
|
||||
using T = AssignableFrom<OptInt&&>;
|
||||
T::reset();
|
||||
{
|
||||
OptInt a(42);
|
||||
std::optional<T> t;
|
||||
t = std::move(a);
|
||||
assert(T::type_constructed == 1);
|
||||
assert(T::type_assigned == 0);
|
||||
assert(T::int_constructed == 0);
|
||||
assert(T::int_assigned == 0);
|
||||
}
|
||||
{
|
||||
using Opt = std::optional<T>;
|
||||
static_assert(!std::is_assignable<Opt&, const OptInt&&>::value, "");
|
||||
static_assert(!std::is_assignable<Opt&, const OptInt&>::value, "");
|
||||
static_assert(!std::is_assignable<Opt&, OptInt&>::value, "");
|
||||
}
|
||||
}
|
||||
{
|
||||
using T = AssignableFrom<OptInt const&&>;
|
||||
T::reset();
|
||||
{
|
||||
const OptInt a(42);
|
||||
std::optional<T> t;
|
||||
t = std::move(a);
|
||||
assert(T::type_constructed == 1);
|
||||
assert(T::type_assigned == 0);
|
||||
assert(T::int_constructed == 0);
|
||||
assert(T::int_assigned == 0);
|
||||
}
|
||||
T::reset();
|
||||
{
|
||||
OptInt a(42);
|
||||
std::optional<T> t;
|
||||
t = std::move(a);
|
||||
assert(T::type_constructed == 1);
|
||||
assert(T::type_assigned == 0);
|
||||
assert(T::int_constructed == 0);
|
||||
assert(T::int_assigned == 0);
|
||||
}
|
||||
{
|
||||
using Opt = std::optional<T>;
|
||||
static_assert(std::is_assignable<Opt&, OptInt&&>::value, "");
|
||||
static_assert(!std::is_assignable<Opt&, const OptInt&>::value, "");
|
||||
static_assert(!std::is_assignable<Opt&, OptInt&>::value, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test()
|
||||
{
|
||||
{
|
||||
optional<int> opt;
|
||||
optional<short> opt2;
|
||||
opt = std::move(opt2);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
}
|
||||
{
|
||||
optional<int> opt;
|
||||
optional<short> opt2(short{2});
|
||||
opt = std::move(opt2);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
assert(*opt2 == 2);
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
assert(*opt == *opt2);
|
||||
}
|
||||
{
|
||||
optional<int> opt(3);
|
||||
optional<short> opt2;
|
||||
opt = std::move(opt2);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
}
|
||||
{
|
||||
optional<int> opt(3);
|
||||
optional<short> opt2(short{2});
|
||||
opt = std::move(opt2);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
assert(*opt2 == 2);
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
assert(*opt == *opt2);
|
||||
}
|
||||
|
||||
enum class state_t { inactive, constructed, copy_assigned, move_assigned };
|
||||
class StateTracker {
|
||||
public:
|
||||
constexpr StateTracker(state_t& s)
|
||||
: state_(&s)
|
||||
{
|
||||
*state_ = state_t::constructed;
|
||||
}
|
||||
|
||||
StateTracker(StateTracker&&) = default;
|
||||
StateTracker(StateTracker const&) = default;
|
||||
|
||||
constexpr StateTracker& operator=(StateTracker&& other) noexcept
|
||||
{
|
||||
*state_ = state_t::inactive;
|
||||
state_ = other.state_;
|
||||
*state_ = state_t::move_assigned;
|
||||
other.state_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr StateTracker& operator=(StateTracker const& other) noexcept
|
||||
{
|
||||
*state_ = state_t::inactive;
|
||||
state_ = other.state_;
|
||||
*state_ = state_t::copy_assigned;
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
state_t* state_;
|
||||
};
|
||||
{
|
||||
auto state = std::array{state_t::inactive, state_t::inactive};
|
||||
auto opt1 = std::optional<StateTracker>(state[0]);
|
||||
assert(state[0] == state_t::constructed);
|
||||
|
||||
auto opt2 = std::optional<StateTracker>(state[1]);
|
||||
assert(state[1] == state_t::constructed);
|
||||
|
||||
opt1 = std::move(opt2);
|
||||
assert(state[0] == state_t::inactive);
|
||||
assert(state[1] == state_t::move_assigned);
|
||||
}
|
||||
{
|
||||
auto state = std::array{state_t::inactive, state_t::inactive};
|
||||
auto opt1 = std::optional<StateTracker>(state[0]);
|
||||
assert(state[0] == state_t::constructed);
|
||||
|
||||
auto opt2 = std::optional<StateTracker>(state[1]);
|
||||
assert(state[1] == state_t::constructed);
|
||||
|
||||
opt1 = opt2;
|
||||
assert(state[0] == state_t::inactive);
|
||||
assert(state[1] == state_t::copy_assigned);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test());
|
||||
#endif
|
||||
test_with_test_type();
|
||||
test_ambiguous_assign();
|
||||
test();
|
||||
{
|
||||
optional<std::unique_ptr<B>> opt;
|
||||
optional<std::unique_ptr<D>> other(new D());
|
||||
opt = std::move(other);
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(static_cast<bool>(other) == true);
|
||||
assert(opt->get() != nullptr);
|
||||
assert(other->get() == nullptr);
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
{
|
||||
optional<X> opt;
|
||||
optional<int> opt2(42);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
try
|
||||
{
|
||||
X::throw_now = true;
|
||||
opt = std::move(opt2);
|
||||
assert(false);
|
||||
}
|
||||
catch (int i)
|
||||
{
|
||||
assert(i == 6);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user