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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 // UNSUPPORTED: libcpp-no-concepts, libcpp-has-no-incomplete-ranges 11 12 // <algorithm> 13 // 14 // namespace ranges { 15 // template<class InputIterator, class OutputIterator> 16 // struct in_out_result; 17 // } 18 19 #include <algorithm> 20 #include <cassert> 21 #include <type_traits> 22 23 struct A { 24 A(int&); 25 }; 26 static_assert(!std::is_constructible_v<std::ranges::in_out_result<A, A>, std::ranges::in_out_result<int, int>&>); 27 28 static_assert(std::is_convertible_v<std::ranges::in_out_result<int, int>&, 29 std::ranges::in_out_result<long, long>>); 30 static_assert(!std::is_nothrow_convertible_v<std::ranges::in_out_result<int, int>&, 31 std::ranges::in_out_result<long, long>>); 32 static_assert(std::is_convertible_v<const std::ranges::in_out_result<int, int>&, 33 std::ranges::in_out_result<long, long>>); 34 static_assert(!std::is_nothrow_convertible_v<const std::ranges::in_out_result<int, int>&, 35 std::ranges::in_out_result<long, long>>); 36 static_assert(std::is_convertible_v<std::ranges::in_out_result<int, int>&&, 37 std::ranges::in_out_result<long, long>>); 38 static_assert(!std::is_nothrow_convertible_v<std::ranges::in_out_result<int, int>&&, 39 std::ranges::in_out_result<long, long>>); 40 static_assert(std::is_convertible_v<const std::ranges::in_out_result<int, int>&&, 41 std::ranges::in_out_result<long, long>>); 42 static_assert(!std::is_nothrow_convertible_v<const std::ranges::in_out_result<int, int>&&, 43 std::ranges::in_out_result<long, long>>); 44 45 int main(int, char**) { 46 // Conversion, fundamental types. 47 { 48 std::ranges::in_out_result<int, bool> x = {2, false}; 49 // FIXME(varconst): try a narrowing conversion. 50 std::ranges::in_out_result<long, char> y = x; 51 assert(y.in == 2); 52 assert(y.out == '\0'); 53 } 54 55 // Conversion, user-defined types. 56 { 57 struct From1 { 58 int value = 0; 59 From1(int v) : value(v) {} 60 }; 61 62 struct To1 { 63 int value = 0; 64 To1(int v) : value(v) {} 65 66 To1(const From1& f) : value(f.value) {}; 67 }; 68 69 struct To2 { 70 int value = 0; 71 To2(int v) : value(v) {} 72 }; 73 struct From2 { 74 int value = 0; 75 From2(int v) : value(v) {} 76 77 operator To2() const { return To2(value); } 78 }; 79 80 std::ranges::in_out_result<From1, From2> x{42, 99}; 81 std::ranges::in_out_result<To1, To2> y = x; 82 assert(y.in.value == 42); 83 assert(y.out.value == 99); 84 } 85 86 // Copy-only type. 87 { 88 struct CopyOnly { 89 int value = 0; 90 CopyOnly() = default; 91 CopyOnly(int v) : value(v) {} 92 93 CopyOnly(const CopyOnly&) = default; 94 CopyOnly(CopyOnly&&) = delete; 95 }; 96 97 std::ranges::in_out_result<CopyOnly, CopyOnly> x; 98 x.in.value = 42; 99 x.out.value = 99; 100 101 auto y = x; 102 assert(y.in.value == 42); 103 assert(y.out.value == 99); 104 } 105 106 // Move-only type. 107 { 108 struct MoveOnly { 109 int value = 0; 110 MoveOnly(int v) : value(v) {} 111 112 MoveOnly(MoveOnly&&) = default; 113 MoveOnly(const MoveOnly&) = delete; 114 }; 115 116 std::ranges::in_out_result<MoveOnly, MoveOnly> x{42, 99}; 117 auto y = std::move(x); 118 assert(y.in.value == 42); 119 assert(y.out.value == 99); 120 } 121 122 // Unsuccessful conversion. 123 { 124 struct Foo1 {}; 125 struct Foo2 {}; 126 struct Bar1 {}; 127 struct Bar2 {}; 128 static_assert( 129 !std::is_convertible_v<std::ranges::in_out_result<Foo1, Foo2>, std::ranges::in_out_result<Bar1, Bar2>>); 130 } 131 132 return 0; 133 } 134