File: out_value_result.pass.cpp

package info (click to toggle)
llvm-toolchain-snapshot 1%3A22~%2B%2B20250731080150%2Bbe449d6b6587-1~exp1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 2,250,472 kB
  • sloc: cpp: 7,641,756; ansic: 1,439,220; asm: 1,072,591; python: 253,178; f90: 95,173; objc: 70,722; lisp: 44,365; pascal: 18,720; sh: 10,051; ml: 5,111; perl: 4,720; awk: 3,523; makefile: 3,397; javascript: 2,272; xml: 892; fortran: 783
file content (141 lines) | stat: -rw-r--r-- 4,823 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20

//  template <class O, class T>
//    struct out_value_result;

#include <algorithm>
#include <cassert>
#include <type_traits>

#include "MoveOnly.h"

using std::ranges::out_value_result;

//
// Helper structs
//

// only explicit construction
struct IterTypeExplicit {
  explicit IterTypeExplicit(int*);
};

// implicit construction
struct IterTypeImplicit {
  IterTypeImplicit(int*);
};

struct IterTypeImplicitRef {
  IterTypeImplicitRef(int&);
};

struct NotConvertible {};

template <class T>
struct ConvertibleFrom {
  constexpr ConvertibleFrom(T c) : content{c} {}
  T content;
};

// Standard layout classes can't have virtual functions
struct NonStandardLayoutTypeBase {
  virtual ~NonStandardLayoutTypeBase();
};
struct NonStandardLayoutType : public NonStandardLayoutTypeBase {};

//
constexpr bool test_constraints() {
  // requires convertible_to<const _OutIter1&, _OutIter2> && convertible_to<const _ValType1&, _ValType2>
  static_assert(std::is_constructible_v<out_value_result<int*, int>, out_value_result<int*, int>>);

  // test failure when implicit conversion isn't allowed
  static_assert(!std::is_constructible_v<out_value_result<IterTypeExplicit, int>, out_value_result<int*, int>>);

  // test success when implicit conversion is allowed, checking combinations of value, reference, and const
  static_assert(std::is_constructible_v<out_value_result<IterTypeImplicit, int>, out_value_result<int*, int>>);
  static_assert(std::is_constructible_v<out_value_result<IterTypeImplicit, int>, out_value_result<int*, int> const>);
  static_assert(std::is_constructible_v<out_value_result<IterTypeImplicit, int>, out_value_result<int*, int>&>);
  static_assert(std::is_constructible_v<out_value_result<IterTypeImplicit, int>, out_value_result<int*, int> const&>);

  static_assert(!std::is_constructible_v<out_value_result<IterTypeImplicitRef, int>, out_value_result<int, int>&>);

  // has to be convertible via const&
  static_assert(std::is_convertible_v<out_value_result<int, int>&, out_value_result<long, long>>);
  static_assert(std::is_convertible_v<const out_value_result<int, int>&, out_value_result<long, long>>);
  static_assert(std::is_convertible_v<out_value_result<int, int>&&, out_value_result<long, long>>);
  static_assert(std::is_convertible_v<const out_value_result<int, int>&&, out_value_result<long, long>>);

  // should be move constructible
  static_assert(std::is_move_constructible_v<out_value_result<MoveOnly, int>>);
  static_assert(std::is_move_constructible_v<out_value_result<int, MoveOnly>>);

  // conversions should not work if there is no conversion
  static_assert(!std::is_convertible_v<out_value_result<NotConvertible, int>, out_value_result<int, NotConvertible>>);
  static_assert(!std::is_convertible_v<out_value_result<int, NotConvertible>, out_value_result<NotConvertible, int>>);

  // check standard layout
  static_assert(std::is_standard_layout_v<out_value_result<int, int>>);
  static_assert(!std::is_standard_layout_v<out_value_result<NonStandardLayoutType, int>>);

  return true;
}

// Test results
constexpr bool test() {
  {
    // Check that conversion operator works
    out_value_result<double, int> res{10, 1};
    assert(res.out == 10);
    assert(res.value == 1);
    out_value_result<ConvertibleFrom<double>, ConvertibleFrom<int>> res2 = res;
    assert(res2.out.content == 10);
    assert(res2.value.content == 1);
  }
  {
    // Check that out_value_result isn't overconstrained w.r.t. move/copy constructors
    out_value_result<MoveOnly, int> res{MoveOnly{}, 10};
    assert(res.out.get() == 1);
    assert(res.value == 10);
    auto res2 = std::move(res);
    assert(res.out.get() == 0);
    assert(res.value == 10);
    assert(res2.out.get() == 1);
    assert(res2.value == 10);
  }
  {
    // Check structured binding
    auto [out, val] = out_value_result<int, int>{1, 2};
    assert(out == 1);
    assert(val == 2);
  }
  {
    // Check default construction
    out_value_result<int, double> res;
    static_assert(std::is_same_v<int, decltype(res.out)>);
    static_assert(std::is_same_v<double, decltype(res.value)>);
  }
  {
    // Check aggregate initiazliation
    out_value_result<int, int> res = {1, 2};
    assert(res.out == 1);
    assert(res.value == 2);
  }

  return true;
}

int main(int, char**) {
  test_constraints();
  static_assert(test_constraints());
  test();
  static_assert(test());
  return 0;
}