@@ -36,6 +36,7 @@ SOFTWARE.
3636#include " static_assert.h"
3737#include " error_handler.h"
3838#include " exception.h"
39+ #include " utility.h"
3940
4041#include < stdint.h>
4142
@@ -71,6 +72,19 @@ namespace etl
7172 }
7273 };
7374
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+
7488 // *****************************************************************************
7589 // / Check that 'p' has 'required_alignment'.
7690 // *****************************************************************************
@@ -333,6 +347,109 @@ namespace etl
333347#if ETL_USING_CPP11
334348 template <size_t Length, typename T>
335349 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+ };
336453#endif
337454}
338455
0 commit comments