137 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++14, c++17, c++2010 11// template<class... Args>12// constexpr explicit expected(unexpect_t, Args&&... args);13//14// Constraints: is_constructible_v<E, Args...> is true.15//16// Effects: Direct-non-list-initializes unex with std::forward<Args>(args)....17//18// Postconditions: has_value() is false.19//20// Throws: Any exception thrown by the initialization of unex.21 22#include <cassert>23#include <expected>24#include <tuple>25#include <type_traits>26#include <utility>27 28#include "MoveOnly.h"29#include "test_macros.h"30#include "../../types.h"31 32// Test Constraints:33static_assert(std::is_constructible_v<std::expected<void, int>, std::unexpect_t>);34static_assert(std::is_constructible_v<std::expected<void, int>, std::unexpect_t, int>);35 36// !is_constructible_v<T, Args...>37struct foo {};38static_assert(!std::is_constructible_v<std::expected<void, foo>, std::unexpect_t, int>);39 40// test explicit41template <class T>42void conversion_test(T);43 44template <class T, class... Args>45concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };46static_assert(ImplicitlyConstructible<int, int>);47 48static_assert(!ImplicitlyConstructible<std::expected<void, int>, std::unexpect_t>);49static_assert(!ImplicitlyConstructible<std::expected<void, int>, std::unexpect_t, int>);50 51struct CopyOnly {52 int i;53 constexpr CopyOnly(int ii) : i(ii) {}54 CopyOnly(const CopyOnly&) = default;55 CopyOnly(CopyOnly&&) = delete;56 friend constexpr bool operator==(const CopyOnly& mi, int ii) { return mi.i == ii; }57};58 59template <class T>60constexpr void testInt() {61 std::expected<void, T> e(std::unexpect, 5);62 assert(!e.has_value());63 assert(e.error() == 5);64}65 66template <class T>67constexpr void testLValue() {68 T t(5);69 std::expected<void, T> e(std::unexpect, t);70 assert(!e.has_value());71 assert(e.error() == 5);72}73 74template <class T>75constexpr void testRValue() {76 std::expected<void, T> e(std::unexpect, T(5));77 assert(!e.has_value());78 assert(e.error() == 5);79}80 81constexpr bool test() {82 testInt<int>();83 testInt<CopyOnly>();84 testInt<MoveOnly>();85 testInt<TailClobberer<1>>();86 testLValue<int>();87 testLValue<CopyOnly>();88 testLValue<TailClobberer<1>>();89 testRValue<int>();90 testRValue<MoveOnly>();91 testRValue<TailClobberer<1>>();92 93 // no arg94 {95 std::expected<void, int> e(std::unexpect);96 assert(!e.has_value());97 assert(e.error() == 0);98 }99 100 // one arg101 {102 std::expected<void, int> e(std::unexpect, 5);103 assert(!e.has_value());104 assert(e.error() == 5);105 }106 107 // multi args108 {109 std::expected<void, std::tuple<int, short, MoveOnly>> e(std::unexpect, 1, short{2}, MoveOnly(3));110 assert(!e.has_value());111 assert((e.error() == std::tuple<int, short, MoveOnly>(1, short{2}, MoveOnly(3))));112 }113 114 return true;115}116 117void testException() {118#ifndef TEST_HAS_NO_EXCEPTIONS119 struct Throwing {120 Throwing(int) { throw Except{}; };121 };122 123 try {124 std::expected<void, Throwing> u(std::unexpect, 5);125 assert(false);126 } catch (Except) {127 }128#endif // TEST_HAS_NO_EXCEPTIONS129}130 131int main(int, char**) {132 test();133 static_assert(test());134 testException();135 return 0;136}137