-
Notifications
You must be signed in to change notification settings - Fork 64
/
Copy pathCSmallVector.h
167 lines (147 loc) · 5.83 KB
/
CSmallVector.h
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the following additional limitation. Functionality enabled by the
* files subject to the Elastic License 2.0 may only be used in production when
* invoked by an Elasticsearch process with a license key installed that permits
* use of machine learning features. You may not use this file except in
* compliance with the Elastic License 2.0 and the foregoing additional
* limitation.
*/
#ifndef INCLUDED_ml_core_CSmallVector_h
#define INCLUDED_ml_core_CSmallVector_h
#include <core/CSmallVectorFwd.h>
#include <boost/container/small_vector.hpp>
#include <initializer_list>
#include <ostream>
#include <type_traits>
#include <vector>
namespace ml {
namespace core {
namespace small_vector_detail {
inline std::size_t min(std::size_t a, std::size_t b) {
return a < b ? a : b;
}
template<typename T, typename = void>
struct SPlusAssign {
static_assert(sizeof(T) < 0, "The contained type has no defined += operator");
};
template<typename T>
struct SPlusAssign<T, std::void_t<decltype(std::declval<T&>() += std::declval<T>())>> {
static void compute(CSmallVectorBase<T>& lhs, const CSmallVectorBase<T>& rhs) {
for (std::size_t i = 0, n = min(lhs.size(), rhs.size()); i < n; ++i) {
lhs[i] += rhs[i];
}
}
};
template<typename T, typename = void>
struct SMinusAssign {
static_assert(sizeof(T) < 0, "The contained type has no defined -= operator");
};
template<typename T>
struct SMinusAssign<T, std::void_t<decltype(std::declval<T&>() -= std::declval<T>())>> {
static void compute(CSmallVectorBase<T>& lhs, const CSmallVectorBase<T>& rhs) {
for (std::size_t i = 0, n = min(lhs.size(), rhs.size()); i < n; ++i) {
lhs[i] -= rhs[i];
}
}
};
}
//! \brief This inherits from boost::container::small_vector.
//!
//! DESCRIPTION:\n
//! The reasons for this class are largely historical in that we didn't have
//! boost::container::small_vector in the version of boost we were using when
//! this was originally implemented. However, a lot of our code now uses this
//! class and it is convenient to provide some non-standard extensions.
//!
//! IMPLEMENTATION DECISIONS:\n
//! Inherits from boost::container::small_vector.
//!
//! \tparam T The element type.
//! \tparam N The maximum number of elements which are stored on the stack.
template<typename T, std::size_t N>
class CSmallVector : public boost::container::small_vector<T, N> {
private:
using TBase = boost::container::small_vector<T, N>;
public:
// Forward typedefs
using value_type = typename TBase::value_type;
using allocator_type = typename TBase::allocator_type;
using reference = typename TBase::reference;
using const_reference = typename TBase::const_reference;
using pointer = typename TBase::pointer;
using const_pointer = typename TBase::const_pointer;
using difference_type = typename TBase::difference_type;
using size_type = typename TBase::size_type;
using iterator = typename TBase::iterator;
using const_iterator = typename TBase::const_iterator;
using reverse_iterator = typename TBase::reverse_iterator;
using const_reverse_iterator = typename TBase::const_reverse_iterator;
public:
//! \name Constructors
//@{
CSmallVector() {}
CSmallVector(const CSmallVector& other) : TBase(other) {}
CSmallVector(CSmallVector&& other) noexcept(std::is_nothrow_move_constructible<TBase>::value)
: TBase(std::move(other.baseRef())) {}
explicit CSmallVector(size_type n, const value_type& val = value_type())
: TBase(n, val) {}
CSmallVector(std::initializer_list<value_type> list)
: TBase(list.begin(), list.end()) {}
template<class ITR>
CSmallVector(ITR first, ITR last) : TBase(first, last) {}
template<typename U, std::size_t M>
CSmallVector(const CSmallVector<U, M>& other)
: TBase(other.begin(), other.end()) {}
template<typename U>
CSmallVector(std::initializer_list<U> list)
: TBase(list.begin(), list.end()) {}
// Extend to construct implicitly from a vector.
template<typename U>
CSmallVector(const std::vector<U>& other)
: TBase(other.begin(), other.end()) {}
CSmallVector&
operator=(CSmallVector&& rhs) noexcept(std::is_nothrow_move_assignable<TBase>::value) {
this->baseRef() = std::move(rhs.baseRef());
return *this;
}
CSmallVector& operator=(const CSmallVector& rhs) {
this->baseRef() = rhs.baseRef();
return *this;
}
// Extend to convert implicitly to a vector.
inline operator std::vector<T>() const {
return std::vector<T>(this->begin(), this->end());
}
// Non-standard plus assign for the case that T has operator+=.
const CSmallVector& operator+=(const CSmallVectorBase<T>& rhs) {
small_vector_detail::SPlusAssign<T>::compute(*this, rhs);
return *this;
}
// Non-standard minus assign for the case that T has operator-=.
const CSmallVector& operator-=(const CSmallVectorBase<T>& rhs) {
small_vector_detail::SMinusAssign<T>::compute(*this, rhs);
return *this;
}
std::string toDelimited(const std::string& delimiter = ", ") const {
std::string result;
for (size_type i = 0; i < this->size(); ++i) {
result += std::to_string((*this)[i]);
if (i < this->size() - 1) {
result += delimiter;
}
// Reserve space to minimize concatenation overhead.
if (i == 0) {
result.reserve(result.size() * this->size());
}
}
return result;
}
private:
TBase& baseRef() { return *this; }
const TBase& baseRef() const { return *this; }
};
}
}
#endif // INCLUDED_ml_core_CSmallVector_h