File: container.h

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 1,998,492 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (144 lines) | stat: -rw-r--r-- 4,531 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
142
143
144
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef RANGES_RANGE_UTILITY_RANGE_UTILITY_CONV_CONTAINER_H
#define RANGES_RANGE_UTILITY_RANGE_UTILITY_CONV_CONTAINER_H

#include <algorithm>
#include <concepts>
#include <cstddef>

enum class CtrChoice { Invalid, DefaultCtrAndInsert, BeginEndPair, FromRangeT, DirectCtr };

enum class InserterChoice { Invalid, Insert, PushBack };

// Allows checking that `ranges::to` correctly follows the order of priority of different constructors -- e.g., if
// 3 constructors are available, the `from_range_t` constructor is chosen in favor of the constructor taking two
// iterators, etc.
template <class ElementType, CtrChoice Rank, InserterChoice Inserter = InserterChoice::Insert, bool CanReserve = false>
struct Container {
  CtrChoice ctr_choice           = CtrChoice::Invalid;
  InserterChoice inserter_choice = InserterChoice::Invalid;
  bool called_reserve            = false;

  int extra_arg1  = 0;
  char extra_arg2 = 0;

  using value_type              = ElementType;
  static constexpr int Capacity = 8;
  int size_                     = 0;
  ElementType buffer_[Capacity] = {};

  // Case 1 -- construct directly from the range.

  constexpr explicit Container(std::ranges::input_range auto&& in)
    requires(Rank >= CtrChoice::DirectCtr)
      : ctr_choice(CtrChoice::DirectCtr), size_(static_cast<int>(std::ranges::size(in))) {
    std::ranges::copy(in, begin());
  }

  // Check that `ranges::to` can also pass extra parameters.
  constexpr explicit Container(std::ranges::input_range auto&& in, int arg1, char arg2)
    requires(Rank >= CtrChoice::DirectCtr)
      : Container(in) {
    extra_arg1 = arg1;
    extra_arg2 = arg2;
  }

  // Case 2 -- use `from_range_t` constructor.

  constexpr Container(std::from_range_t, std::ranges::input_range auto&& in)
    requires(Rank >= CtrChoice::FromRangeT)
      : ctr_choice(CtrChoice::FromRangeT), size_(static_cast<int>(std::ranges::size(in))) {
    std::ranges::copy(in, begin());
  }

  constexpr Container(std::from_range_t, std::ranges::input_range auto&& in, int arg1, char arg2)
    requires(Rank >= CtrChoice::FromRangeT)
      : Container(std::from_range, in) {
    extra_arg1 = arg1;
    extra_arg2 = arg2;
  }

  // Case 3 -- use begin-end pair.

  template <class Iter>
  constexpr Container(Iter b, Iter e)
    requires(Rank >= CtrChoice::BeginEndPair)
      : ctr_choice(CtrChoice::BeginEndPair), size_(static_cast<int>(e - b)) {
    std::ranges::copy(b, e, begin());
  }

  template <class Iter>
  constexpr Container(Iter b, Iter e, int arg1, char arg2)
    requires(Rank >= CtrChoice::BeginEndPair)
      : Container(b, e) {
    extra_arg1 = arg1;
    extra_arg2 = arg2;
  }

  // Case 4 -- default-construct and insert, reserving the size if possible.

  constexpr Container()
    requires(Rank >= CtrChoice::DefaultCtrAndInsert)
      : ctr_choice(CtrChoice::DefaultCtrAndInsert) {}

  constexpr Container(int arg1, char arg2)
    requires(Rank >= CtrChoice::DefaultCtrAndInsert)
      : ctr_choice(CtrChoice::DefaultCtrAndInsert), extra_arg1(arg1), extra_arg2(arg2) {}

  constexpr ElementType* begin() { return buffer_; }
  constexpr ElementType* end() { return buffer_ + size_; }
  constexpr std::size_t size() const { return size_; }

  template <class T>
  constexpr void push_back(T val)
    requires(Inserter >= InserterChoice::PushBack)
  {
    inserter_choice = InserterChoice::PushBack;
    buffer_[size_]  = val;
    ++size_;
  }

  template <class T>
  constexpr ElementType* insert(ElementType* where, T val)
    requires(Inserter >= InserterChoice::Insert)
  {
    assert(size() + 1 <= Capacity);

    inserter_choice = InserterChoice::Insert;

    std::shift_right(where, end(), 1);
    *where = val;
    ++size_;

    return where;
  }

  constexpr void reserve(size_t)
    requires CanReserve
  {
    called_reserve = true;
  }

  constexpr std::size_t capacity() const
    requires CanReserve
  {
    return Capacity;
  }

  constexpr std::size_t max_size() const
    requires CanReserve
  {
    return Capacity;
  }

  friend constexpr bool operator==(const Container&, const Container&) = default;
};

#endif // RANGES_RANGE_UTILITY_RANGE_UTILITY_CONV_CONTAINER_H