//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // UNSUPPORTED: c++98, c++03, c++11, c++14 // XFAIL: dylib-has-no-bad_optional_access && !libcpp-no-exceptions // // template // constexpr EXPLICIT optional(U&& u); #include #include #include #include "test_macros.h" #include "archetypes.h" #include "test_convertible.h" 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);} }; struct ImplicitAny { template constexpr ImplicitAny(U&&) {} }; template constexpr bool implicit_conversion(optional&& opt, const From& v) { using O = optional; static_assert(test_convertible(), ""); static_assert(!test_convertible(), ""); static_assert(!test_convertible(), ""); return opt && *opt == static_cast(v); } template constexpr bool explicit_conversion(Input&& in, const Expect& v) { using O = optional; static_assert(std::is_constructible::value, ""); static_assert(!std::is_convertible::value, ""); static_assert(!std::is_constructible::value, ""); static_assert(!std::is_constructible::value, ""); optional opt(std::forward(in)); return opt && *opt == static_cast(v); } void test_implicit() { { static_assert(implicit_conversion(42, 42), ""); } { static_assert(implicit_conversion(3.14, 3.14), ""); } { int x = 42; optional o(&x); assert(*o == &x); } { using T = TrivialTestTypes::TestType; static_assert(implicit_conversion(42, 42), ""); } { using T = TestTypes::TestType; assert(implicit_conversion(3, T(3))); } { using O = optional; static_assert(!test_convertible(), ""); static_assert(!test_convertible(), ""); static_assert(!test_convertible(), ""); static_assert(!test_convertible(), ""); static_assert(!test_convertible(), ""); } #ifndef TEST_HAS_NO_EXCEPTIONS { try { using T = ImplicitThrow; optional t = 42; assert(false); ((void)t); } catch (int) { } } #endif } void test_explicit() { { using T = ExplicitTrivialTestTypes::TestType; static_assert(explicit_conversion(42, 42), ""); } { using T = ExplicitConstexprTestTypes::TestType; static_assert(explicit_conversion(42, 42), ""); static_assert(!std::is_convertible::value, ""); } { using T = ExplicitTestTypes::TestType; T::reset(); { assert(explicit_conversion(42, 42)); assert(T::alive == 0); } T::reset(); { optional 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(42); assert(false); } catch (int) { } } #endif } int main(int, char**) { test_implicit(); test_explicit(); return 0; }