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