tuple_vector.hpp
Go to the documentation of this file.
1 // Copyright 2022-2024 Ekumen, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef BELUGA_CONTAINERS_TUPLE_VECTOR_HPP
16 #define BELUGA_CONTAINERS_TUPLE_VECTOR_HPP
17 
18 #include <tuple>
19 #include <vector>
20 
21 #include <beluga/type_traits.hpp>
22 #include <beluga/views/zip.hpp>
23 #include <range/v3/algorithm/copy.hpp>
24 #include <range/v3/iterator/insert_iterators.hpp>
25 #include <range/v3/view/const.hpp>
26 #include <range/v3/view/take.hpp>
27 
33 namespace beluga {
34 
36 template <template <class> class InternalContainer, class T>
38 
40 
49 template <template <class> class InternalContainer, class... Types>
50 class TupleContainer<InternalContainer, std::tuple<Types...>> {
51  public:
53  using value_type = std::tuple<Types...>;
54 
56  using reference_type = ranges::common_tuple<Types&...>;
57 
59  using size_type = std::size_t;
60 
62  using difference_type = std::ptrdiff_t;
63 
65 
70  using allocator_type = void;
71 
73  constexpr TupleContainer() = default;
74 
76 
79  explicit constexpr TupleContainer(size_type count) : sequences_{((void)sizeof(Types), count)...} {}
80 
82  template <typename I, typename S>
83  constexpr TupleContainer(I first, S last) {
84  assign(first, last);
85  }
86 
88  constexpr TupleContainer(std::initializer_list<value_type> init) { assign(init.begin(), init.end()); }
89 
91  [[nodiscard]] constexpr bool empty() const noexcept { return std::get<0>(sequences_).empty(); }
92 
94  [[nodiscard]] constexpr size_type size() const noexcept { return std::get<0>(sequences_).size(); }
95 
97  [[nodiscard]] constexpr size_type capacity() const noexcept { return std::get<0>(sequences_).capacity(); }
98 
100  constexpr void clear() noexcept {
101  std::apply([](auto&&... containers) { (containers.clear(), ...); }, sequences_);
102  }
103 
105 
108  template <typename I, typename S>
109  constexpr void assign(I first, S last) {
110  auto range = ranges::make_subrange(first, last);
111  static_assert(ranges::input_range<decltype(range)>);
112  if constexpr (ranges::sized_range<decltype(range)>) {
113  resize(ranges::size(range));
114  ranges::copy(range, begin());
115  } else {
116  // Optimization to copy as much as we can before we start back inserting.
117  // Back insertion time is severely punished by having multiple containers.
118  //
119  // There are two bad cases for this implementation:
120  // - The capacity is too large compared to the size of the input range, so
121  // we allocate and default construct unnecessarily.
122  // - The capacity is too low compared to the size of the input range, so
123  // there will be a lot of back inserting.
124  //
125  // If common guidelines of calling reserve with the expected size are followed,
126  // then this is quite fast, even when we don't know the exact size of the range
127  // in advance.
128  resize(capacity());
129  // Copy elements until we reach current capacity.
130  auto limited_range = range | ranges::views::take(size());
131  auto [last_in, last_out] = ranges::copy(limited_range, begin());
132  const auto copied_size = static_cast<size_type>(ranges::distance(begin(), last_out));
133  if (size() == copied_size) {
134  // Back insert the remaining elements if any.
135  ranges::copy(last_in.base(), last, ranges::back_inserter(*this));
136  } else {
137  // Remove extra elements by resizing to the correct size.
138  resize(copied_size);
139  }
140  }
141  }
142 
144  template <typename R>
145  constexpr void assign_range(R&& range) {
146  assign(ranges::begin(range), ranges::end(range));
147  }
148 
150 
156  constexpr void reserve(size_type new_cap) {
157  std::apply([new_cap](auto&&... containers) { (containers.reserve(new_cap), ...); }, sequences_);
158  }
159 
161 
168  constexpr void resize(size_type count) {
169  std::apply([count](auto&&... containers) { (containers.resize(count), ...); }, sequences_);
170  }
171 
173 
176  constexpr void push_back(const value_type& value) {
177  push_back_impl(value, std::make_index_sequence<sizeof...(Types)>());
178  }
179 
181  constexpr void push_back(value_type&& value) {
182  push_back_impl(std::move(value), std::make_index_sequence<sizeof...(Types)>());
183  }
184 
186  [[nodiscard]] constexpr auto begin() const { return all().begin(); }
187 
189  [[nodiscard]] constexpr auto end() const { return all().end(); }
190 
192  [[nodiscard]] constexpr auto begin() { return all().begin(); }
193 
195  [[nodiscard]] constexpr auto end() { return all().end(); }
196 
197  private:
198  std::tuple<InternalContainer<Types>...> sequences_;
199 
200  template <typename T, std::size_t... Ids>
201  constexpr void push_back_impl(T value, std::index_sequence<Ids...>) {
202  (std::get<Ids>(sequences_).push_back(std::get<Ids>(value)), ...);
203  }
204 
205  [[nodiscard]] constexpr auto all() const {
206  return std::apply([](auto&... containers) { return beluga::views::zip(containers...); }, sequences_);
207  }
208 
209  [[nodiscard]] constexpr auto all() {
210  return std::apply([](auto&... containers) { return beluga::views::zip(containers...); }, sequences_);
211  }
212 };
213 
215 template <class T>
216 using Vector = std::vector<T, std::allocator<T>>;
217 
219 
222 template <class T>
223 class TupleVector : public TupleContainer<Vector, T> {
226 };
227 
229 template <class I, class S, typename = std::enable_if_t<ranges::input_iterator<I> && ranges::input_iterator<S>>>
231 
232 } // namespace beluga
233 
234 #endif
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::assign
constexpr void assign(I first, S last)
Replaces elements in the container with copies of those in the range [first, last).
Definition: tuple_vector.hpp:109
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::all
constexpr auto all()
Definition: tuple_vector.hpp:209
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::push_back
constexpr void push_back(value_type &&value)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tuple_vector.hpp:181
zip.hpp
Implementation of a zip range adaptor object.
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::all
constexpr auto all() const
Definition: tuple_vector.hpp:205
type_traits.hpp
Includes all Beluga type traits.
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::end
constexpr auto end() const
Returns an iterator to the last element of the container.
Definition: tuple_vector.hpp:189
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::empty
constexpr bool empty() const noexcept
Returns true if the container is empty.
Definition: tuple_vector.hpp:91
beluga::Vector
std::vector< T, std::allocator< T > > Vector
Shorthand for a vector with the default allocator.
Definition: tuple_vector.hpp:216
beluga::actions::assign
constexpr detail::assign_fn assign
Definition: assign.hpp:99
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::reference_type
ranges::common_tuple< Types &... > reference_type
Reference type of the container.
Definition: tuple_vector.hpp:56
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::size
constexpr size_type size() const noexcept
Returns the size of the container.
Definition: tuple_vector.hpp:94
beluga::TupleContainer
Primary template for a tuple of containers.
Definition: tuple_vector.hpp:37
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::TupleContainer
constexpr TupleContainer(std::initializer_list< value_type > init)
Constructs a container from an initializer_list.
Definition: tuple_vector.hpp:88
beluga::TupleVector
Shorthand for a tuple of vectors with the default allocator.
Definition: tuple_vector.hpp:223
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::TupleContainer
constexpr TupleContainer(I first, S last)
Constructs a container from iterators.
Definition: tuple_vector.hpp:83
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::resize
constexpr void resize(size_type count)
Resizes the container.
Definition: tuple_vector.hpp:168
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::capacity
constexpr size_type capacity() const noexcept
Returns the capacity of the container.
Definition: tuple_vector.hpp:97
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::clear
constexpr void clear() noexcept
Clears the container.
Definition: tuple_vector.hpp:100
beluga::TupleVector
TupleVector(I, S) -> TupleVector< decay_tuple_like_t< ranges::iter_value_t< I >>>
Deduction guide to construct from iterators.
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::begin
constexpr auto begin()
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tuple_vector.hpp:192
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::TupleContainer
constexpr TupleContainer(size_type count)
Constructs a container of size count, all values are default initialized.
Definition: tuple_vector.hpp:79
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::reserve
constexpr void reserve(size_type new_cap)
Reserves the specified capacity.
Definition: tuple_vector.hpp:156
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::push_back_impl
constexpr void push_back_impl(T value, std::index_sequence< Ids... >)
Definition: tuple_vector.hpp:201
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::allocator_type
void allocator_type
Allocator type.
Definition: tuple_vector.hpp:70
std
Definition: circular_array.hpp:529
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::begin
constexpr auto begin() const
Returns an iterator to the first element of the container.
Definition: tuple_vector.hpp:186
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::difference_type
std::ptrdiff_t difference_type
Difference type of the container.
Definition: tuple_vector.hpp:62
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::size_type
std::size_t size_type
Size type of the container.
Definition: tuple_vector.hpp:59
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::sequences_
std::tuple< InternalContainer< Types >... > sequences_
Definition: tuple_vector.hpp:198
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::push_back
constexpr void push_back(const value_type &value)
Adds an element at the end of the container.
Definition: tuple_vector.hpp:176
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::end
constexpr auto end()
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tuple_vector.hpp:195
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::assign_range
constexpr void assign_range(R &&range)
Replaces elements in the container with a copy of each element in range.
Definition: tuple_vector.hpp:145
beluga::views::zip
constexpr detail::zip_fn zip
Given N ranges, return a new range where the Mth element is a tuple of the Mth elements of all N rang...
Definition: zip.hpp:74
beluga::TupleContainer< InternalContainer, std::tuple< Types... > >::value_type
std::tuple< Types... > value_type
Value type of the container.
Definition: tuple_vector.hpp:53
beluga
The main Beluga namespace.
Definition: 3d_embedding.hpp:21


beluga
Author(s):
autogenerated on Tue Jul 16 2024 02:59:53