Implement N4606 optional

Summary:
Adapt implementation of Library Fundamentals TS optional into an implementation of N4606 optional.

  - Update relational operators per http://wg21.link/P0307
  - Update to requirements of http://wg21.link/P0032
  - Extension: Implement trivial copy/move construction/assignment for `optional<T>` when `T` is trivially copyable.

Audit P/Rs for optional LWG issues:
  - 2756 "C++ WP optional<T> should 'forward' T's implicit conversions" Implemented, which also resolves 2753 "Optional's constructors and assignments need constraints" (modulo my refusal to explicitly delete the move operations, which is a design error that I'm working on correcting in the 2756 P/R).
  - 2736 "nullopt_t insufficiently constrained" Already conforming. I've added a test ensuring that `nullopt_t` is not copy-initializable from an empty braced-init-list, which I believe is the root intent of the issue, to avoid regression.
  - 2740 "constexpr optional<T>::operator->" Already conforming.
  - 2746 "Inconsistency between requirements for emplace between optional and variant" No P/R, but note that the author's '"suggested resolution" is already implemented.
  - 2748 "swappable traits for optionals" Already conforming.
  - 2753 "Optional's constructors and assignments need constraints" Implemented.

Most of the work for this patch was done by Casey Carter @ Microsoft. Thank you Casey!



Reviewers: mclow.lists, CaseyCarter, EricWF

Differential Revision: https://reviews.llvm.org/D22741

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@283980 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Fiselier
2016-10-12 07:46:20 +00:00
parent ead5d404cc
commit 35ce4859dd
86 changed files with 8473 additions and 56 deletions

View File

@@ -0,0 +1,261 @@
//===----------------------------------------------------------------------===//
//
// 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>
// template <class U> optional<T>& operator=(U&& v);
#include <optional>
#include <type_traits>
#include <cassert>
#include <memory>
#include "test_macros.h"
#include "archetypes.hpp"
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;
};
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>();
}
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;
{
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(*)();
int main()
{
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();
}

View File

@@ -0,0 +1,254 @@
//===----------------------------------------------------------------------===//
//
// 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>
// 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.hpp"
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_ambigious_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()
{
test_with_test_type();
test_ambigious_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
}

View File

@@ -0,0 +1,102 @@
//===----------------------------------------------------------------------===//
//
// 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>
// optional<T>& operator=(const optional<T>& rhs);
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
#include "archetypes.hpp"
using std::optional;
struct X
{
static bool throw_now;
X() = default;
X(const X&)
{
if (throw_now)
TEST_THROW(6);
}
};
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()
{
{
using O = optional<int>;
LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
assert(assign_empty(O{42}));
assert(assign_value(O{42}));
}
{
using O = optional<TrivialTestTypes::TestType>;
LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
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
}

View File

@@ -0,0 +1,237 @@
//===----------------------------------------------------------------------===//
//
// 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>
// template <class... Args> void optional<T>::emplace(Args&&... args);
#include <optional>
#include <type_traits>
#include <cassert>
#include <memory>
#include "test_macros.h"
#include "archetypes.hpp"
using std::optional;
class X
{
int i_;
int j_ = 0;
public:
X() : i_(0) {}
X(int i) : i_(i) {}
X(int i, int j) : i_(i), j_(j) {}
friend 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>
void test_one_arg() {
using Opt = std::optional<T>;
{
Opt opt;
opt.emplace();
assert(static_cast<bool>(opt) == true);
assert(*opt == T(0));
}
{
Opt opt;
opt.emplace(1);
assert(static_cast<bool>(opt) == true);
assert(*opt == T(1));
}
{
Opt opt(2);
opt.emplace();
assert(static_cast<bool>(opt) == true);
assert(*opt == T(0));
}
{
Opt opt(2);
opt.emplace(1);
assert(static_cast<bool>(opt) == true);
assert(*opt == T(1));
}
}
template <class T>
void test_multi_arg()
{
test_one_arg<T>();
using Opt = std::optional<T>;
Opt opt;
{
opt.emplace(101, 41);
assert(static_cast<bool>(opt) == true);
assert(*opt == T(101, 41));
}
{
Opt opt;
opt.emplace({1, 2, 3, 4});
assert(static_cast<bool>(opt) == true);
assert(*opt == T(4)); // T sets its value to the size of the init list
}
{
Opt opt;
opt.emplace({1, 2, 3, 4, 5}, 6);
assert(static_cast<bool>(opt) == true);
assert(*opt == T(5)); // T sets its value to the size of the init list
}
}
template <class T>
void test_on_test_type() {
T::reset();
optional<T> opt;
assert(T::alive == 0);
{
T::reset_constructors();
opt.emplace();
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());
}
{
T::reset_constructors();
opt.emplace();
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());
}
{
T::reset_constructors();
opt.emplace(101);
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));
}
{
T::reset_constructors();
opt.emplace(-10, 99);
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));
}
{
T::reset_constructors();
opt.emplace(-10, 99);
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));
}
{
T::reset_constructors();
opt.emplace({-10, 99, 42, 1});
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
}
{
T::reset_constructors();
opt.emplace({-10, 99, 42, 1}, 42);
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
}
}
int main()
{
{
test_on_test_type<TestTypes::TestType>();
test_on_test_type<ExplicitTestTypes::TestType>();
}
{
using T = int;
test_one_arg<T>();
test_one_arg<const T>();
}
{
using T = ConstexprTestTypes::TestType;
test_multi_arg<T>();
}
{
using T = ExplicitConstexprTestTypes::TestType;
test_multi_arg<T>();
}
{
using T = TrivialTestTypes::TestType;
test_multi_arg<T>();
}
{
using T = ExplicitTrivialTestTypes::TestType;
test_multi_arg<T>();
}
{
optional<const int> opt;
opt.emplace(42);
assert(*opt == 42);
opt.emplace();
assert(*opt == 0);
}
#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);
opt.emplace(1);
}
catch (int i)
{
assert(i == 6);
assert(static_cast<bool>(opt) == false);
assert(Y::dtor_called == true);
}
}
#endif
}

View File

@@ -0,0 +1,113 @@
//===----------------------------------------------------------------------===//
//
// 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>
// template <class U, class... Args>
// void 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;
public:
static bool dtor_called;
constexpr X() : i_(0) {}
constexpr X(int i) : i_(i) {}
constexpr X(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {}
~X() {dtor_called = true;}
friend constexpr bool operator==(const X& x, const X& y)
{return x.i_ == y.i_ && x.j_ == y.j_;}
};
bool X::dtor_called = false;
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;
int main()
{
{
X x;
optional<X> opt(x);
assert(X::dtor_called == false);
opt.emplace({1, 2});
assert(X::dtor_called == true);
assert(*opt == X({1, 2}));
}
{
optional<std::vector<int>> opt;
opt.emplace({1, 2, 3}, std::allocator<int>());
assert(static_cast<bool>(opt) == true);
assert(*opt == std::vector<int>({1, 2, 3}));
}
{
optional<Y> opt;
opt.emplace({1, 2});
assert(static_cast<bool>(opt) == true);
assert(*opt == Y({1, 2}));
}
#ifndef TEST_HAS_NO_EXCEPTIONS
{
Z z;
optional<Z> opt(z);
try
{
assert(static_cast<bool>(opt) == true);
assert(Z::dtor_called == false);
opt.emplace({1, 2});
}
catch (int i)
{
assert(i == 6);
assert(static_cast<bool>(opt) == false);
assert(Z::dtor_called == true);
}
}
#endif
}

View File

@@ -0,0 +1,174 @@
//===----------------------------------------------------------------------===//
//
// 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>
// optional<T>& operator=(optional<T>&& rhs)
// noexcept(is_nothrow_move_assignable<T>::value &&
// is_nothrow_move_constructible<T>::value);
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
#include "archetypes.hpp"
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;
int main()
{
{
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);
}
#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, "");
}
}

View File

@@ -0,0 +1,67 @@
//===----------------------------------------------------------------------===//
//
// 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>
// optional<T>& operator=(nullopt_t) noexcept;
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
#include "archetypes.hpp"
using std::optional;
using std::nullopt_t;
using std::nullopt;
int main()
{
{
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);
}
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();
}

View File

@@ -0,0 +1,268 @@
//===----------------------------------------------------------------------===//
//
// 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>
// From LWG2451:
// template <class U>
// optional<T>& operator=(optional<U>&& rhs);
#include <optional>
#include <type_traits>
#include <memory>
#include <cassert>
#include "test_macros.h"
#include "archetypes.hpp"
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; }
};
class B {};
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_ambigious_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, "");
}
}
}
int main()
{
test_with_test_type();
test_ambigious_assign();
{
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);
}
{
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
}

View File

@@ -0,0 +1,137 @@
//===----------------------------------------------------------------------===//
//
// 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>
// template <class U>
// constexpr EXPLICIT optional(U&& u);
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
#include "archetypes.hpp"
#include "test_convertible.hpp"
using std::optional;
struct ImplicitThrow
{
constexpr ImplicitThrow(int x) { if (x != -1) TEST_THROW(6);}
};
struct ExplicitThrow
{
constexpr explicit ExplicitThrow(int x) { if (x != -1) TEST_THROW(6);}
};
template <class To, class From>
constexpr bool implicit_conversion(optional<To>&& opt, const From& v)
{
using O = optional<To>;
static_assert(test_convertible<O, From>(), "");
static_assert(!test_convertible<O, void*>(), "");
static_assert(!test_convertible<O, From, int>(), "");
return opt && *opt == static_cast<To>(v);
}
template <class To, class Input, class Expect>
constexpr bool explicit_conversion(Input&& in, const Expect& v)
{
using O = optional<To>;
static_assert(std::is_constructible<O, Input>::value, "");
static_assert(!std::is_convertible<Input, O>::value, "");
static_assert(!std::is_constructible<O, void*>::value, "");
static_assert(!std::is_constructible<O, Input, int>::value, "");
optional<To> opt(std::forward<Input>(in));
return opt && *opt == static_cast<To>(v);
}
void test_implicit()
{
{
using T = long long;
static_assert(implicit_conversion<long long>(42, 42), "");
}
{
using T = long double;
static_assert(implicit_conversion<long double>(3.14, 3.14), "");
}
{
using T = TrivialTestTypes::TestType;
static_assert(implicit_conversion<T>(42, 42), "");
}
{
using T = TestTypes::TestType;
assert(implicit_conversion<T>(3, T(3)));
}
#ifndef TEST_HAS_NO_EXCEPTIONS
{
try {
using T = ImplicitThrow;
optional<T> t = 42;
assert(false);
} catch (int) {
}
}
#endif
}
void test_explicit() {
{
using T = ExplicitTrivialTestTypes::TestType;
using O = optional<T>;
static_assert(explicit_conversion<T>(42, 42), "");
}
{
using T = ExplicitConstexprTestTypes::TestType;
using O = optional<T>;
static_assert(explicit_conversion<T>(42, 42), "");
static_assert(!std::is_convertible<int, T>::value, "");
}
{
using T = ExplicitTestTypes::TestType;
using O = optional<T>;
T::reset();
{
assert(explicit_conversion<T>(42, 42));
assert(T::alive == 0);
}
T::reset();
{
optional<T> t(42);
assert(T::alive == 1);
assert(T::value_constructed == 1);
assert(T::move_constructed == 0);
assert(T::copy_constructed == 0);
assert(t.value().value == 42);
}
assert(T::alive == 0);
}
#ifndef TEST_HAS_NO_EXCEPTIONS
{
try {
using T = ExplicitThrow;
optional<T> t(42);
assert(false);
} catch (int) {
}
}
#endif
}
int main() {
test_implicit();
test_explicit();
}

View File

@@ -0,0 +1,123 @@
//===----------------------------------------------------------------------===//
//
// 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 T& v);
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
#include "archetypes.hpp"
using std::optional;
int main()
{
{
typedef int T;
constexpr T t(5);
constexpr optional<T> opt(t);
static_assert(static_cast<bool>(opt) == true, "");
static_assert(*opt == 5, "");
struct test_constexpr_ctor
: public optional<T>
{
constexpr test_constexpr_ctor(const T&) {}
};
}
{
typedef double T;
constexpr T t(3);
constexpr optional<T> opt(t);
static_assert(static_cast<bool>(opt) == true, "");
static_assert(*opt == 3, "");
struct test_constexpr_ctor
: public optional<T>
{
constexpr test_constexpr_ctor(const T&) {}
};
}
{
typedef TestTypes::TestType T;
T::reset();
const T t(3);
optional<T> opt = t;
assert(T::alive == 2);
assert(T::copy_constructed == 1);
assert(static_cast<bool>(opt) == true);
assert(opt.value().value == 3);
}
{
typedef ExplicitTestTypes::TestType T;
static_assert(!std::is_convertible<T const&, optional<T>>::value, "");
T::reset();
const T t(3);
optional<T> opt(t);
assert(T::alive == 2);
assert(T::copy_constructed == 1);
assert(static_cast<bool>(opt) == true);
assert(opt.value().value == 3);
}
{
typedef ConstexprTestTypes::TestType T;
constexpr T t(3);
constexpr optional<T> opt = {t};
static_assert(static_cast<bool>(opt) == true, "");
static_assert(opt.value().value == 3, "");
struct test_constexpr_ctor
: public optional<T>
{
constexpr test_constexpr_ctor(const T&) {}
};
}
{
typedef ExplicitConstexprTestTypes::TestType T;
static_assert(!std::is_convertible<const T&, optional<T>>::value, "");
constexpr T t(3);
constexpr optional<T> opt(t);
static_assert(static_cast<bool>(opt) == true, "");
static_assert(opt.value().value == 3, "");
struct test_constexpr_ctor
: public optional<T>
{
constexpr test_constexpr_ctor(const T&) {}
};
}
#ifndef TEST_HAS_NO_EXCEPTIONS
{
struct Z {
Z(int) {}
Z(const Z&) {throw 6;}
};
typedef Z T;
try
{
const T t(3);
optional<T> opt(t);
assert(false);
}
catch (int i)
{
assert(i == 6);
}
}
#endif
}

View File

@@ -0,0 +1,134 @@
//===----------------------------------------------------------------------===//
//
// 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>
// template <class U>
// optional(const optional<U>& rhs);
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
template <class T, class U>
void
test(const optional<U>& rhs, bool is_going_to_throw = false)
{
bool rhs_engaged = static_cast<bool>(rhs);
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
optional<T> lhs = rhs;
assert(is_going_to_throw == false);
assert(static_cast<bool>(lhs) == rhs_engaged);
if (rhs_engaged)
assert(*lhs == *rhs);
}
catch (int i)
{
assert(i == 6);
}
#else
if (is_going_to_throw) return;
optional<T> lhs = rhs;
assert(static_cast<bool>(lhs) == rhs_engaged);
if (rhs_engaged)
assert(*lhs == *rhs);
#endif
}
class X
{
int i_;
public:
X(int i) : i_(i) {}
X(const X& x) : i_(x.i_) {}
~X() {i_ = 0;}
friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
};
class Y
{
int i_;
public:
Y(int i) : i_(i) {}
friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
};
int count = 0;
class Z
{
int i_;
public:
Z(int i) : i_(i) {TEST_THROW(6);}
friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
};
int main()
{
{
typedef short U;
typedef int T;
optional<U> rhs;
test<T>(rhs);
}
{
typedef short U;
typedef int T;
optional<U> rhs(U{3});
test<T>(rhs);
}
{
typedef X T;
typedef int U;
optional<U> rhs;
test<T>(rhs);
}
{
typedef X T;
typedef int U;
optional<U> rhs(U{3});
test<T>(rhs);
}
{
typedef Y T;
typedef int U;
optional<U> rhs;
test<T>(rhs);
}
{
typedef Y T;
typedef int U;
optional<U> rhs(U{3});
test<T>(rhs);
}
{
typedef Z T;
typedef int U;
optional<U> rhs;
test<T>(rhs);
}
{
typedef Z T;
typedef int U;
optional<U> rhs(U{3});
test<T>(rhs, true);
}
static_assert(!(std::is_constructible<optional<X>, const optional<Y>&>::value), "");
}

View File

@@ -0,0 +1,150 @@
//===----------------------------------------------------------------------===//
//
// 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>
// optional(const optional<T>& rhs);
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
#include "archetypes.hpp"
using std::optional;
template <class T, class ...InitArgs>
void test(InitArgs&&... args)
{
const optional<T> rhs(std::forward<InitArgs>(args)...);
bool rhs_engaged = static_cast<bool>(rhs);
optional<T> lhs = rhs;
assert(static_cast<bool>(lhs) == rhs_engaged);
if (rhs_engaged)
assert(*lhs == *rhs);
}
void test_throwing_ctor() {
#ifndef TEST_HAS_NO_EXCEPTIONS
struct Z {
Z() : count(0) {}
Z(Z const& o) : count(o.count + 1)
{ if (count == 2) throw 6; }
int count;
};
const Z z;
const optional<Z> rhs(z);
try
{
optional<Z> lhs(rhs);
assert(false);
}
catch (int i)
{
assert(i == 6);
}
#endif
}
template <class T, class ...InitArgs>
void test_ref(InitArgs&&... args)
{
const optional<T> rhs(std::forward<InitArgs>(args)...);
bool rhs_engaged = static_cast<bool>(rhs);
optional<T> lhs = rhs;
assert(static_cast<bool>(lhs) == rhs_engaged);
if (rhs_engaged)
assert(&(*lhs) == &(*rhs));
}
void test_reference_extension()
{
#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled.
using T = TestTypes::TestType;
T::reset();
{
T t;
T::reset_constructors();
test_ref<T&>();
test_ref<T&>(t);
assert(T::alive == 1);
assert(T::constructed == 0);
assert(T::assigned == 0);
assert(T::destroyed == 0);
}
assert(T::destroyed == 1);
assert(T::alive == 0);
{
T t;
const T& ct = t;
T::reset_constructors();
test_ref<T const&>();
test_ref<T const&>(t);
test_ref<T const&>(ct);
assert(T::alive == 1);
assert(T::constructed == 0);
assert(T::assigned == 0);
assert(T::destroyed == 0);
}
assert(T::alive == 0);
assert(T::destroyed == 1);
{
static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, "");
static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, "");
}
#endif
}
int main()
{
test<int>();
test<int>(3);
{
using T = TestTypes::TestType;
T::reset();
const optional<T> rhs;
assert(T::alive == 0);
const optional<T> lhs(rhs);
assert(lhs.has_value() == false);
assert(T::alive == 0);
}
TestTypes::TestType::reset();
{
using T = TestTypes::TestType;
T::reset();
const optional<T> rhs(42);
assert(T::alive == 1);
assert(T::value_constructed == 1);
assert(T::copy_constructed == 0);
const optional<T> lhs(rhs);
assert(lhs.has_value());
assert(T::copy_constructed == 1);
assert(T::alive == 2);
}
TestTypes::TestType::reset();
{
using namespace ConstexprTestTypes;
test<TestType>();
test<TestType>(42);
}
{
using namespace TrivialTestTypes;
test<TestType>();
test<TestType>(42);
}
{
test_throwing_ctor();
}
{
test_reference_extension();
}
}

View File

@@ -0,0 +1,81 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <optional>
// constexpr optional() noexcept;
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
#include "archetypes.hpp"
using std::optional;
template <class Opt>
void
test_constexpr()
{
static_assert(std::is_nothrow_default_constructible<Opt>::value, "");
static_assert(std::is_trivially_destructible<Opt>::value, "");
static_assert(std::is_trivially_destructible<typename Opt::value_type>::value, "");
constexpr Opt opt;
static_assert(static_cast<bool>(opt) == false, "");
struct test_constexpr_ctor
: public Opt
{
constexpr test_constexpr_ctor() {}
};
}
template <class Opt>
void
test()
{
static_assert(std::is_nothrow_default_constructible<Opt>::value, "");
static_assert(!std::is_trivially_destructible<Opt>::value, "");
static_assert(!std::is_trivially_destructible<typename Opt::value_type>::value, "");
{
Opt opt;
assert(static_cast<bool>(opt) == false);
}
{
const Opt opt;
assert(static_cast<bool>(opt) == false);
}
struct test_constexpr_ctor
: public Opt
{
constexpr test_constexpr_ctor() {}
};
}
int main()
{
test_constexpr<optional<int>>();
test_constexpr<optional<int*>>();
test_constexpr<optional<ImplicitTypes::NoCtors>>();
test_constexpr<optional<NonTrivialTypes::NoCtors>>();
test_constexpr<optional<NonConstexprTypes::NoCtors>>();
test<optional<NonLiteralTypes::NoCtors>>();
// EXTENSIONS
#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled.
test_constexpr<optional<int&>>();
test_constexpr<optional<const int&>>();
test_constexpr<optional<int&>>();
test_constexpr<optional<NonLiteralTypes::NoCtors&>>();
test_constexpr<optional<NonLiteralTypes::NoCtors&&>>();
#endif
}

View File

@@ -0,0 +1,121 @@
//===----------------------------------------------------------------------===//
//
// 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>
// template <class U>
// explicit optional(const optional<U>& rhs);
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
template <class T, class U>
void
test(const optional<U>& rhs, bool is_going_to_throw = false)
{
static_assert(!(std::is_convertible<const optional<U>&, optional<T>>::value), "");
bool rhs_engaged = static_cast<bool>(rhs);
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
optional<T> lhs(rhs);
assert(is_going_to_throw == false);
assert(static_cast<bool>(lhs) == rhs_engaged);
if (rhs_engaged)
assert(*lhs == T(*rhs));
}
catch (int i)
{
assert(i == 6);
}
#else
if (is_going_to_throw) return;
optional<T> lhs(rhs);
assert(static_cast<bool>(lhs) == rhs_engaged);
if (rhs_engaged)
assert(*lhs == T(*rhs));
#endif
}
class X
{
int i_;
public:
explicit X(int i) : i_(i) {}
X(const X& x) : i_(x.i_) {}
~X() {i_ = 0;}
friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
};
class Y
{
int i_;
public:
explicit Y(int i) : i_(i) {}
friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
};
int count = 0;
class Z
{
int i_;
public:
explicit Z(int i) : i_(i) { TEST_THROW(6);}
friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
};
int main()
{
{
typedef X T;
typedef int U;
optional<U> rhs;
test<T>(rhs);
}
{
typedef X T;
typedef int U;
optional<U> rhs(3);
test<T>(rhs);
}
{
typedef Y T;
typedef int U;
optional<U> rhs;
test<T>(rhs);
}
{
typedef Y T;
typedef int U;
optional<U> rhs(3);
test<T>(rhs);
}
{
typedef Z T;
typedef int U;
optional<U> rhs;
test<T>(rhs);
}
{
typedef Z T;
typedef int U;
optional<U> rhs(3);
test<T>(rhs, true);
}
}

View File

@@ -0,0 +1,84 @@
//===----------------------------------------------------------------------===//
//
// 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>
// template <class U>
// explicit optional(optional<U>&& rhs);
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
template <class T, class U>
void
test(optional<U>&& rhs, bool is_going_to_throw = false)
{
static_assert(!(std::is_convertible<optional<U>&&, optional<T>>::value), "");
bool rhs_engaged = static_cast<bool>(rhs);
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
optional<T> lhs(std::move(rhs));
assert(is_going_to_throw == false);
assert(static_cast<bool>(lhs) == rhs_engaged);
}
catch (int i)
{
assert(i == 6);
}
#else
if (is_going_to_throw) return;
optional<T> lhs(std::move(rhs));
assert(static_cast<bool>(lhs) == rhs_engaged);
#endif
}
class X
{
int i_;
public:
explicit X(int i) : i_(i) {}
X(X&& x) : i_(std::exchange(x.i_, 0)) {}
~X() {i_ = 0;}
friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
};
int count = 0;
class Z
{
public:
explicit Z(int) { TEST_THROW(6); }
};
int main()
{
{
optional<int> rhs;
test<X>(std::move(rhs));
}
{
optional<int> rhs(3);
test<X>(std::move(rhs));
}
{
optional<int> rhs;
test<Z>(std::move(rhs));
}
{
optional<int> rhs(3);
test<Z>(std::move(rhs), true);
}
}

View File

@@ -0,0 +1,144 @@
//===----------------------------------------------------------------------===//
//
// 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>
// template <class... Args>
// constexpr explicit optional(in_place_t, Args&&... args);
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
using std::in_place_t;
using std::in_place;
class X
{
int i_;
int j_ = 0;
public:
X() : i_(0) {}
X(int i) : i_(i) {}
X(int i, int j) : i_(i), j_(j) {}
~X() {}
friend 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(int i, int j) : i_(i), j_(j) {}
friend constexpr bool operator==(const Y& x, const Y& y)
{return x.i_ == y.i_ && x.j_ == y.j_;}
};
class Z
{
public:
Z(int i) {TEST_THROW(6);}
};
int main()
{
{
constexpr optional<int> opt(in_place, 5);
static_assert(static_cast<bool>(opt) == true, "");
static_assert(*opt == 5, "");
struct test_constexpr_ctor
: public optional<int>
{
constexpr test_constexpr_ctor(in_place_t, int i)
: optional<int>(in_place, i) {}
};
}
{
const optional<X> opt(in_place);
assert(static_cast<bool>(opt) == true);
assert(*opt == X());
}
{
const optional<X> opt(in_place, 5);
assert(static_cast<bool>(opt) == true);
assert(*opt == X(5));
}
{
const optional<X> opt(in_place, 5, 4);
assert(static_cast<bool>(opt) == true);
assert(*opt == X(5, 4));
}
{
constexpr optional<Y> opt(in_place);
static_assert(static_cast<bool>(opt) == true, "");
static_assert(*opt == Y(), "");
struct test_constexpr_ctor
: public optional<Y>
{
constexpr test_constexpr_ctor(in_place_t)
: optional<Y>(in_place) {}
};
}
{
constexpr optional<Y> opt(in_place, 5);
static_assert(static_cast<bool>(opt) == true, "");
static_assert(*opt == Y(5), "");
struct test_constexpr_ctor
: public optional<Y>
{
constexpr test_constexpr_ctor(in_place_t, int i)
: optional<Y>(in_place, i) {}
};
}
{
constexpr optional<Y> opt(in_place, 5, 4);
static_assert(static_cast<bool>(opt) == true, "");
static_assert(*opt == Y(5, 4), "");
struct test_constexpr_ctor
: public optional<Y>
{
constexpr test_constexpr_ctor(in_place_t, int i, int j)
: optional<Y>(in_place, i, j) {}
};
}
#ifndef TEST_HAS_NO_EXCEPTIONS
{
try
{
const optional<Z> opt(in_place, 1);
assert(false);
}
catch (int i)
{
assert(i == 6);
}
}
#endif
}

View File

@@ -0,0 +1,116 @@
//===----------------------------------------------------------------------===//
//
// 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>
// template <class U, class... Args>
// constexpr
// explicit optional(in_place_t, initializer_list<U> il, Args&&... args);
#include <optional>
#include <type_traits>
#include <vector>
#include <cassert>
#include "test_macros.h"
using std::optional;
using std::in_place_t;
using std::in_place;
class X
{
int i_;
int j_ = 0;
public:
X() : i_(0) {}
X(int i) : i_(i) {}
X(int i, int j) : i_(i), j_(j) {}
~X() {}
friend 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:
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);}
friend bool operator==(const Z& x, const Z& y)
{return x.i_ == y.i_ && x.j_ == y.j_;}
};
int main()
{
{
static_assert(!std::is_constructible<X, std::initializer_list<int>&>::value, "");
static_assert(!std::is_constructible<optional<X>, std::initializer_list<int>&>::value, "");
}
{
optional<std::vector<int>> opt(in_place, {3, 1});
assert(static_cast<bool>(opt) == true);
assert((*opt == std::vector<int>{3, 1}));
assert(opt->size() == 2);
}
{
optional<std::vector<int>> opt(in_place, {3, 1}, std::allocator<int>());
assert(static_cast<bool>(opt) == true);
assert((*opt == std::vector<int>{3, 1}));
assert(opt->size() == 2);
}
{
static_assert(std::is_constructible<optional<Y>, std::initializer_list<int>&>::value, "");
constexpr optional<Y> opt(in_place, {3, 1});
static_assert(static_cast<bool>(opt) == true, "");
static_assert(*opt == Y{3, 1}, "");
struct test_constexpr_ctor
: public optional<Y>
{
constexpr test_constexpr_ctor(in_place_t, std::initializer_list<int> i)
: optional<Y>(in_place, i) {}
};
}
#ifndef TEST_HAS_NO_EXCEPTIONS
{
static_assert(std::is_constructible<optional<Z>, std::initializer_list<int>&>::value, "");
try
{
optional<Z> opt(in_place, {3, 1});
assert(false);
}
catch (int i)
{
assert(i == 6);
}
}
#endif
}

View File

@@ -0,0 +1,196 @@
//===----------------------------------------------------------------------===//
//
// 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>
// optional(optional<T>&& rhs);
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
#include "archetypes.hpp"
using std::optional;
template <class T, class ...InitArgs>
void test(InitArgs&&... args)
{
const optional<T> orig(std::forward<InitArgs>(args)...);
optional<T> rhs(orig);
bool rhs_engaged = static_cast<bool>(rhs);
optional<T> lhs = std::move(rhs);
assert(static_cast<bool>(lhs) == rhs_engaged);
if (rhs_engaged)
assert(*lhs == *orig);
}
void test_throwing_ctor() {
#ifndef TEST_HAS_NO_EXCEPTIONS
struct Z {
Z() : count(0) {}
Z(Z&& o) : count(o.count + 1)
{ if (count == 2) throw 6; }
int count;
};
Z z;
optional<Z> rhs(std::move(z));
try
{
optional<Z> lhs(std::move(rhs));
assert(false);
}
catch (int i)
{
assert(i == 6);
}
#endif
}
template <class T, class ...InitArgs>
void test_ref(InitArgs&&... args)
{
optional<T> rhs(std::forward<InitArgs>(args)...);
bool rhs_engaged = static_cast<bool>(rhs);
optional<T> lhs = std::move(rhs);
assert(static_cast<bool>(lhs) == rhs_engaged);
if (rhs_engaged)
assert(&(*lhs) == &(*rhs));
}
void test_reference_extension()
{
#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled.
using T = TestTypes::TestType;
T::reset();
{
T t;
T::reset_constructors();
test_ref<T&>();
test_ref<T&>(t);
assert(T::alive == 1);
assert(T::constructed == 0);
assert(T::assigned == 0);
assert(T::destroyed == 0);
}
assert(T::destroyed == 1);
assert(T::alive == 0);
{
T t;
const T& ct = t;
T::reset_constructors();
test_ref<T const&>();
test_ref<T const&>(t);
test_ref<T const&>(ct);
assert(T::alive == 1);
assert(T::constructed == 0);
assert(T::assigned == 0);
assert(T::destroyed == 0);
}
assert(T::alive == 0);
assert(T::destroyed == 1);
{
T t;
T::reset_constructors();
test_ref<T&&>();
test_ref<T&&>(std::move(t));
assert(T::alive == 1);
assert(T::constructed == 0);
assert(T::assigned == 0);
assert(T::destroyed == 0);
}
assert(T::alive == 0);
assert(T::destroyed == 1);
{
T t;
const T& ct = t;
T::reset_constructors();
test_ref<T const&&>();
test_ref<T const&&>(std::move(t));
test_ref<T const&&>(std::move(ct));
assert(T::alive == 1);
assert(T::constructed == 0);
assert(T::assigned == 0);
assert(T::destroyed == 0);
}
assert(T::alive == 0);
assert(T::destroyed == 1);
{
static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, "");
static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, "");
}
#endif
}
int main()
{
test<int>();
test<int>(3);
{
using T = TestTypes::TestType;
T::reset();
optional<T> rhs;
assert(T::alive == 0);
const optional<T> lhs(std::move(rhs));
assert(lhs.has_value() == false);
assert(rhs.has_value() == false);
assert(T::alive == 0);
}
TestTypes::TestType::reset();
{
using T = TestTypes::TestType;
T::reset();
optional<T> rhs(42);
assert(T::alive == 1);
assert(T::value_constructed == 1);
assert(T::move_constructed == 0);
const optional<T> lhs(std::move(rhs));
assert(lhs.has_value());
assert(rhs.has_value());
assert(lhs.value().value == 42);
assert(rhs.value().value == -1);
assert(T::move_constructed == 1);
assert(T::alive == 2);
}
TestTypes::TestType::reset();
{
using namespace ConstexprTestTypes;
test<TestType>();
test<TestType>(42);
}
{
using namespace TrivialTestTypes;
test<TestType>();
test<TestType>(42);
}
{
test_throwing_ctor();
}
{
struct ThrowsMove {
ThrowsMove() noexcept(false) {}
ThrowsMove(ThrowsMove const&) noexcept(false) {}
ThrowsMove(ThrowsMove &&) noexcept(false) {}
};
static_assert(!std::is_nothrow_move_constructible<optional<ThrowsMove>>::value, "");
struct NoThrowMove {
NoThrowMove() noexcept(false) {}
NoThrowMove(NoThrowMove const&) noexcept(false) {}
NoThrowMove(NoThrowMove &&) noexcept(true) {}
};
static_assert(std::is_nothrow_move_constructible<optional<NoThrowMove>>::value, "");
}
{
test_reference_extension();
}
}

View File

@@ -0,0 +1,73 @@
//===----------------------------------------------------------------------===//
//
// 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(nullopt_t) noexcept;
#include <optional>
#include <type_traits>
#include <cassert>
#include "archetypes.hpp"
using std::optional;
using std::nullopt_t;
using std::nullopt;
template <class Opt>
void
test_constexpr()
{
static_assert(std::is_nothrow_constructible<Opt, nullopt_t&>::value, "");
static_assert(std::is_trivially_destructible<Opt>::value, "");
static_assert(std::is_trivially_destructible<typename Opt::value_type>::value, "");
constexpr Opt opt(nullopt);
static_assert(static_cast<bool>(opt) == false, "");
struct test_constexpr_ctor
: public Opt
{
constexpr test_constexpr_ctor() {}
};
}
template <class Opt>
void
test()
{
static_assert(std::is_nothrow_constructible<Opt, nullopt_t&>::value, "");
static_assert(!std::is_trivially_destructible<Opt>::value, "");
static_assert(!std::is_trivially_destructible<typename Opt::value_type>::value, "");
{
Opt opt(nullopt);
assert(static_cast<bool>(opt) == false);
}
{
const Opt opt(nullopt);
assert(static_cast<bool>(opt) == false);
}
struct test_constexpr_ctor
: public Opt
{
constexpr test_constexpr_ctor() {}
};
}
int main()
{
test_constexpr<optional<int>>();
test_constexpr<optional<int*>>();
test_constexpr<optional<ImplicitTypes::NoCtors>>();
test_constexpr<optional<NonTrivialTypes::NoCtors>>();
test_constexpr<optional<NonConstexprTypes::NoCtors>>();
test<optional<NonLiteralTypes::NoCtors>>();
}

View File

@@ -0,0 +1,93 @@
//===----------------------------------------------------------------------===//
//
// 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>
// template <class U>
// optional(optional<U>&& rhs);
#include <optional>
#include <type_traits>
#include <memory>
#include <cassert>
#include "test_macros.h"
using std::optional;
template <class T, class U>
void
test(optional<U>&& rhs, bool is_going_to_throw = false)
{
bool rhs_engaged = static_cast<bool>(rhs);
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
optional<T> lhs = std::move(rhs);
assert(is_going_to_throw == false);
assert(static_cast<bool>(lhs) == rhs_engaged);
}
catch (int i)
{
assert(i == 6);
}
#else
if (is_going_to_throw) return;
optional<T> lhs = std::move(rhs);
assert(static_cast<bool>(lhs) == rhs_engaged);
#endif
}
class X
{
int i_;
public:
X(int i) : i_(i) {}
X(X&& x) : i_(std::exchange(x.i_, 0)) {}
~X() {i_ = 0;}
friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
};
int count = 0;
struct Z
{
Z(int) { TEST_THROW(6); }
};
int main()
{
{
optional<short> rhs;
test<int>(std::move(rhs));
}
{
optional<short> rhs(short{3});
test<int>(std::move(rhs));
}
{
optional<int> rhs;
test<X>(std::move(rhs));
}
{
optional<int> rhs(3);
test<X>(std::move(rhs));
}
{
optional<int> rhs;
test<Z>(std::move(rhs));
}
{
optional<int> rhs(3);
test<Z>(std::move(rhs), true);
}
static_assert(!(std::is_constructible<optional<X>, optional<Z>>::value), "");
}

View File

@@ -0,0 +1,148 @@
//===----------------------------------------------------------------------===//
//
// 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(T&& v);
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
#include "archetypes.hpp"
using std::optional;
class Z
{
public:
Z(int) {}
Z(Z&&) {TEST_THROW(6);}
};
int main()
{
{
typedef int T;
constexpr optional<T> opt(T(5));
static_assert(static_cast<bool>(opt) == true, "");
static_assert(*opt == 5, "");
struct test_constexpr_ctor
: public optional<T>
{
constexpr test_constexpr_ctor(T&&) {}
};
}
{
typedef double T;
constexpr optional<T> opt(T(3));
static_assert(static_cast<bool>(opt) == true, "");
static_assert(*opt == 3, "");
struct test_constexpr_ctor
: public optional<T>
{
constexpr test_constexpr_ctor(T&&) {}
};
}
{
typedef TestTypes::TestType T;
T::reset();
optional<T> opt = T{3};
assert(T::alive == 1);
assert(T::move_constructed == 1);
assert(static_cast<bool>(opt) == true);
assert(opt.value().value == 3);
}
{
typedef ExplicitTestTypes::TestType T;
static_assert(!std::is_convertible<T&&, optional<T>>::value, "");
T::reset();
optional<T> opt(T{3});
assert(T::alive == 1);
assert(T::move_constructed == 1);
assert(static_cast<bool>(opt) == true);
assert(opt.value().value == 3);
}
{
typedef TestTypes::TestType T;
T::reset();
optional<T> opt = {3};
assert(T::alive == 1);
assert(T::value_constructed == 1);
assert(T::copy_constructed == 0);
assert(T::move_constructed == 0);
assert(static_cast<bool>(opt) == true);
assert(opt.value().value == 3);
}
{
typedef ConstexprTestTypes::TestType T;
constexpr optional<T> opt = {T(3)};
static_assert(static_cast<bool>(opt) == true, "");
static_assert(opt.value().value == 3, "");
struct test_constexpr_ctor
: public optional<T>
{
constexpr test_constexpr_ctor(const T&) {}
};
}
{
typedef ConstexprTestTypes::TestType T;
constexpr optional<T> opt = {3};
static_assert(static_cast<bool>(opt) == true, "");
static_assert(opt.value().value == 3, "");
struct test_constexpr_ctor
: public optional<T>
{
constexpr test_constexpr_ctor(const T&) {}
};
}
{
typedef ExplicitConstexprTestTypes::TestType T;
static_assert(!std::is_convertible<T&&, optional<T>>::value, "");
constexpr optional<T> opt(T{3});
static_assert(static_cast<bool>(opt) == true, "");
static_assert(opt.value().value == 3, "");
struct test_constexpr_ctor
: public optional<T>
{
constexpr test_constexpr_ctor(T&&) {}
};
}
#ifndef TEST_HAS_NO_EXCEPTIONS
{
struct Z {
Z(int) {}
Z(Z&&) {throw 6;}
};
typedef Z T;
try
{
T t(3);
optional<T> opt(std::move(t));
assert(false);
}
catch (int i)
{
assert(i == 6);
}
}
#endif
}

View File

@@ -0,0 +1,68 @@
//===----------------------------------------------------------------------===//
//
// 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>
// ~optional();
#include <optional>
#include <type_traits>
#include <cassert>
using std::optional;
struct PODType {
int value;
int value2;
};
class X
{
public:
static bool dtor_called;
X() = default;
~X() {dtor_called = true;}
};
bool X::dtor_called = false;
int main()
{
{
typedef int T;
static_assert(std::is_trivially_destructible<T>::value, "");
static_assert(std::is_trivially_destructible<optional<T>>::value, "");
static_assert(std::is_literal_type<optional<T>>::value, "");
}
{
typedef double T;
static_assert(std::is_trivially_destructible<T>::value, "");
static_assert(std::is_trivially_destructible<optional<T>>::value, "");
static_assert(std::is_literal_type<optional<T>>::value, "");
}
{
typedef PODType T;
static_assert(std::is_trivially_destructible<T>::value, "");
static_assert(std::is_trivially_destructible<optional<T>>::value, "");
static_assert(std::is_literal_type<optional<T>>::value, "");
}
{
typedef X T;
static_assert(!std::is_trivially_destructible<T>::value, "");
static_assert(!std::is_trivially_destructible<optional<T>>::value, "");
static_assert(!std::is_literal_type<optional<T>>::value, "");
{
X x;
optional<X> opt{x};
assert(X::dtor_called == false);
}
assert(X::dtor_called == true);
}
}

View File

@@ -0,0 +1,61 @@
//===----------------------------------------------------------------------===//
//
// 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>
// void reset() noexcept;
#include <optional>
#include <type_traits>
#include <cassert>
using std::optional;
struct X
{
static bool dtor_called;
~X() {dtor_called = true;}
};
bool X::dtor_called = false;
int main()
{
{
optional<int> opt;
static_assert(noexcept(opt.reset()) == true, "");
opt.reset();
assert(static_cast<bool>(opt) == false);
}
{
optional<int> opt(3);
opt.reset();
assert(static_cast<bool>(opt) == false);
}
{
optional<X> opt;
static_assert(noexcept(opt.reset()) == true, "");
assert(X::dtor_called == false);
opt.reset();
assert(X::dtor_called == false);
assert(static_cast<bool>(opt) == false);
}
assert(X::dtor_called == false); // TRANSITION, Clang/C2 VSO#239997
{
optional<X> opt(X{});
X::dtor_called = false;
opt.reset();
assert(X::dtor_called == true);
assert(static_cast<bool>(opt) == false);
X::dtor_called = false;
}
assert(X::dtor_called == false); // TRANSITION, Clang/C2 VSO#239997
}

View File

@@ -0,0 +1,37 @@
//===----------------------------------------------------------------------===//
//
// 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 explicit optional<T>::operator bool() const noexcept;
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
int main()
{
using std::optional;
{
const optional<int> opt; ((void)opt);
ASSERT_NOEXCEPT(bool(opt));
static_assert(!std::is_convertible<optional<int>, bool>::value, "");
}
{
constexpr optional<int> opt;
static_assert(!opt, "");
}
{
constexpr optional<int> opt(0);
static_assert(opt, "");
}
}

View File

@@ -0,0 +1,73 @@
//===----------------------------------------------------------------------===//
//
// 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 T& optional<T>::operator*() &;
#ifdef _LIBCPP_DEBUG
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#endif
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
struct X
{
constexpr int test() const& {return 3;}
int test() & {return 4;}
constexpr int test() const&& {return 5;}
int test() && {return 6;}
};
struct Y
{
constexpr int test() {return 7;}
};
constexpr int
test()
{
optional<Y> opt{Y{}};
return (*opt).test();
}
int main()
{
{
optional<X> opt; ((void)opt);
ASSERT_SAME_TYPE(decltype(*opt), X&);
// ASSERT_NOT_NOEXCEPT(*opt);
// FIXME: This assertion fails with GCC because it can see that
// (A) operator*() is constexpr, and
// (B) there is no path through the function that throws.
// It's arguable if this is the correct behavior for the noexcept
// operator.
// Regardless this function should still be noexcept(false) because
// it has a narrow contract.
}
{
optional<X> opt(X{});
assert((*opt).test() == 4);
}
static_assert(test() == 7, "");
#ifdef _LIBCPP_DEBUG
{
optional<X> opt;
assert((*opt).test() == 3);
assert(false);
}
#endif // _LIBCPP_DEBUG
}

View File

@@ -0,0 +1,69 @@
//===----------------------------------------------------------------------===//
//
// 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 const T& optional<T>::operator*() const &;
#ifdef _LIBCPP_DEBUG
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#endif
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
struct X
{
constexpr int test() const& {return 3;}
int test() & {return 4;}
constexpr int test() const&& {return 5;}
int test() && {return 6;}
};
struct Y
{
int test() const {return 2;}
};
int main()
{
{
const optional<X> opt; ((void)opt);
ASSERT_SAME_TYPE(decltype(*opt), X const&);
// ASSERT_NOT_NOEXCEPT(*opt);
// FIXME: This assertion fails with GCC because it can see that
// (A) operator*() is constexpr, and
// (B) there is no path through the function that throws.
// It's arguable if this is the correct behavior for the noexcept
// operator.
// Regardless this function should still be noexcept(false) because
// it has a narrow contract.
}
{
constexpr optional<X> opt(X{});
static_assert((*opt).test() == 3, "");
}
{
constexpr optional<Y> opt(Y{});
assert((*opt).test() == 2);
}
#ifdef _LIBCPP_DEBUG
{
const optional<X> opt;
assert((*opt).test() == 3);
assert(false);
}
#endif // _LIBCPP_DEBUG
}

View File

@@ -0,0 +1,69 @@
//===----------------------------------------------------------------------===//
//
// 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 T&& optional<T>::operator*() const &&;
#ifdef _LIBCPP_DEBUG
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#endif
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
struct X
{
constexpr int test() const& {return 3;}
int test() & {return 4;}
constexpr int test() const&& {return 5;}
int test() && {return 6;}
};
struct Y
{
int test() const && {return 2;}
};
int main()
{
{
const optional<X> opt; ((void)opt);
ASSERT_SAME_TYPE(decltype(*std::move(opt)), X const &&);
// ASSERT_NOT_NOEXCEPT(*std::move(opt));
// FIXME: This assertion fails with GCC because it can see that
// (A) operator*() is constexpr, and
// (B) there is no path through the function that throws.
// It's arguable if this is the correct behavior for the noexcept
// operator.
// Regardless this function should still be noexcept(false) because
// it has a narrow contract.
}
{
constexpr optional<X> opt(X{});
static_assert((*std::move(opt)).test() == 5, "");
}
{
constexpr optional<Y> opt(Y{});
assert((*std::move(opt)).test() == 2);
}
#ifdef _LIBCPP_DEBUG
{
optional<X> opt;
assert((*std::move(opt)).test() == 5);
assert(false);
}
#endif // _LIBCPP_DEBUG
}

View File

@@ -0,0 +1,73 @@
//===----------------------------------------------------------------------===//
//
// 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 T&& optional<T>::operator*() &&;
#ifdef _LIBCPP_DEBUG
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#endif
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
struct X
{
constexpr int test() const& {return 3;}
int test() & {return 4;}
constexpr int test() const&& {return 5;}
int test() && {return 6;}
};
struct Y
{
constexpr int test() && {return 7;}
};
constexpr int
test()
{
optional<Y> opt{Y{}};
return (*std::move(opt)).test();
}
int main()
{
{
optional<X> opt; ((void)opt);
ASSERT_SAME_TYPE(decltype(*std::move(opt)), X&&);
// ASSERT_NOT_NOEXCEPT(*std::move(opt));
// FIXME: This assertion fails with GCC because it can see that
// (A) operator*() is constexpr, and
// (B) there is no path through the function that throws.
// It's arguable if this is the correct behavior for the noexcept
// operator.
// Regardless this function should still be noexcept(false) because
// it has a narrow contract.
}
{
optional<X> opt(X{});
assert((*std::move(opt)).test() == 6);
}
static_assert(test() == 7, "");
#ifdef _LIBCPP_DEBUG
{
optional<X> opt;
assert((*std::move(opt)).test() == 3);
assert(false);
}
#endif // _LIBCPP_DEBUG
}

View File

@@ -0,0 +1,37 @@
//===----------------------------------------------------------------------===//
//
// 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 bool optional<T>::has_value() const noexcept;
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
int main()
{
using std::optional;
{
const optional<int> opt; ((void)opt);
ASSERT_NOEXCEPT(opt.has_value());
ASSERT_SAME_TYPE(decltype(opt.has_value()), bool);
}
{
constexpr optional<int> opt;
static_assert(!opt.has_value(), "");
}
{
constexpr optional<int> opt(0);
static_assert(opt.has_value(), "");
}
}

View File

@@ -0,0 +1,72 @@
//===----------------------------------------------------------------------===//
//
// 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 T* optional<T>::operator->();
#ifdef _LIBCPP_DEBUG
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#endif
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
struct X
{
int test() noexcept {return 3;}
};
struct Y
{
constexpr int test() {return 3;}
};
constexpr int
test()
{
optional<Y> opt{Y{}};
return opt->test();
}
int main()
{
{
std::optional<X> opt; ((void)opt);
ASSERT_SAME_TYPE(decltype(opt.operator->()), X*);
// ASSERT_NOT_NOEXCEPT(opt.operator->());
// FIXME: This assertion fails with GCC because it can see that
// (A) operator->() is constexpr, and
// (B) there is no path through the function that throws.
// It's arguable if this is the correct behavior for the noexcept
// operator.
// Regardless this function should still be noexcept(false) because
// it has a narrow contract.
}
{
optional<X> opt(X{});
assert(opt->test() == 3);
}
{
static_assert(test() == 3, "");
}
#ifdef _LIBCPP_DEBUG
{
optional<X> opt;
assert(opt->test() == 3);
assert(false);
}
#endif // _LIBCPP_DEBUG
}

View File

@@ -0,0 +1,76 @@
//===----------------------------------------------------------------------===//
//
// 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 const T* optional<T>::operator->() const;
#ifdef _LIBCPP_DEBUG
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#endif
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
struct X
{
constexpr int test() const {return 3;}
};
struct Y
{
int test() const noexcept {return 2;}
};
struct Z
{
const Z* operator&() const;
constexpr int test() const {return 1;}
};
int main()
{
{
const std::optional<X> opt; ((void)opt);
ASSERT_SAME_TYPE(decltype(opt.operator->()), X const*);
// ASSERT_NOT_NOEXCEPT(opt.operator->());
// FIXME: This assertion fails with GCC because it can see that
// (A) operator->() is constexpr, and
// (B) there is no path through the function that throws.
// It's arguable if this is the correct behavior for the noexcept
// operator.
// Regardless this function should still be noexcept(false) because
// it has a narrow contract.
}
{
constexpr optional<X> opt(X{});
static_assert(opt->test() == 3, "");
}
{
constexpr optional<Y> opt(Y{});
assert(opt->test() == 2);
}
{
constexpr optional<Z> opt(Z{});
static_assert(opt->test() == 1, "");
}
#ifdef _LIBCPP_DEBUG
{
const optional<X> opt;
assert(opt->test() == 3);
assert(false);
}
#endif // _LIBCPP_DEBUG
}

View File

@@ -0,0 +1,73 @@
//===----------------------------------------------------------------------===//
//
// 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 T& optional<T>::value() &;
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
using std::bad_optional_access;
struct X
{
X() = default;
X(const X&) = delete;
constexpr int test() const & {return 3;}
int test() & {return 4;}
constexpr int test() const && {return 5;}
int test() && {return 6;}
};
struct Y
{
constexpr int test() & {return 7;}
};
constexpr int
test()
{
optional<Y> opt{Y{}};
return opt.value().test();
}
int main()
{
{
optional<X> opt; ((void)opt);
ASSERT_NOT_NOEXCEPT(opt.value());
ASSERT_SAME_TYPE(decltype(opt.value()), X&);
}
{
optional<X> opt;
opt.emplace();
assert(opt.value().test() == 4);
}
#ifndef TEST_HAS_NO_EXCEPTIONS
{
optional<X> opt;
try
{
opt.value();
assert(false);
}
catch (const bad_optional_access&)
{
}
}
#endif
static_assert(test() == 7, "");
}

View File

@@ -0,0 +1,33 @@
//===----------------------------------------------------------------------===//
//
// 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 const T& optional<T>::value() const &;
#include <optional>
#include <type_traits>
#include <cassert>
using std::optional;
struct X
{
constexpr int test() const {return 3;}
int test() {return 4;}
};
int main()
{
{
constexpr optional<X> opt;
static_assert(opt.value().test() == 3, "");
}
}

View File

@@ -0,0 +1,64 @@
//===----------------------------------------------------------------------===//
//
// 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 const T& optional<T>::value() const &;
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
using std::in_place_t;
using std::in_place;
using std::bad_optional_access;
struct X
{
X() = default;
X(const X&) = delete;
constexpr int test() const & {return 3;}
int test() & {return 4;}
constexpr int test() const && {return 5;}
int test() && {return 6;}
};
int main()
{
{
const optional<X> opt; ((void)opt);
ASSERT_NOT_NOEXCEPT(opt.value());
ASSERT_SAME_TYPE(decltype(opt.value()), X const&);
}
{
constexpr optional<X> opt(in_place);
static_assert(opt.value().test() == 3, "");
}
{
const optional<X> opt(in_place);
assert(opt.value().test() == 3);
}
#ifndef TEST_HAS_NO_EXCEPTIONS
{
const optional<X> opt;
try
{
opt.value();
assert(false);
}
catch (const bad_optional_access&)
{
}
}
#endif
}

View File

@@ -0,0 +1,64 @@
//===----------------------------------------------------------------------===//
//
// 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 const T& optional<T>::value() const &&;
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
using std::in_place_t;
using std::in_place;
using std::bad_optional_access;
struct X
{
X() = default;
X(const X&) = delete;
constexpr int test() const & {return 3;}
int test() & {return 4;}
constexpr int test() const && {return 5;}
int test() && {return 6;}
};
int main()
{
{
const optional<X> opt; ((void)opt);
ASSERT_NOT_NOEXCEPT(std::move(opt).value());
ASSERT_SAME_TYPE(decltype(std::move(opt).value()), X const&&);
}
{
constexpr optional<X> opt(in_place);
static_assert(std::move(opt).value().test() == 5, "");
}
{
const optional<X> opt(in_place);
assert(std::move(opt).value().test() == 5);
}
#ifndef TEST_HAS_NO_EXCEPTIONS
{
const optional<X> opt;
try
{
std::move(opt).value();
assert(false);
}
catch (const bad_optional_access&)
{
}
}
#endif
}

View File

@@ -0,0 +1,68 @@
//===----------------------------------------------------------------------===//
//
// 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>
// template <class U> T optional<T>::value_or(U&& v) &&;
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
using std::in_place_t;
using std::in_place;
struct Y
{
int i_;
Y(int i) : i_(i) {}
};
struct X
{
int i_;
X(int i) : i_(i) {}
X(X&& x) : i_(x.i_) {x.i_ = 0;}
X(const Y& y) : i_(y.i_) {}
X(Y&& y) : i_(y.i_+1) {}
friend constexpr bool operator==(const X& x, const X& y)
{return x.i_ == y.i_;}
};
int main()
{
{
optional<X> opt(in_place, 2);
Y y(3);
assert(std::move(opt).value_or(y) == 2);
assert(*opt == 0);
}
{
optional<X> opt(in_place, 2);
assert(std::move(opt).value_or(Y(3)) == 2);
assert(*opt == 0);
}
{
optional<X> opt;
Y y(3);
assert(std::move(opt).value_or(y) == 3);
assert(!opt);
}
{
optional<X> opt;
assert(std::move(opt).value_or(Y(3)) == 4);
assert(!opt);
}
}

View File

@@ -0,0 +1,77 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <optional>
// template <class U> constexpr T optional<T>::value_or(U&& v) const&;
#include <optional>
#include <type_traits>
#include <cassert>
using std::optional;
struct Y
{
int i_;
constexpr Y(int i) : i_(i) {}
};
struct X
{
int i_;
constexpr X(int i) : i_(i) {}
constexpr X(const Y& y) : i_(y.i_) {}
constexpr X(Y&& y) : i_(y.i_+1) {}
friend constexpr bool operator==(const X& x, const X& y)
{return x.i_ == y.i_;}
};
int main()
{
{
constexpr optional<X> opt(2);
constexpr Y y(3);
static_assert(opt.value_or(y) == 2, "");
}
{
constexpr optional<X> opt(2);
static_assert(opt.value_or(Y(3)) == 2, "");
}
{
constexpr optional<X> opt;
constexpr Y y(3);
static_assert(opt.value_or(y) == 3, "");
}
{
constexpr optional<X> opt;
static_assert(opt.value_or(Y(3)) == 4, "");
}
{
const optional<X> opt(2);
const Y y(3);
assert(opt.value_or(y) == 2);
}
{
const optional<X> opt(2);
assert(opt.value_or(Y(3)) == 2);
}
{
const optional<X> opt;
const Y y(3);
assert(opt.value_or(y) == 3);
}
{
const optional<X> opt;
assert(opt.value_or(Y(3)) == 4);
}
}

View File

@@ -0,0 +1,72 @@
//===----------------------------------------------------------------------===//
//
// 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 T& optional<T>::value() &&;
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
using std::optional;
using std::bad_optional_access;
struct X
{
X() = default;
X(const X&) = delete;
constexpr int test() const & {return 3;}
int test() & {return 4;}
constexpr int test() const && {return 5;}
int test() && {return 6;}
};
struct Y
{
constexpr int test() && {return 7;}
};
constexpr int
test()
{
optional<Y> opt{Y{}};
return std::move(opt).value().test();
}
int main()
{
{
optional<X> opt; ((void)opt);
ASSERT_NOT_NOEXCEPT(std::move(opt).value());
ASSERT_SAME_TYPE(decltype(std::move(opt).value()), X&&);
}
{
optional<X> opt;
opt.emplace();
assert(std::move(opt).value().test() == 6);
}
#ifndef TEST_HAS_NO_EXCEPTIONS
{
optional<X> opt;
try
{
std::move(opt).value();
assert(false);
}
catch (const bad_optional_access&)
{
}
}
#endif
static_assert(test() == 7, "");
}

View File

@@ -0,0 +1,306 @@
//===----------------------------------------------------------------------===//
//
// 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>
// void swap(optional&)
// noexcept(is_nothrow_move_constructible<T>::value &&
// is_nothrow_swappable<T>::value)
#include <optional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
#include "archetypes.hpp"
using std::optional;
class X
{
int i_;
public:
static unsigned dtor_called;
X(int i) : i_(i) {}
X(X&& x) = default;
X& operator=(X&&) = default;
~X() {++dtor_called;}
friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
};
unsigned X::dtor_called = 0;
class Y
{
int i_;
public:
static unsigned dtor_called;
Y(int i) : i_(i) {}
Y(Y&&) = default;
~Y() {++dtor_called;}
friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);}
};
unsigned Y::dtor_called = 0;
class Z
{
int i_;
public:
Z(int i) : i_(i) {}
Z(Z&&) {TEST_THROW(7);}
friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
friend void swap(Z& x, Z& y) {TEST_THROW(6);}
};
int main()
{
{
optional<int> opt1;
optional<int> opt2;
static_assert(noexcept(opt1.swap(opt2)) == true, "");
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == false);
opt1.swap(opt2);
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == false);
}
{
optional<int> opt1(1);
optional<int> opt2;
static_assert(noexcept(opt1.swap(opt2)) == true, "");
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 1);
assert(static_cast<bool>(opt2) == false);
opt1.swap(opt2);
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 1);
}
{
optional<int> opt1;
optional<int> opt2(2);
static_assert(noexcept(opt1.swap(opt2)) == true, "");
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 2);
opt1.swap(opt2);
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 2);
assert(static_cast<bool>(opt2) == false);
}
{
optional<int> opt1(1);
optional<int> opt2(2);
static_assert(noexcept(opt1.swap(opt2)) == true, "");
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 1);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 2);
opt1.swap(opt2);
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 2);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 1);
}
{
optional<X> opt1;
optional<X> opt2;
static_assert(noexcept(opt1.swap(opt2)) == true, "");
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == false);
opt1.swap(opt2);
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == false);
assert(X::dtor_called == 0);
}
{
optional<X> opt1(1);
optional<X> opt2;
static_assert(noexcept(opt1.swap(opt2)) == true, "");
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 1);
assert(static_cast<bool>(opt2) == false);
X::dtor_called = 0;
opt1.swap(opt2);
assert(X::dtor_called == 1);
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 1);
}
{
optional<X> opt1;
optional<X> opt2(2);
static_assert(noexcept(opt1.swap(opt2)) == true, "");
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 2);
X::dtor_called = 0;
opt1.swap(opt2);
assert(X::dtor_called == 1);
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 2);
assert(static_cast<bool>(opt2) == false);
}
{
optional<X> opt1(1);
optional<X> opt2(2);
static_assert(noexcept(opt1.swap(opt2)) == true, "");
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 1);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 2);
X::dtor_called = 0;
opt1.swap(opt2);
assert(X::dtor_called == 1); // from inside std::swap
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 2);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 1);
}
{
optional<Y> opt1;
optional<Y> opt2;
static_assert(noexcept(opt1.swap(opt2)) == false, "");
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == false);
opt1.swap(opt2);
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == false);
assert(Y::dtor_called == 0);
}
{
optional<Y> opt1(1);
optional<Y> opt2;
static_assert(noexcept(opt1.swap(opt2)) == false, "");
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 1);
assert(static_cast<bool>(opt2) == false);
Y::dtor_called = 0;
opt1.swap(opt2);
assert(Y::dtor_called == 1);
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 1);
}
{
optional<Y> opt1;
optional<Y> opt2(2);
static_assert(noexcept(opt1.swap(opt2)) == false, "");
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 2);
Y::dtor_called = 0;
opt1.swap(opt2);
assert(Y::dtor_called == 1);
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 2);
assert(static_cast<bool>(opt2) == false);
}
{
optional<Y> opt1(1);
optional<Y> opt2(2);
static_assert(noexcept(opt1.swap(opt2)) == false, "");
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 1);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 2);
Y::dtor_called = 0;
opt1.swap(opt2);
assert(Y::dtor_called == 0);
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 2);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 1);
}
{
optional<Z> opt1;
optional<Z> opt2;
static_assert(noexcept(opt1.swap(opt2)) == false, "");
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == false);
opt1.swap(opt2);
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == false);
}
#ifndef TEST_HAS_NO_EXCEPTIONS
{
optional<Z> opt1;
opt1.emplace(1);
optional<Z> opt2;
static_assert(noexcept(opt1.swap(opt2)) == false, "");
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 1);
assert(static_cast<bool>(opt2) == false);
try
{
opt1.swap(opt2);
assert(false);
}
catch (int i)
{
assert(i == 7);
}
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 1);
assert(static_cast<bool>(opt2) == false);
}
{
optional<Z> opt1;
optional<Z> opt2;
opt2.emplace(2);
static_assert(noexcept(opt1.swap(opt2)) == false, "");
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 2);
try
{
opt1.swap(opt2);
assert(false);
}
catch (int i)
{
assert(i == 7);
}
assert(static_cast<bool>(opt1) == false);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 2);
}
{
optional<Z> opt1;
opt1.emplace(1);
optional<Z> opt2;
opt2.emplace(2);
static_assert(noexcept(opt1.swap(opt2)) == false, "");
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 1);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 2);
try
{
opt1.swap(opt2);
assert(false);
}
catch (int i)
{
assert(i == 6);
}
assert(static_cast<bool>(opt1) == true);
assert(*opt1 == 1);
assert(static_cast<bool>(opt2) == true);
assert(*opt2 == 2);
}
#endif
}

View File

@@ -0,0 +1,50 @@
//===----------------------------------------------------------------------===//
//
// 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>
// T shall be an object type and shall satisfy the requirements of Destructible
#include <optional>
using std::optional;
struct X
{
private:
~X() {}
};
int main()
{
using std::optional;
{
// expected-error@optional:* 2 {{static_assert failed "instantiation of optional with a reference type is ill-formed}}
optional<int&> opt1;
optional<int&&> opt2;
}
{
// expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed"}}
optional<X> opt3;
}
{
// expected-error@optional:* {{static_assert failed "instantiation of optional with a non-object type is undefined behavior"}}
// expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed}}
optional<void()> opt4;
}
{
// expected-error@optional:* {{static_assert failed "instantiation of optional with a non-object type is undefined behavior"}}
// expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed}}
// expected-error@optional:* 1+ {{cannot form a reference to 'void'}}
optional<const void> opt4;
}
// FIXME these are garbage diagnostics that Clang should not produce
// expected-error@optional:* 0+ {{is not a base class}}
}

View File

@@ -0,0 +1,74 @@
//===----------------------------------------------------------------------===//
//
// 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>
#include <optional>
#include <type_traits>
#include <cassert>
#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_copy_constructible_v<T> && std::is_copy_assignable_v<T>) ||
(std::is_move_constructible_v<T> && std::is_move_assignable_v<T>)),
"optional<T> is move assignable if and only if T is both move assignable and "
"move constructible, or both copy constructible and copy assignable.");
};
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>{}
);
}

View File

@@ -0,0 +1,38 @@
//===----------------------------------------------------------------------===//
//
// 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>
// template <class T>
// class optional
// {
// public:
// typedef T value_type;
// ...
#include <optional>
#include <type_traits>
using std::optional;
template <class Opt, class T>
void
test()
{
static_assert(std::is_same<typename Opt::value_type, T>::value, "");
}
int main()
{
test<optional<int>, int>();
test<optional<const int>, const int>();
test<optional<double>, double>();
test<optional<const double>, const double>();
}