brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.7 KiB · 9f45976 Raw
142 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2010 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 structs24//25 26// only explicit construction27struct IterTypeExplicit {28  explicit IterTypeExplicit(int*);29};30 31// implicit construction32struct 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 functions49struct 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 allowed60  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 const63  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 constructible77  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 conversion81  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 layout85  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 results92constexpr bool test() {93  {94    // Check that conversion operator works95    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 constructors104    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 binding115    auto [out, val] = out_value_result<int, int>{1, 2};116    assert(out == 1);117    assert(val == 2);118  }119  {120    // Check default construction121    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 initialization127    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