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
11 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
12 
13 // template <class I1, class I2>
14 // struct in_in_result;
15 
16 #include <algorithm>
17 #include <cassert>
18 #include <type_traits>
19 
20 #include "MoveOnly.h"
21 
22 template <class T>
23 struct ConstructibleFrom {
24   constexpr ConstructibleFrom(T c) : content{c} {}
25   T content;
26 };
27 
28 struct A {
29   explicit A(int);
30 };
31 static_assert(!std::is_constructible_v<std::ranges::in_in_result<A, A>,
32                                        std::ranges::in_in_result<int, int>>);
33 
34 struct B {
35   B(const int&);
36   B(int&&);
37 };
38 static_assert(std::is_constructible_v<std::ranges::in_in_result<B, B>, std::ranges::in_in_result<int, int>>);
39 static_assert(std::is_constructible_v<std::ranges::in_in_result<B, B>, std::ranges::in_in_result<int, int>&>);
40 static_assert(std::is_constructible_v<std::ranges::in_in_result<B, B>, const std::ranges::in_in_result<int, int>>);
41 static_assert(std::is_constructible_v<std::ranges::in_in_result<B, B>, const std::ranges::in_in_result<int, int>&>);
42 
43 struct C {
44   C(int&);
45 };
46 static_assert(!std::is_constructible_v<std::ranges::in_in_result<C, C>, std::ranges::in_in_result<int, int>&>);
47 
48 static_assert(std::is_convertible_v<         std::ranges::in_in_result<int, int>&, std::ranges::in_in_result<long, long>>);
49 static_assert(!std::is_nothrow_convertible_v<std::ranges::in_in_result<int, int>&, std::ranges::in_in_result<long, long>>);
50 static_assert(std::is_convertible_v<         const std::ranges::in_in_result<int, int>&, std::ranges::in_in_result<long, long>>);
51 static_assert(!std::is_nothrow_convertible_v<const std::ranges::in_in_result<int, int>&, std::ranges::in_in_result<long, long>>);
52 static_assert(std::is_convertible_v<         std::ranges::in_in_result<int, int>&&, std::ranges::in_in_result<long, long>>);
53 static_assert(!std::is_nothrow_convertible_v<std::ranges::in_in_result<int, int>&&, std::ranges::in_in_result<long, long>>);
54 static_assert(std::is_convertible_v<         const std::ranges::in_in_result<int, int>&&, std::ranges::in_in_result<long, long>>);
55 static_assert(!std::is_nothrow_convertible_v<const std::ranges::in_in_result<int, int>&&, std::ranges::in_in_result<long, long>>);
56 
57 struct NotConvertible {};
58 static_assert(!std::is_convertible_v<std::ranges::in_in_result<NotConvertible, int>,
59                                      std::ranges::in_in_result<int, int>>);
60 static_assert(!std::is_convertible_v<std::ranges::in_in_result<int, NotConvertible>,
61                                      std::ranges::in_in_result<int, int>>);
62 
63 constexpr bool test() {
64   {
65     std::ranges::in_in_result<int, double> res{10L, 0.};
66     assert(res.in1 == 10);
67     assert(res.in2 == 0.);
68     std::ranges::in_in_result<ConstructibleFrom<int>, ConstructibleFrom<double>> res2 = res;
69     assert(res2.in1.content == 10);
70     assert(res2.in2.content == 0.);
71   }
72   {
73     std::ranges::in_in_result<MoveOnly, int> res{MoveOnly{}, 0};
74     assert(res.in1.get() == 1);
75     [[maybe_unused]] auto res2 = static_cast<std::ranges::in_in_result<MoveOnly, int>>(std::move(res));
76     assert(res.in1.get() == 0);
77   }
78   auto [in1, in2] = std::ranges::in_in_result<int, int>{1, 2};
79   assert(in1 == 1);
80   assert(in2 == 2);
81 
82   return true;
83 }
84 
85 int main(int, char**) {
86   test();
87   static_assert(test());
88 
89   return 0;
90 }
91