176 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410// <optional>11 12// constexpr optional(const optional<T>& rhs);13 14#include <cassert>15#include <optional>16#include <type_traits>17 18#include "test_macros.h"19#include "archetypes.h"20 21using std::optional;22 23template <class T, class... InitArgs>24void test(InitArgs&&... args) {25 const optional<T> rhs(std::forward<InitArgs>(args)...);26 bool rhs_engaged = static_cast<bool>(rhs);27 optional<T> lhs = rhs;28 assert(static_cast<bool>(lhs) == rhs_engaged);29 if (rhs_engaged)30 assert(*lhs == *rhs);31}32 33template <class T, class... InitArgs>34constexpr bool constexpr_test(InitArgs&&... args) {35 static_assert(std::is_trivially_copy_constructible_v<T>, ""); // requirement36 const optional<T> rhs(std::forward<InitArgs>(args)...);37 optional<T> lhs = rhs;38 return (lhs.has_value() == rhs.has_value()) && (lhs.has_value() ? *lhs == *rhs : true);39}40 41void test_throwing_ctor() {42#ifndef TEST_HAS_NO_EXCEPTIONS43 struct Z {44 Z() : count(0) {}45 Z(Z const& o) : count(o.count + 1) {46 if (count == 2)47 throw 6;48 }49 int count;50 };51 const Z z;52 const optional<Z> rhs(z);53 try {54 optional<Z> lhs(rhs);55 assert(false);56 } catch (int i) {57 assert(i == 6);58 }59#endif60}61 62template <class T, class... InitArgs>63void test_ref(InitArgs&&... args) {64 const optional<T> rhs(std::forward<InitArgs>(args)...);65 bool rhs_engaged = static_cast<bool>(rhs);66 optional<T> lhs = rhs;67 assert(static_cast<bool>(lhs) == rhs_engaged);68 if (rhs_engaged)69 assert(&(*lhs) == &(*rhs));70}71 72void test_reference_extension() {73#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled.74 using T = TestTypes::TestType;75 T::reset();76 {77 T t;78 T::reset_constructors();79 test_ref<T&>();80 test_ref<T&>(t);81 assert(T::alive == 1);82 assert(T::constructed == 0);83 assert(T::assigned == 0);84 assert(T::destroyed == 0);85 }86 assert(T::destroyed == 1);87 assert(T::alive == 0);88 {89 T t;90 const T& ct = t;91 T::reset_constructors();92 test_ref<T const&>();93 test_ref<T const&>(t);94 test_ref<T const&>(ct);95 assert(T::alive == 1);96 assert(T::constructed == 0);97 assert(T::assigned == 0);98 assert(T::destroyed == 0);99 }100 assert(T::alive == 0);101 assert(T::destroyed == 1);102 {103 static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, "");104 static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, "");105 }106#endif107}108 109int main(int, char**) {110 test<int>();111 test<int>(3);112 static_assert(constexpr_test<int>(), "");113 static_assert(constexpr_test<int>(3), "");114 115 {116 const optional<const int> o(42);117 optional<const int> o2(o);118 assert(*o2 == 42);119 }120 {121 using T = TestTypes::TestType;122 T::reset();123 const optional<T> rhs;124 assert(T::alive == 0);125 const optional<T> lhs(rhs);126 assert(lhs.has_value() == false);127 assert(T::alive == 0);128 }129 TestTypes::TestType::reset();130 {131 using T = TestTypes::TestType;132 T::reset();133 const optional<T> rhs(42);134 assert(T::alive == 1);135 assert(T::value_constructed == 1);136 assert(T::copy_constructed == 0);137 const optional<T> lhs(rhs);138 assert(lhs.has_value());139 assert(T::copy_constructed == 1);140 assert(T::alive == 2);141 }142 TestTypes::TestType::reset();143 {144 using namespace ConstexprTestTypes;145 test<TestType>();146 test<TestType>(42);147 }148 {149 using namespace TrivialTestTypes;150 test<TestType>();151 test<TestType>(42);152 }153 {154 test_throwing_ctor();155 }156 {157 test_reference_extension();158 }159 {160 constexpr std::optional<int> o1{4};161 constexpr std::optional<int> o2 = o1;162 static_assert(*o2 == 4, "");163 }164 165 // LWG3836 https://wg21.link/LWG3836166 // std::optional<bool> conversion constructor optional(const optional<U>&)167 // should take precedence over optional(U&&) with operator bool168 {169 std::optional<bool> o1(false);170 std::optional<bool> o2(o1);171 assert(!o2.value());172 }173 174 return 0;175}176