//===----------------------------------------------------------------------===// // // 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 // // template // constexpr EXPLICIT optional(U&& u); #include #include #include #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);} }; 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() { test_implicit(); test_explicit(); }