158 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 11// <optional>12 13// template <class U>14// constexpr EXPLICIT optional(U&& u);15 16#include <cassert>17#include <optional>18#include <type_traits>19 20#include "test_macros.h"21#include "archetypes.h"22#include "test_convertible.h"23 24using std::optional;25 26struct ImplicitThrow {27 constexpr ImplicitThrow(int x) {28 if (x != -1)29 TEST_THROW(6);30 }31};32 33struct ExplicitThrow {34 constexpr explicit ExplicitThrow(int x) {35 if (x != -1)36 TEST_THROW(6);37 }38};39 40struct ImplicitAny {41 template <class U>42 constexpr ImplicitAny(U&&) {}43};44 45template <class To, class From>46constexpr bool implicit_conversion(optional<To>&& opt, const From& v) {47 using O = optional<To>;48 static_assert(test_convertible<O, From>(), "");49 static_assert(!test_convertible<O, void*>(), "");50 static_assert(!test_convertible<O, From, int>(), "");51 return opt && *opt == static_cast<To>(v);52}53 54template <class To, class Input, class Expect>55constexpr bool explicit_conversion(Input&& in, const Expect& v) {56 using O = optional<To>;57 static_assert(std::is_constructible<O, Input>::value, "");58 static_assert(!std::is_convertible<Input, O>::value, "");59 static_assert(!std::is_constructible<O, void*>::value, "");60 static_assert(!std::is_constructible<O, Input, int>::value, "");61 optional<To> opt(std::forward<Input>(in));62 optional<To> opt2{std::forward<Input>(in)};63 return opt && *opt == static_cast<To>(v) && (opt2 && *opt2 == static_cast<To>(v));64}65 66void test_implicit() {67 {68 static_assert(implicit_conversion<long long>(42, 42), "");69 }70 {71 static_assert(implicit_conversion<long double>(3.14, 3.14), "");72 }73 {74 int x = 42;75 optional<void* const> o(&x);76 assert(*o == &x);77 }78 {79 using T = TrivialTestTypes::TestType;80 static_assert(implicit_conversion<T>(42, 42), "");81 }82 {83 using T = TestTypes::TestType;84 assert(implicit_conversion<T>(3, T(3)));85 }86 {87 using T = TestTypes::TestType;88 optional<T> opt({3});89 assert(opt && *opt == static_cast<T>(3));90 }91 {92 using O = optional<ImplicitAny>;93 static_assert(!test_convertible<O, std::in_place_t>(), "");94 static_assert(!test_convertible<O, std::in_place_t&>(), "");95 static_assert(!test_convertible<O, const std::in_place_t&>(), "");96 static_assert(!test_convertible<O, std::in_place_t&&>(), "");97 static_assert(!test_convertible<O, const std::in_place_t&&>(), "");98 }99#ifndef TEST_HAS_NO_EXCEPTIONS100 {101 try {102 using T = ImplicitThrow;103 optional<T> t = 42;104 assert(false);105 ((void)t);106 } catch (int) {107 }108 }109#endif110}111 112void test_explicit() {113 {114 using T = ExplicitTrivialTestTypes::TestType;115 static_assert(explicit_conversion<T>(42, 42), "");116 }117 {118 using T = ExplicitConstexprTestTypes::TestType;119 static_assert(explicit_conversion<T>(42, 42), "");120 static_assert(!std::is_convertible<int, T>::value, "");121 }122 {123 using T = ExplicitTestTypes::TestType;124 T::reset();125 {126 assert(explicit_conversion<T>(42, 42));127 assert(T::alive == 0);128 }129 T::reset();130 {131 optional<T> t(42);132 assert(T::alive == 1);133 assert(T::value_constructed == 1);134 assert(T::move_constructed == 0);135 assert(T::copy_constructed == 0);136 assert(t.value().value == 42);137 }138 assert(T::alive == 0);139 }140#ifndef TEST_HAS_NO_EXCEPTIONS141 {142 try {143 using T = ExplicitThrow;144 optional<T> t(42);145 assert(false);146 } catch (int) {147 }148 }149#endif150}151 152int main(int, char**) {153 test_implicit();154 test_explicit();155 156 return 0;157}158