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, c++20
10
11// template <class O, class T>
12// struct out_value_result;
13
14#include <algorithm>
15#include <cassert>
16#include <type_traits>
17
18#include "MoveOnly.h"
19
20using std::ranges::out_value_result;
21
22//
23// Helper structs
24//
25
26// only explicit construction
27struct IterTypeExplicit {
28 explicit IterTypeExplicit(int*);
29};
30
31// implicit construction
32struct IterTypeImplicit {
33 IterTypeImplicit(int*);
34};
35
36struct IterTypeImplicitRef {
37 IterTypeImplicitRef(int&);
38};
39
40struct NotConvertible {};
41
42template <class T>
43struct ConvertibleFrom {
44 constexpr ConvertibleFrom(T c) : content{c} {}
45 T content;
46};
47
48// Standard layout classes can't have virtual functions
49struct NonStandardLayoutTypeBase {
50 virtual ~NonStandardLayoutTypeBase();
51};
52struct NonStandardLayoutType : public NonStandardLayoutTypeBase {};
53
54//
55constexpr bool test_constraints() {
56 // requires convertible_to<const _OutIter1&, _OutIter2> && convertible_to<const _ValType1&, _ValType2>
57 static_assert(std::is_constructible_v<out_value_result<int*, int>, out_value_result<int*, int>>);
58
59 // test failure when implicit conversion isn't allowed
60 static_assert(!std::is_constructible_v<out_value_result<IterTypeExplicit, int>, out_value_result<int*, int>>);
61
62 // test success when implicit conversion is allowed, checking combinations of value, reference, and const
63 static_assert(std::is_constructible_v<out_value_result<IterTypeImplicit, int>, out_value_result<int*, int>>);
64 static_assert(std::is_constructible_v<out_value_result<IterTypeImplicit, int>, out_value_result<int*, int> const>);
65 static_assert(std::is_constructible_v<out_value_result<IterTypeImplicit, int>, out_value_result<int*, int>&>);
66 static_assert(std::is_constructible_v<out_value_result<IterTypeImplicit, int>, out_value_result<int*, int> const&>);
67
68 static_assert(!std::is_constructible_v<out_value_result<IterTypeImplicitRef, int>, out_value_result<int, int>&>);
69
70 // has to be convertible via const&
71 static_assert(std::is_convertible_v<out_value_result<int, int>&, out_value_result<long, long>>);
72 static_assert(std::is_convertible_v<const out_value_result<int, int>&, out_value_result<long, long>>);
73 static_assert(std::is_convertible_v<out_value_result<int, int>&&, out_value_result<long, long>>);
74 static_assert(std::is_convertible_v<const out_value_result<int, int>&&, out_value_result<long, long>>);
75
76 // should be move constructible
77 static_assert(std::is_move_constructible_v<out_value_result<MoveOnly, int>>);
78 static_assert(std::is_move_constructible_v<out_value_result<int, MoveOnly>>);
79
80 // conversions should not work if there is no conversion
81 static_assert(!std::is_convertible_v<out_value_result<NotConvertible, int>, out_value_result<int, NotConvertible>>);
82 static_assert(!std::is_convertible_v<out_value_result<int, NotConvertible>, out_value_result<NotConvertible, int>>);
83
84 // check standard layout
85 static_assert(std::is_standard_layout_v<out_value_result<int, int>>);
86 static_assert(!std::is_standard_layout_v<out_value_result<NonStandardLayoutType, int>>);
87
88 return true;
89}
90
91// Test results
92constexpr bool test() {
93 {
94 // Check that conversion operator works
95 out_value_result<double, int> res{10, 1};
96 assert(res.out == 10);
97 assert(res.value == 1);
98 out_value_result<ConvertibleFrom<double>, ConvertibleFrom<int>> res2 = res;
99 assert(res2.out.content == 10);
100 assert(res2.value.content == 1);
101 }
102 {
103 // Check that out_value_result isn't overconstrained w.r.t. move/copy constructors
104 out_value_result<MoveOnly, int> res{MoveOnly{}, 10};
105 assert(res.out.get() == 1);
106 assert(res.value == 10);
107 auto res2 = std::move(res);
108 assert(res.out.get() == 0);
109 assert(res.value == 10);
110 assert(res2.out.get() == 1);
111 assert(res2.value == 10);
112 }
113 {
114 // Check structured binding
115 auto [out, val] = out_value_result<int, int>{1, 2};
116 assert(out == 1);
117 assert(val == 2);
118 }
119 {
120 // Check default construction
121 out_value_result<int, double> res;
122 static_assert(std::is_same_v<int, decltype(res.out)>);
123 static_assert(std::is_same_v<double, decltype(res.value)>);
124 }
125 {
126 // Check aggregate initiazliation
127 out_value_result<int, int> res = {1, 2};
128 assert(res.out == 1);
129 assert(res.value == 2);
130 }
131
132 return true;
133}
134
135int main(int, char**) {
136 test_constraints();
137 static_assert(test_constraints());
138 test();
139 static_assert(test());
140 return 0;
141}
142

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of libcxx/test/std/algorithms/algorithms.results/out_value_result.pass.cpp