brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.1 KiB · 4fd5268 Raw
167 lines · c
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#ifndef RANGES_RANGE_UTILITY_RANGE_UTILITY_CONV_CONTAINER_H10#define RANGES_RANGE_UTILITY_RANGE_UTILITY_CONV_CONTAINER_H11 12#include <algorithm>13#include <cstddef>14 15enum class CtrChoice { Invalid, DefaultCtrAndInsert, BeginEndPair, FromRangeT, DirectCtr };16 17enum class InserterChoice { Invalid, Insert, Emplace, PushBack, EmplaceBack };18 19// Allows checking that `ranges::to` correctly follows the order of priority of different constructors -- e.g., if20// 3 constructors are available, the `from_range_t` constructor is chosen in favor of the constructor taking two21// iterators, etc.22template <class ElementType, CtrChoice Rank, InserterChoice Inserter = InserterChoice::Insert, bool CanReserve = false>23struct Container {24  CtrChoice ctr_choice           = CtrChoice::Invalid;25  InserterChoice inserter_choice = InserterChoice::Invalid;26  bool called_reserve            = false;27 28  int extra_arg1  = 0;29  char extra_arg2 = 0;30 31  using value_type              = ElementType;32  static constexpr int Capacity = 8;33  int size_                     = 0;34  ElementType buffer_[Capacity] = {};35 36  // Case 1 -- construct directly from the range.37 38  constexpr explicit Container(std::ranges::input_range auto&& in)39    requires(Rank >= CtrChoice::DirectCtr)40      : ctr_choice(CtrChoice::DirectCtr), size_(static_cast<int>(std::ranges::size(in))) {41    std::ranges::copy(in, begin());42  }43 44  // Check that `ranges::to` can also pass extra parameters.45  constexpr explicit Container(std::ranges::input_range auto&& in, int arg1, char arg2)46    requires(Rank >= CtrChoice::DirectCtr)47      : Container(in) {48    extra_arg1 = arg1;49    extra_arg2 = arg2;50  }51 52  // Case 2 -- use `from_range_t` constructor.53 54  constexpr Container(std::from_range_t, std::ranges::input_range auto&& in)55    requires(Rank >= CtrChoice::FromRangeT)56      : ctr_choice(CtrChoice::FromRangeT), size_(static_cast<int>(std::ranges::size(in))) {57    std::ranges::copy(in, begin());58  }59 60  constexpr Container(std::from_range_t, std::ranges::input_range auto&& in, int arg1, char arg2)61    requires(Rank >= CtrChoice::FromRangeT)62      : Container(std::from_range, in) {63    extra_arg1 = arg1;64    extra_arg2 = arg2;65  }66 67  // Case 3 -- use begin-end pair.68 69  template <class Iter>70  constexpr Container(Iter b, Iter e)71    requires(Rank >= CtrChoice::BeginEndPair)72      : ctr_choice(CtrChoice::BeginEndPair), size_(static_cast<int>(e - b)) {73    std::ranges::copy(b, e, begin());74  }75 76  template <class Iter>77  constexpr Container(Iter b, Iter e, int arg1, char arg2)78    requires(Rank >= CtrChoice::BeginEndPair)79      : Container(b, e) {80    extra_arg1 = arg1;81    extra_arg2 = arg2;82  }83 84  // Case 4 -- default-construct and insert, reserving the size if possible.85 86  constexpr Container()87    requires(Rank >= CtrChoice::DefaultCtrAndInsert)88      : ctr_choice(CtrChoice::DefaultCtrAndInsert) {}89 90  constexpr Container(int arg1, char arg2)91    requires(Rank >= CtrChoice::DefaultCtrAndInsert)92      : ctr_choice(CtrChoice::DefaultCtrAndInsert), extra_arg1(arg1), extra_arg2(arg2) {}93 94  constexpr ElementType* begin() { return buffer_; }95  constexpr ElementType* end() { return buffer_ + size_; }96  constexpr std::size_t size() const { return size_; }97 98  template <class T>99  constexpr void emplace_back(T val)100    requires(Inserter >= InserterChoice::EmplaceBack)101  {102    inserter_choice = InserterChoice::EmplaceBack;103    __push_back_impl(val);104  }105 106  template <class T>107  constexpr void push_back(T val)108    requires(Inserter >= InserterChoice::PushBack)109  {110    inserter_choice = InserterChoice::PushBack;111    __push_back_impl(val);112  }113 114  template <class T>115  constexpr void __push_back_impl(T val) {116    buffer_[size_] = val;117    ++size_;118  }119 120  template <class T>121  constexpr ElementType* emplace(ElementType* where, T val)122    requires(Inserter >= InserterChoice::Emplace)123  {124    inserter_choice = InserterChoice::Emplace;125    return __insert_impl(where, val);126  }127 128  template <class T>129  constexpr ElementType* insert(ElementType* where, T val)130    requires(Inserter >= InserterChoice::Insert)131  {132    inserter_choice = InserterChoice::Insert;133    return __insert_impl(where, val);134  }135 136  template <class T>137  constexpr ElementType* __insert_impl(ElementType* where, T val) {138    assert(size() + 1 <= Capacity);139    std::shift_right(where, end(), 1);140    *where = val;141    ++size_;142    return where;143  }144 145  constexpr void reserve(size_t)146    requires CanReserve147  {148    called_reserve = true;149  }150 151  constexpr std::size_t capacity() const152    requires CanReserve153  {154    return Capacity;155  }156 157  constexpr std::size_t max_size() const158    requires CanReserve159  {160    return Capacity;161  }162 163  friend constexpr bool operator==(const Container&, const Container&) = default;164};165 166#endif // RANGES_RANGE_UTILITY_RANGE_UTILITY_CONV_CONTAINER_H167