@@ -36,6 +36,7 @@ SOFTWARE.
36
36
#include " static_assert.h"
37
37
#include " error_handler.h"
38
38
#include " exception.h"
39
+ #include " utility.h"
39
40
40
41
#include < stdint.h>
41
42
@@ -71,6 +72,19 @@ namespace etl
71
72
}
72
73
};
73
74
75
+ // ***************************************************************************
76
+ // / Typed storage exception.
77
+ // ***************************************************************************
78
+ class typed_storage_error : public alignment_exception
79
+ {
80
+ public:
81
+
82
+ typed_storage_error (string_type file_name_, numeric_type line_number_)
83
+ : alignment_exception(ETL_ERROR_TEXT(" typed_storage:error" , ETL_ALIGNMENT_FILE_ID" B" ), file_name_, line_number_)
84
+ {
85
+ }
86
+ };
87
+
74
88
// *****************************************************************************
75
89
// / Check that 'p' has 'required_alignment'.
76
90
// *****************************************************************************
@@ -333,6 +347,109 @@ namespace etl
333
347
#if ETL_USING_CPP11
334
348
template <size_t Length, typename T>
335
349
using aligned_storage_as_t = typename aligned_storage_as<Length, T>::type;
350
+
351
+ // ***************************************************************************
352
+ // / Wrapper class that provides a memory area and lets the user emplace and
353
+ // / instance of T in this memory at runtime. This class also erases the
354
+ // / destructor call of T, i.e. if typed_storage goes out of scope, the
355
+ // / destructor if the wrapped type will not be called. This can be done
356
+ // / explicitly by calling destroy().
357
+ // / \tparam T Type of element stored in this instance of typed_storage.
358
+ // ***************************************************************************
359
+ template <typename T>
360
+ class typed_storage
361
+ {
362
+ public:
363
+
364
+ using value_type = T;
365
+ using reference = T&;
366
+ using const_reference = T const &;
367
+ using pointer = T*;
368
+ using const_pointer = T const *;
369
+
370
+ // Constructor
371
+ typed_storage ()
372
+ : valid(false )
373
+ {
374
+ }
375
+
376
+ // ***************************************************************************
377
+ // / Default destructor which will NOT call the destructor of the object which
378
+ // / was created by calling emplace().
379
+ // ***************************************************************************
380
+ ~typed_storage () = default ;
381
+
382
+ // ***************************************************************************
383
+ // / Calls the destructor of the wrapped object and asserts if has_value() is false.
384
+ // ***************************************************************************
385
+ void destroy ()
386
+ {
387
+ ETL_ASSERT (has_value (), ETL_ERROR (etl::typed_storage_error));
388
+ data.template get_reference <T>().~T ();
389
+ valid = false ;
390
+ }
391
+
392
+ // ***************************************************************************
393
+ // / \returns true if object has been constructed using emplace().
394
+ // / \returns false otherwise.
395
+ // ***************************************************************************
396
+ bool has_value () const
397
+ {
398
+ return valid;
399
+ }
400
+
401
+ // ***************************************************************************
402
+ // / Constructs the instance of T forwarding the given \p args to its constructor and
403
+ // / asserts if has_value() is true before calling emplace().
404
+ // /
405
+ // / \returns the instance of T which has been constructed in the internal byte array.
406
+ // ***************************************************************************
407
+ template <typename ... Args>
408
+ reference create (Args&&... args)
409
+ {
410
+ ETL_ASSERT (!has_value (), ETL_ERROR (etl::typed_storage_error));
411
+ valid = true ;
412
+ return *::new (data.template get_address <char >()) value_type (etl::forward<Args>(args)...);
413
+ }
414
+
415
+ // ***************************************************************************
416
+ // / \returns a pointer of type T and asserts if has_value() is false.
417
+ // ***************************************************************************
418
+ pointer operator ->()
419
+ {
420
+ ETL_ASSERT (has_value (), ETL_ERROR (etl::typed_storage_error));
421
+ return data.template get_address <value_type>();
422
+ }
423
+
424
+ // ***************************************************************************
425
+ // / \returns a const pointer of type T and asserts if has_value() is false.
426
+ // ***************************************************************************
427
+ const_pointer operator ->() const
428
+ {
429
+ return operator ->();
430
+ }
431
+
432
+ // ***************************************************************************
433
+ // / \returns reference of type T and asserts if has_value() is false.
434
+ // ***************************************************************************
435
+ reference operator *()
436
+ {
437
+ return *operator ->();
438
+ }
439
+
440
+ // ***************************************************************************
441
+ // / \returns const reference of type T and asserts if has_value() is false.
442
+ // ***************************************************************************
443
+ const_reference operator *() const
444
+ {
445
+ return *operator ->();
446
+ }
447
+
448
+ private:
449
+
450
+ typename aligned_storage_as<sizeof (value_type), value_type>::type data;
451
+ bool valid;
452
+ };
336
453
#endif
337
454
}
338
455
0 commit comments