brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.1 KiB · b2eeddd Raw
226 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// REQUIRES: std-at-least-c++2310 11// <ranges>12 13// constexpr decltype(auto) operator*() const;14 15#include <ranges>16 17#include <array>18#include <cassert>19#include <cstddef>20#include <string>21#include <string_view>22#include <type_traits>23#include <utility>24#include <vector>25 26#include "../types.h"27 28struct ProxyRef {29  int& val;30};31 32class CommonProxyRef {33public:34  constexpr CommonProxyRef(ProxyRef i) : val(i.val) {}35  constexpr CommonProxyRef(int i) : val(i) {}36 37  constexpr int get() const { return val; }38 39private:40  int val;41};42 43template <template <class> class TQual, template <class> class UQual>44struct std::basic_common_reference<ProxyRef, int, TQual, UQual> {45  using type = CommonProxyRef;46};47 48template <template <class> class TQual, template <class> class UQual>49struct std::basic_common_reference<int, ProxyRef, TQual, UQual> {50  using type = CommonProxyRef;51};52 53static_assert(std::common_reference_with<int&, ProxyRef>);54static_assert(std::common_reference_with<int&, CommonProxyRef>);55 56class ProxyIter {57public:58  using value_type      = int;59  using difference_type = std::ptrdiff_t;60 61  constexpr ProxyIter() : ptr_(nullptr) {}62  constexpr explicit ProxyIter(int* p) : ptr_(p) {}63 64  constexpr ProxyRef operator*() const { return ProxyRef{*ptr_}; }65 66  constexpr ProxyIter& operator++() {67    ++ptr_;68    return *this;69  }70 71  constexpr ProxyIter operator++(int) {72    ProxyIter tmp = *this;73    ++ptr_;74    return tmp;75  }76 77  constexpr bool operator==(const ProxyIter& other) const { return ptr_ == other.ptr_; }78 79private:80  int* ptr_;81};82 83static_assert(std::forward_iterator<ProxyIter>);84 85constexpr bool test() {86  { // Result of `operator*` is (maybe const) lvalue reference87    using V       = std::ranges::owning_view<std::vector<std::string>>;88    using Pattern = std::ranges::owning_view<std::string>;89    using JWV     = std::ranges::join_with_view<V, Pattern>;90 91    JWV jwv(V{{"ab", "cd", "ef"}}, Pattern{"><"});92 93    {94      auto it                                  = jwv.begin();95      std::same_as<char&> decltype(auto) v_ref = *std::as_const(it);96      assert(v_ref == 'a');97      std::ranges::advance(it, 2);98      std::same_as<char&> decltype(auto) pattern_ref = *it;99      assert(pattern_ref == '>');100    }101 102    {103      auto cit                                        = std::as_const(jwv).begin();104      std::same_as<const char&> decltype(auto) cv_ref = *cit;105      assert(cv_ref == 'a');106      std::ranges::advance(cit, 3);107      std::same_as<const char&> decltype(auto) cpattern_ref = *std::as_const(cit);108      assert(cpattern_ref == '<');109    }110  }111 112  { // Result of `operator*` is const lvalue reference113    using V       = std::ranges::owning_view<std::vector<std::string_view>>;114    using Pattern = std::string_view;115    using JWV     = std::ranges::join_with_view<V, Pattern>;116 117    JWV jwv(V{{"123", "456", "789"}}, Pattern{"._."});118 119    {120      auto it                                        = jwv.begin();121      std::same_as<const char&> decltype(auto) v_ref = *it;122      assert(v_ref == '1');123      std::ranges::advance(it, 3);124      std::same_as<const char&> decltype(auto) pattern_ref = *std::as_const(it);125      assert(pattern_ref == '.');126    }127 128    {129      auto cit                                        = std::as_const(jwv).begin();130      std::same_as<const char&> decltype(auto) cv_ref = *std::as_const(cit);131      assert(cv_ref == '1');132      std::ranges::advance(cit, 4);133      std::same_as<const char&> decltype(auto) cpattern_ref = *cit;134      assert(cpattern_ref == '_');135    }136  }137 138  { // Result of `operator*` is prvalue139    using V       = std::vector<std::string_view>;140    using Pattern = RvalueVector<char>;141    using JWV     = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>;142 143    JWV jwv(V{"x^2", "y^2", "z^2"}, Pattern{{' ', '+', ' '}});144 145    {146      auto it                                 = jwv.begin();147      std::same_as<char> decltype(auto) v_ref = *std::as_const(it);148      assert(v_ref == 'x');149      std::ranges::advance(it, 3);150      std::same_as<char> decltype(auto) pattern_ref = *it;151      assert(pattern_ref == ' ');152    }153 154    {155      auto cit                                 = std::as_const(jwv).begin();156      std::same_as<char> decltype(auto) cv_ref = *cit;157      assert(cv_ref == 'x');158      std::ranges::advance(cit, 4);159      std::same_as<char> decltype(auto) cpattern_ref = *std::as_const(cit);160      assert(cpattern_ref == '+');161    }162  }163 164  { // Result of `operator*` is (maybe const) rvalue reference165    using Inner   = std::ranges::as_rvalue_view<std::ranges::owning_view<std::string>>;166    using V       = std::ranges::owning_view<std::vector<Inner>>;167    using Pattern = std::ranges::as_rvalue_view<std::ranges::owning_view<std::array<char, 2>>>;168    using JWV     = std::ranges::join_with_view<V, Pattern>;169 170    std::vector<Inner> vec;171    vec.emplace_back(Inner{{"x*y"}});172    vec.emplace_back(Inner{{"y*z"}});173    vec.emplace_back(Inner{{"z*x"}});174    JWV jwv(V(std::move(vec)), Pattern(std::array{',', ' '}));175 176    {177      auto it                                   = jwv.begin();178      std::same_as<char&&> decltype(auto) v_ref = *it;179      assert(v_ref == 'x');180      std::ranges::advance(it, 3);181      std::same_as<char&&> decltype(auto) pattern_ref = *std::as_const(it);182      assert(pattern_ref == ',');183    }184 185    {186      auto cit                                         = std::as_const(jwv).begin();187      std::same_as<const char&&> decltype(auto) cv_ref = *std::as_const(cit);188      assert(cv_ref == 'x');189      std::ranges::advance(cit, 4);190      std::same_as<const char&&> decltype(auto) cpattern_ref = *cit;191      assert(cpattern_ref == ' ');192    }193  }194 195  { // Result of `operator*` is type different from range_reference_t<InnerRng> and range_reference_t<Pattern>196    using Inner   = std::vector<int>;197    using V       = std::vector<Inner>;198    using Pattern = std::ranges::subrange<ProxyIter, ProxyIter>;199    using JWV     = std::ranges::join_with_view<std::ranges::owning_view<V>, Pattern>;200 201    static_assert(!std::same_as<std::ranges::range_reference_t<V>, std::ranges::range_reference_t<JWV>>);202    static_assert(!std::same_as<std::ranges::range_reference_t<Pattern>, std::ranges::range_reference_t<JWV>>);203 204    std::array<int, 2> pattern = {-1, -1};205    Pattern pattern_as_subrange(ProxyIter{pattern.data()}, ProxyIter{pattern.data() + pattern.size()});206 207    JWV jwv(V{Inner{1, 1}, Inner{2, 2}, Inner{3, 3}}, pattern_as_subrange);208 209    auto it                                           = jwv.begin();210    std::same_as<CommonProxyRef> decltype(auto) v_ref = *it;211    assert(v_ref.get() == 1);212    std::ranges::advance(it, 7);213    std::same_as<CommonProxyRef> decltype(auto) pattern_ref = *std::as_const(it);214    assert(pattern_ref.get() == -1);215  }216 217  return true;218}219 220int main(int, char**) {221  test();222  static_assert(test());223 224  return 0;225}226