sequencer
type_erased_storage.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <sequencer/assert.hpp>
4 
5 #include <cassert>
6 #include <type_traits>
7 #include <utility>
8 
9 namespace sequencer
10 {
12  {
13  template < class T >
14  static void delete_data( void* data ) noexcept
15  {
16  SEQUENCER_ASSERT( data )
17  delete static_cast< T* >( data );
18  }
19 
20  template < class T >
21  static void* copy_data( void* data )
22  {
23  return data ? new T( *static_cast< T* >( data ) ) : nullptr;
24  }
25 
26  public:
27  type_erased_storage_t() noexcept = default;
28 
29  template < class T, std::enable_if_t< !std::is_constructible<
30  type_erased_storage_t, std::decay_t< T > >::value >* = nullptr >
31  // NOLINTNEXTLINE(bugprone-forwarding-reference-overload)
32  explicit type_erased_storage_t( T&& value )
33  : del_( &delete_data< std::decay_t< T > > ),
34  copy_data_( &copy_data< std::decay_t< T > > ),
35  data_( new std::decay_t< T >( std::forward< T >( value ) ) )
36  {
37  }
38 
39  template < class T, std::enable_if_t< !std::is_constructible<
40  type_erased_storage_t, std::decay_t< T > >::value >* = nullptr >
41  type_erased_storage_t& operator=( T&& value )
42  {
43  // NOLINTNEXTLINE(cppcoreguidelines-c-copy-assignment-signature)
44  return *this = Storage( std::forward< T >( value ) );
45  }
46 
48  {
49  reset();
50  }
51 
52  type_erased_storage_t( const type_erased_storage_t& other )
53  : del_( other.del_ ), copy_data_( other.copy_data_ ),
54  data_( other.data_ == nullptr ? nullptr : other.copy() )
55  {
56  }
57 
58  type_erased_storage_t( type_erased_storage_t&& other ) noexcept
59  : del_( other.del_ ), copy_data_( other.copy_data_ ), data_( other.data_ )
60  {
61  other.data_ = nullptr;
62  }
63 
64  type_erased_storage_t& operator=( const type_erased_storage_t& other )
65  {
66  reset();
67  del_ = other.del_;
68  copy_data_ = other.copy_data_;
69  data_ = ( other.data_ == nullptr ? nullptr : other.copy() );
70  return *this;
71  }
72 
73  type_erased_storage_t& operator=( type_erased_storage_t&& other ) noexcept
74  {
75  reset();
76  del_ = other.del_;
77  copy_data_ = other.copy_data_;
78  data_ = other.data_;
79  other.data_ = nullptr;
80  return *this;
81  }
82 
83  template < class T >
84  T& get() noexcept
85  {
86  SEQUENCER_ASSERT( data_ )
87  return *static_cast< T* >( data_ );
88  }
89 
90  template < class T >
91  const T& get() const noexcept
92  {
93  SEQUENCER_ASSERT( data_ )
94  return *static_cast< const T* >( data_ );
95  }
96 
97  explicit operator bool() const noexcept
98  {
99  return data_ != nullptr;
100  }
101 
102  private:
103  void reset() noexcept
104  {
105  if ( data_ != nullptr )
106  {
107  del_( data_ );
108  }
109  }
110 
111  void* copy() const
112  {
113  SEQUENCER_ASSERT( data_ )
114  return copy_data_( data_ );
115  }
116 
117  using delete_fn = void ( * )( void* );
118  using copy_fn = void* (*)( void* );
119  delete_fn del_ = nullptr;
120  copy_fn copy_data_ = nullptr;
121  void* data_ = nullptr;
122  };
123 } // namespace sequencer
type_erased_storage_t(T &&value)
Definition: type_erased_storage.hpp:32
type_erased_storage_t & operator=(T &&value)
Definition: type_erased_storage.hpp:41
Definition: beat_duration.hpp:106
#define SEQUENCER_ASSERT(cond)
Definition: assert.hpp:8
type_erased_storage_t(type_erased_storage_t &&other) noexcept
Definition: type_erased_storage.hpp:58
type_erased_storage_t & operator=(const type_erased_storage_t &other)
Definition: type_erased_storage.hpp:64
Definition: type_erased_storage.hpp:11
~type_erased_storage_t()
Definition: type_erased_storage.hpp:47
type_erased_storage_t(const type_erased_storage_t &other)
Definition: type_erased_storage.hpp:52
type_erased_storage_t() noexcept=default
type_erased_storage_t & operator=(type_erased_storage_t &&other) noexcept
Definition: type_erased_storage.hpp:73