FE 0.13.1
Header-only C++ frontend library
Loading...
Searching...
No Matches
vector.h
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <functional>
5#include <memory>
6#include <ranges>
7#include <type_traits>
8
9#ifdef FE_ABSL
10# include <absl/container/inlined_vector.h>
11#else
12# include <vector>
13#endif
14
15#include "fe/span.h"
16
17namespace fe {
18
19/// Use up to 4 words (i.e., 4 * sizeof(size_t)) of inlined storage, rounded up.
20template<class T>
21static constexpr size_t Default_Inlined_Size = std::max((size_t)1, 4 * sizeof(size_t) / sizeof(T));
22
23namespace detail {
24#ifdef FE_ABSL
25template<class T, size_t N, class A>
26using VectorBase = absl::InlinedVector<T, N, A>;
27#else
28template<class T, size_t, class A>
29using VectorBase = std::vector<T, A>;
30#endif
31} // namespace detail
32
33/// This is a thin wrapper for
34/// [`absl::InlinedVector<T, N, A>`](https://github.com/abseil/abseil-cpp/blob/master/absl/container/inlined_vector.h)
35/// which is a drop-in replacement for [`std::vector<T, A>`](https://en.cppreference.com/w/cpp/container/vector).
36/// In addition, there are generator-like/lambda-based constructors and conversions to Span available.
37/// @note Without `FE_ABSL` this falls back to `std::vector<T, A>` and @p N has no effect.
38template<class T, size_t N = Default_Inlined_Size<T>, class A = std::allocator<T>>
39class Vector : public detail::VectorBase<T, N, A> {
40public:
41 using Base = detail::VectorBase<T, N, A>;
42
43 using Base::insert;
44
45 /// @name Constructors
46 ///@{
47 using Base::Base;
48 template<class F>
49 constexpr explicit Vector(size_t size, F&& f) noexcept(
50 std::is_nothrow_invocable_r_v<T, F, size_t>&& std::is_nothrow_assignable_v<T&, T>)
51 requires(std::is_invocable_r_v<T, F, size_t>)
52 : Base(size) {
53 for (size_t i = 0; i != size; ++i)
54 (*this)[i] = std::invoke(f, i);
55 }
56
57 template<std::ranges::forward_range R, class F>
58 constexpr explicit Vector(R&& range, F&& f) noexcept(
59 std::is_nothrow_invocable_r_v<T, F, decltype(*std::ranges::begin(range))>&& std::is_nothrow_assignable_v<T&, T>)
60 requires(std::is_invocable_r_v<T, F, decltype(*std::ranges::begin(range))>
61 && !std::is_same_v<std::decay_t<R>, Vector>)
62 : Base(std::ranges::distance(range)) {
63 auto ri = std::ranges::begin(range);
64 for (auto& elem : *this)
65 elem = std::invoke(f, *ri++);
66 }
67 ///@}
68
69 /// @name insert_range / append_range
70 /// Available in C++23 but not absl.
71 ///@{
72 template<std::ranges::forward_range R>
73 constexpr void insert_range(Base::const_iterator pos, R&& r) {
74 insert(pos, r.begin(), r.end());
75 }
76 template<std::ranges::forward_range R>
77 constexpr void append_range(R&& r) {
78 insert_range(Base::end(), r);
79 }
80 ///@}
81
82 /// @name Span
83 ///@{
84 constexpr auto span() noexcept { return Span{Base::data(), Base::size()}; }
85 constexpr auto span() const noexcept { return Span{Base::data(), Base::size()}; }
86 constexpr auto view() const noexcept { return span(); }
87 ///@}
88
89 friend void swap(Vector& v1, Vector& v2) noexcept(noexcept(v1.swap(v2))) { v1.swap(v2); }
90};
91
92static_assert(std::ranges::contiguous_range<Vector<int>>);
93
94/// @name Deduction Guides
95///@{
96template<class I, class A = std::allocator<typename std::iterator_traits<I>::value_type>>
99 A>;
100///@}
101
102/// @name erase
103///@{
104template<class T, size_t N, class A, class U>
106 auto it = std::remove(c.begin(), c.end(), value);
107 auto r = c.end() - it;
108 c.erase(it, c.end());
109 return r;
110}
111
112template<class T, size_t N, class A, class Pred>
114 auto it = std::remove_if(c.begin(), c.end(), pred);
115 auto r = c.end() - it;
116 c.erase(it, c.end());
117 return r;
118}
119///@}
120
121} // namespace fe
This is a thin wrapper for std::span<T, N> with the following additional features:
Definition span.h:33
This is a thin wrapper for absl::InlinedVector<T, N, A> which is a drop-in replacement for std::vecto...
Definition vector.h:39
constexpr auto span() const noexcept
Definition vector.h:85
constexpr Vector(R &&range, F &&f) noexcept(std::is_nothrow_invocable_r_v< T, F, decltype(*std::ranges::begin(range))> &&std::is_nothrow_assignable_v< T &, T >)
Definition vector.h:58
constexpr auto view() const noexcept
Definition vector.h:86
constexpr void append_range(R &&r)
Definition vector.h:77
constexpr Vector(size_t size, F &&f) noexcept(std::is_nothrow_invocable_r_v< T, F, size_t > &&std::is_nothrow_assignable_v< T &, T >)
Definition vector.h:49
constexpr void insert_range(Base::const_iterator pos, R &&r)
Definition vector.h:73
friend void swap(Vector &v1, Vector &v2) noexcept(noexcept(v1.swap(v2)))
Definition vector.h:89
detail::VectorBase< T, N, A > Base
Definition vector.h:41
constexpr auto span() noexcept
Definition vector.h:84
Definition algo.h:17
Vector< T, N, A >::size_type erase(Vector< T, N, A > &c, const U &value)
Definition vector.h:105
static constexpr size_t Default_Inlined_Size
Use up to 4 words (i.e., 4 * sizeof(size_t)) of inlined storage, rounded up.
Definition vector.h:21
Vector< T, N, A >::size_type erase_if(Vector< T, N, A > &c, Pred pred)
Definition vector.h:113