brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.2 KiB · 4e79b0f Raw
133 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 View base() const& requires copy_constructible<View>;14// constexpr View base() &&;15 16#include <ranges>17 18#include <cassert>19#include <utility>20#include <vector>21 22using InnerRange = std::vector<int>;23 24struct Range : std::ranges::view_base {25  constexpr explicit Range(InnerRange* b, InnerRange* e) : begin_(b), end_(e) {}26  constexpr Range(const Range& other) : begin_(other.begin_), end_(other.end_), was_copy_initialized_(true) {}27  constexpr Range(Range&& other) : begin_(other.begin_), end_(other.end_), was_move_initialized_(true) {}28  Range& operator=(const Range&) = default;29  Range& operator=(Range&&)      = default;30  constexpr InnerRange* begin() const { return begin_; }31  constexpr InnerRange* end() const { return end_; }32 33  InnerRange* begin_;34  InnerRange* end_;35  bool was_copy_initialized_ = false;36  bool was_move_initialized_ = false;37};38 39static_assert(std::ranges::view<Range>);40static_assert(std::ranges::input_range<Range>);41 42struct Pattern : std::ranges::view_base {43  static constexpr int pat[2] = {0, 0};44  constexpr const int* begin() const { return pat; }45  constexpr const int* end() const { return pat + 2; }46};47 48static_assert(std::ranges::view<Pattern>);49static_assert(std::ranges::forward_range<Pattern>);50 51template <class Tp>52struct NonCopyableRange : std::ranges::view_base {53  NonCopyableRange(const NonCopyableRange&)            = delete;54  NonCopyableRange(NonCopyableRange&&)                 = default;55  NonCopyableRange& operator=(const NonCopyableRange&) = default;56  NonCopyableRange& operator=(NonCopyableRange&&)      = default;57  Tp* begin() const;58  Tp* end() const;59};60 61static_assert(!std::copy_constructible<NonCopyableRange<InnerRange>>);62static_assert(!std::copy_constructible<NonCopyableRange<int>>);63 64template <typename T>65concept CanCallBaseOn = requires(T&& t) { std::forward<T>(t).base(); };66 67constexpr bool test() {68  InnerRange buff[3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};69  Pattern pattern;70 71  { // Check the const& overload72    Range range(buff, buff + 3);73    std::ranges::join_with_view<Range, Pattern> view(range, pattern);74    std::same_as<Range> decltype(auto) result = view.base();75    assert(result.was_copy_initialized_);76    assert(result.begin() == buff);77    assert(result.end() == buff + 3);78  }79 80  { // Check the const& overload on const `view`81    Range range(buff, buff + 3);82    const std::ranges::join_with_view<Range, Pattern> view(range, pattern);83    std::same_as<Range> decltype(auto) result = view.base();84    assert(result.was_copy_initialized_);85    assert(result.begin() == buff);86    assert(result.end() == buff + 3);87  }88 89  { // Check the && overload90    Range range(buff, buff + 3);91    std::ranges::join_with_view<Range, Pattern> view(range, pattern);92    std::same_as<Range> decltype(auto) result = std::move(view).base();93    assert(result.was_move_initialized_);94    assert(result.begin() == buff);95    assert(result.end() == buff + 3);96  }97 98  { // Ensure the const& overload is not considered when the base is not copy-constructible99    static_assert(!CanCallBaseOn<const std::ranges::join_with_view<NonCopyableRange<InnerRange>, Pattern>&>);100    static_assert(!CanCallBaseOn<std::ranges::join_with_view<NonCopyableRange<InnerRange>, Pattern>&>);101    static_assert(!CanCallBaseOn<const std::ranges::join_with_view<NonCopyableRange<InnerRange>, Pattern>&&>);102    static_assert(CanCallBaseOn<std::ranges::join_with_view<NonCopyableRange<InnerRange>, Pattern>&&>);103    static_assert(CanCallBaseOn<std::ranges::join_with_view<NonCopyableRange<InnerRange>, Pattern>>);104  }105 106  { // Ensure the const& overload does not depend on Pattern's copy-constructability107    static_assert(CanCallBaseOn<const std::ranges::join_with_view<Range, NonCopyableRange<int>>&>);108    static_assert(CanCallBaseOn<std::ranges::join_with_view<Range, NonCopyableRange<int>>&>);109    static_assert(CanCallBaseOn<const std::ranges::join_with_view<Range, NonCopyableRange<int>>&&>);110    static_assert(CanCallBaseOn<std::ranges::join_with_view<Range, NonCopyableRange<int>>&&>);111    static_assert(CanCallBaseOn<std::ranges::join_with_view<Range, NonCopyableRange<int>>>);112  }113 114  { // Check above two at the same time115    static_assert(116        !CanCallBaseOn<const std::ranges::join_with_view<NonCopyableRange<InnerRange>, NonCopyableRange<int>>&>);117    static_assert(!CanCallBaseOn<std::ranges::join_with_view<NonCopyableRange<InnerRange>, NonCopyableRange<int>>&>);118    static_assert(119        !CanCallBaseOn<const std::ranges::join_with_view< NonCopyableRange<InnerRange>, NonCopyableRange<int>>&&>);120    static_assert(CanCallBaseOn<std::ranges::join_with_view<NonCopyableRange<InnerRange>, NonCopyableRange<int>>&&>);121    static_assert(CanCallBaseOn<std::ranges::join_with_view<NonCopyableRange<InnerRange>, NonCopyableRange<int>>>);122  }123 124  return true;125}126 127int main(int, char**) {128  test();129  static_assert(test());130 131  return 0;132}133