@@ -70,13 +70,13 @@ namespace ack {
70
70
public:
71
71
using value_type = T;
72
72
73
- constexpr fixed_buffer () = default;
74
- constexpr fixed_buffer (const fixed_buffer& rhs) = default;
75
- constexpr fixed_buffer (fixed_buffer&& rhs) = default;
76
- constexpr fixed_buffer& operator =(const fixed_buffer& rhs) = default ;
77
- constexpr fixed_buffer& operator =(fixed_buffer&& rhs) = default ;
73
+ constexpr fixed_buffer () noexcept = default;
74
+ constexpr fixed_buffer (const fixed_buffer& rhs) noexcept = default;
75
+ constexpr fixed_buffer (fixed_buffer&& rhs) noexcept = default;
76
+ constexpr fixed_buffer& operator =(const fixed_buffer& rhs) noexcept = default ;
77
+ constexpr fixed_buffer& operator =(fixed_buffer&& rhs) noexcept = default ;
78
78
79
- constexpr bool resize (size_t n)
79
+ constexpr bool resize (size_t n) noexcept
80
80
{
81
81
if ( n > N ) {
82
82
return false ;
@@ -85,12 +85,12 @@ namespace ack {
85
85
return true ;
86
86
}
87
87
88
- constexpr void clear ()
88
+ constexpr void clear () noexcept
89
89
{
90
90
size_ = 0 ;
91
91
}
92
92
93
- constexpr T* data ()
93
+ constexpr T* data () noexcept
94
94
{
95
95
return data_.data ();
96
96
}
@@ -100,17 +100,17 @@ namespace ack {
100
100
return data_.data ();
101
101
}
102
102
103
- constexpr std::size_t size () const
103
+ constexpr std::size_t size () const noexcept
104
104
{
105
105
return size_;
106
106
}
107
107
108
- constexpr std::size_t max_size () const
108
+ constexpr std::size_t max_size () const noexcept
109
109
{
110
110
return N;
111
111
}
112
112
113
- constexpr void swap (fixed_buffer& rhs)
113
+ constexpr void swap (fixed_buffer& rhs) noexcept
114
114
{
115
115
std::swap ( data_, rhs.data_ );
116
116
std::swap ( size_, rhs.size_ );
@@ -138,25 +138,79 @@ namespace ack {
138
138
* @warning if buffer is resized over the size of stack allocated memory (N)
139
139
* data is re-allocated on the heap, and this data is never released
140
140
* due to constexpr constrains which prohibits defining custom destructor.
141
+ * You have to manually call `clear` to free heap allocated memory.
141
142
* The flexbuffer should be used only in short lived environments like WASM.
142
143
*/
143
144
template <typename T, std::size_t N>
144
145
class flexbuffer final : public buffer_base<flexbuffer<T, N>, T> {
145
146
public:
146
147
using value_type = T;
147
148
148
- constexpr flexbuffer () = default;
149
- constexpr flexbuffer (const flexbuffer& rhs) = default;
150
- constexpr flexbuffer (flexbuffer&& rhs) = default;
151
- constexpr flexbuffer& operator =(const flexbuffer& rhs) = default ;
152
- constexpr flexbuffer& operator =(flexbuffer&& rhs) = default ;
149
+ constexpr flexbuffer () noexcept = default;
150
+ constexpr flexbuffer (const flexbuffer& rhs)
151
+ {
152
+ sdata_ = rhs.sdata_ ;
153
+ size_ = rhs.size_ ;
154
+ dsize_ = rhs.dsize_ ;
155
+ if ( !std::is_constant_evaluated () ) {
156
+ if ( rhs.ddata_ ) {
157
+ ddata_ = new T[dsize_];
158
+ memcpy ( ddata_, rhs.ddata_ , dsize_ * sizeof ( T ));
159
+ }
160
+ }
161
+ }
162
+
163
+ constexpr flexbuffer (flexbuffer&& rhs) noexcept
164
+ {
165
+ sdata_ = std::move ( rhs.sdata_ );
166
+ size_ = rhs.size_ ;
167
+ dsize_ = rhs.dsize_ ;
168
+ ddata_ = rhs.ddata_ ;
169
+
170
+ rhs.size_ = 0 ;
171
+ rhs.dsize_ = 0 ;
172
+ rhs.ddata_ = nullptr ;
173
+ }
153
174
154
- // ~flex_buffer() // destructor deleted otherwise flex_buffer can't be constructed at compile time
175
+ constexpr flexbuffer& operator =(const flexbuffer& rhs)
176
+ {
177
+ if ( &rhs != this ) {
178
+ this ->clear ();
179
+ sdata_ = rhs.sdata_ ;
180
+ size_ = rhs.size_ ;
181
+ dsize_ = rhs.dsize_ ;
182
+ if ( !std::is_constant_evaluated () ) {
183
+ if ( rhs.ddata_ ) {
184
+ ddata_ = new T[dsize_];
185
+ memcpy ( ddata_, rhs.ddata_ , dsize_ * sizeof ( T ));
186
+ }
187
+ }
188
+ }
189
+ return *this ;
190
+ }
191
+
192
+ constexpr flexbuffer& operator =(flexbuffer&& rhs) noexcept
193
+ {
194
+ if ( &rhs != this ) {
195
+ this ->clear ();
196
+ sdata_ = std::move ( rhs.sdata_ );
197
+ size_ = rhs.size_ ;
198
+ dsize_ = rhs.dsize_ ;
199
+ ddata_ = rhs.ddata_ ;
200
+
201
+ rhs.size_ = 0 ;
202
+ rhs.dsize_ = 0 ;
203
+ rhs.ddata_ = nullptr ;
204
+ }
205
+ return *this ;
206
+ }
207
+
208
+ // constexpr ~flex_buffer() // destructor deleted otherwise flex_buffer can't be constructed at compile time
155
209
// {
156
210
// if ( std::is_constant_evaluated() ) {
157
- // if ( ddata_ ) {
158
- // delete[] ddata_;
159
- // }
211
+ // if ( ddata_ ) {
212
+ // delete[] ddata_;
213
+ // }
160
214
// }
161
215
// }
162
216
@@ -168,19 +222,18 @@ namespace ack {
168
222
}
169
223
}
170
224
else {
171
- if ( n > N && n > dsize ) {
172
-
225
+ if ( n > N && n > dsize_ ) {
173
226
bool scpy = ( ddata_ == nullptr );
174
227
T* pold = ddata_;
175
228
176
- dsize += std::max ( N, n );
177
- ddata_ = new T[dsize ];
229
+ dsize_ += std::max ( N, n );
230
+ ddata_ = new T[dsize_ ];
178
231
179
232
if ( scpy ) {
180
233
memcpy ( ddata_, sdata_.data (), N * sizeof ( T ));
181
234
}
182
- else {
183
- memcpy ( ddata_, pold, (dsize - std::max ( N, n )) * sizeof ( T ));
235
+ else {
236
+ memcpy ( ddata_, pold, (dsize_ - std::max ( N, n )) * sizeof ( T ));
184
237
delete[] pold;
185
238
pold = nullptr ;
186
239
}
@@ -193,7 +246,14 @@ namespace ack {
193
246
194
247
constexpr void clear ()
195
248
{
196
- size_ = 0 ;
249
+ if ( !std::is_constant_evaluated () ) {
250
+ if ( ddata_ ) {
251
+ delete [] ddata_;
252
+ ddata_ = nullptr ;
253
+ }
254
+ }
255
+ dsize_ = 0 ;
256
+ size_ = 0 ;
197
257
}
198
258
199
259
constexpr T* data ()
@@ -203,7 +263,7 @@ namespace ack {
203
263
204
264
constexpr const T* data () const
205
265
{
206
- return ddata_? ddata_ : sdata_.data ();
266
+ return ddata_ ? ddata_ : sdata_.data ();
207
267
}
208
268
209
269
constexpr std::size_t size () const
@@ -220,7 +280,7 @@ namespace ack {
220
280
{
221
281
std::swap ( sdata_, rhs.sdata_ );
222
282
if ( !std::is_constant_evaluated () ) {
223
- std::swap ( dsize , rhs.dsize );
283
+ std::swap ( dsize_ , rhs.dsize_ );
224
284
std::swap ( ddata_, rhs.ddata_ );
225
285
}
226
286
std::swap ( size_, rhs.size_ );
@@ -251,8 +311,8 @@ namespace ack {
251
311
private:
252
312
std::array<T, N> sdata_ = {};
253
313
T* ddata_ = nullptr ; // replace with std::vector<T> when C++20 constexpr ctor is supported
254
- std::size_t size_ = 0 ;
255
- std::size_t dsize = 0 ;
314
+ std::size_t size_ = 0 ;
315
+ std::size_t dsize_ = 0 ;
256
316
};
257
317
template <std::size_t N>
258
318
using fixed_word_buffer = fixed_buffer<word_t , N>;
0 commit comments