FastLED 3.9.15
Loading...
Searching...
No Matches
fl::Variant< Types > Class Template Reference

Detailed Description

template<typename... Types>
class fl::Variant< Types >

Definition at line 11 of file variant.h.

#include <variant.h>

+ Inheritance diagram for fl::Variant< Types >:

Classes

struct  type_to_tag_impl
 
struct  type_to_tag_impl< T >
 
struct  type_to_tag_impl< T, U, Rest... >
 

Public Types

using Tag = u8
 

Public Member Functions

 Variant () noexcept
 
template<typename T, typename = typename fl::enable_if< contains_type<T, Types...>::value>::type>
 Variant (const T &value)
 
 Variant (const Variant &other)
 
template<typename T, typename = typename fl::enable_if< contains_type<T, Types...>::value>::type>
 Variant (T &&value)
 
 Variant (Variant &&other) noexcept
 
 ~Variant ()
 
template<typename T, typename... Args>
fl::enable_if< contains_type< T, Types... >::value, T & >::type emplace (Args &&...args)
 
bool empty () const noexcept
 
template<typename T>
bool equals (const T &other) const
 
template<typename T>
T & get ()
 Get a reference to the stored value of type T.
 
template<typename T>
const T & get () const
 Get a const reference to the stored value of type T.
 
template<typename T>
bool is () const noexcept
 
template<typename T, typename = typename fl::enable_if< contains_type<T, Types...>::value>::type>
Variantoperator= (const T &value)
 
Variantoperator= (const Variant &other)
 
template<typename T, typename = typename fl::enable_if< contains_type<T, Types...>::value>::type>
Variantoperator= (T &&value)
 
Variantoperator= (Variant &&other) noexcept
 
template<typename T>
T * ptr ()
 
template<typename T>
const T * ptr () const
 
void reset () noexcept
 
Tag tag () const noexcept
 
template<typename Visitor>
void visit (Visitor &visitor)
 
template<typename Visitor>
void visit (Visitor &visitor) const
 

Static Public Attributes

static constexpr Tag Empty = 0
 

Private Member Functions

template<typename T, typename... Args>
void construct (Args &&...args)
 
void copy_construct_from (const Variant &other)
 
void destroy_current () noexcept
 
void move_construct_from (Variant &other) noexcept
 

Static Private Member Functions

template<typename T>
static void copy_fn (void *storage, const Variant &other)
 
template<typename T>
static void destroy_fn (void *storage)
 
template<typename T>
static void move_fn (void *storage, Variant &other)
 
template<typename T>
static constexpr Tag type_to_tag ()
 
template<typename T, typename Visitor>
static void visit_fn (void *storage, Visitor &v)
 
template<typename T, typename Visitor>
static void visit_fn_const (const void *storage, Visitor &v)
 

Private Attributes

char _storage [max_size< Types... >::value]
 
Tag _tag
 

Member Typedef Documentation

◆ Tag

template<typename... Types>
using fl::Variant< Types >::Tag = u8

Definition at line 13 of file variant.h.

Constructor & Destructor Documentation

◆ Variant() [1/5]

template<typename... Types>
fl::Variant< Types >::Variant ( )
inlinenoexcept

Definition at line 18 of file variant.h.

18: _tag(Empty) {}
static constexpr Tag Empty
Definition variant.h:14

◆ Variant() [2/5]

template<typename... Types>
template<typename T, typename = typename fl::enable_if< contains_type<T, Types...>::value>::type>
fl::Variant< Types >::Variant ( const T & value)
inline

Definition at line 22 of file variant.h.

22 : _tag(Empty) {
24 }
void construct(Args &&...args)
Definition variant.h:288

◆ Variant() [3/5]

template<typename... Types>
template<typename T, typename = typename fl::enable_if< contains_type<T, Types...>::value>::type>
fl::Variant< Types >::Variant ( T && value)
inline

Definition at line 28 of file variant.h.

28 : _tag(Empty) {
30 }

◆ Variant() [4/5]

template<typename... Types>
fl::Variant< Types >::Variant ( const Variant< Types > & other)
inline

Definition at line 32 of file variant.h.

32 : _tag(Empty) {
33 if (!other.empty()) {
35 }
36 }
bool empty() const noexcept
Definition variant.h:104
void copy_construct_from(const Variant &other)
Definition variant.h:229

◆ Variant() [5/5]

template<typename... Types>
fl::Variant< Types >::Variant ( Variant< Types > && other)
inlinenoexcept

Definition at line 38 of file variant.h.

38 : _tag(Empty) {
39 if (!other.empty()) {
41 // After moving, mark other as empty to prevent destructor calls on moved-from objects
43 }
44 }
void move_construct_from(Variant &other) noexcept
Definition variant.h:245

◆ ~Variant()

template<typename... Types>
fl::Variant< Types >::~Variant ( )
inline

Definition at line 46 of file variant.h.

46{ reset(); }
void reset() noexcept
Definition variant.h:96

Member Function Documentation

◆ construct()

template<typename... Types>
template<typename T, typename... Args>
void fl::Variant< Types >::construct ( Args &&... args)
inlineprivate

Definition at line 288 of file variant.h.

288 {
289 new (&_storage) T(fl::forward<Args>(args)...);
291 }
char _storage[max_size< Types... >::value]
Definition variant.h:294
static constexpr Tag type_to_tag()
Definition variant.h:267

Referenced by fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::Variant(), fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::Variant(), fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::emplace(), fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::operator=(), and fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::operator=().

+ Here is the caller graph for this function:

◆ copy_construct_from()

template<typename... Types>
void fl::Variant< Types >::copy_construct_from ( const Variant< Types > & other)
inlineprivate

Definition at line 229 of file variant.h.

229 {
230 using Fn = void (*)(void *, const Variant &);
231 static constexpr Fn table[] = {&Variant::template copy_fn<Types>...};
232 table[other._tag - 1](&_storage, other);
233 _tag = other._tag;
234 }
Variant() noexcept
Definition variant.h:18
static void copy_fn(void *storage, const Variant &other)
Definition variant.h:237

Referenced by fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::operator=().

+ Here is the caller graph for this function:

◆ copy_fn()

template<typename... Types>
template<typename T>
static void fl::Variant< Types >::copy_fn ( void * storage,
const Variant< Types > & other )
inlinestaticprivate

Definition at line 237 of file variant.h.

237 {
238 // Use bit_cast_ptr for safe type-punning on properly aligned storage
239 // The storage is guaranteed to be properly aligned by alignas(max_align<Types...>::value)
241 new (storage) T(*source_ptr);
242 }
To * bit_cast_ptr(void *storage) noexcept
Definition bit_cast.h:54

◆ destroy_current()

template<typename... Types>
void fl::Variant< Types >::destroy_current ( )
inlineprivatenoexcept

Definition at line 213 of file variant.h.

213 {
214 using Fn = void (*)(void *);
215 static constexpr Fn table[] = {&Variant::template destroy_fn<Types>...};
216 if (_tag != Empty) {
217 table[_tag - 1](&_storage);
218 }
219 }
static void destroy_fn(void *storage)
Definition variant.h:221

Referenced by fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::reset().

+ Here is the caller graph for this function:

◆ destroy_fn()

template<typename... Types>
template<typename T>
static void fl::Variant< Types >::destroy_fn ( void * storage)
inlinestaticprivate

Definition at line 221 of file variant.h.

221 {
222 // Use bit_cast_ptr for safe type-punning on properly aligned storage
223 // The storage is guaranteed to be properly aligned by alignas(max_align<Types...>::value)
225 typed_ptr->~T();
226 }

◆ emplace()

template<typename... Types>
template<typename T, typename... Args>
fl::enable_if< contains_type< T, Types... >::value, T & >::type fl::Variant< Types >::emplace ( Args &&... args)
inline

Definition at line 90 of file variant.h.

90 {
91 reset();
93 return ptr<T>();
94 }
T * ptr()
Definition variant.h:110

◆ empty()

template<typename... Types>
bool fl::Variant< Types >::empty ( ) const
inlinenoexcept

Definition at line 104 of file variant.h.

104{ return _tag == Empty; }

Referenced by fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::Variant(), fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::operator=(), fl::Optional< T >::operator==(), and fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::reset().

+ Here is the caller graph for this function:

◆ equals()

template<typename... Types>
template<typename T>
bool fl::Variant< Types >::equals ( const T & other) const
inline

Definition at line 146 of file variant.h.

146 {
147 if (auto p = ptr<T>()) {
148 return *p == other;
149 }
150 return false;
151 }

◆ get() [1/2]

template<typename... Types>
template<typename T>
T & fl::Variant< Types >::get ( )
inline

Get a reference to the stored value of type T.

Template Parameters
TThe type to retrieve
Returns
Reference to the stored value
Note
Asserts if the variant doesn't contain type T. Use is<T>() to check first.
Warning
Will crash if called with wrong type - this is intentional for fast failure

Definition at line 129 of file variant.h.

129 {
130 // Dereference ptr() directly - will crash with null pointer access if wrong type
131 // This provides fast failure semantics similar to std::variant
132 return *ptr<T>();
133 }

◆ get() [2/2]

template<typename... Types>
template<typename T>
const T & fl::Variant< Types >::get ( ) const
inline

Get a const reference to the stored value of type T.

Template Parameters
TThe type to retrieve
Returns
Const reference to the stored value
Note
Asserts if the variant doesn't contain type T. Use is<T>() to check first.
Warning
Will crash if called with wrong type - this is intentional for fast failure

Definition at line 140 of file variant.h.

140 {
141 // Dereference ptr() directly - will crash with null pointer access if wrong type
142 // This provides fast failure semantics similar to std::variant
143 return *ptr<T>();
144 }

◆ is()

template<typename... Types>
template<typename T>
bool fl::Variant< Types >::is ( ) const
inlinenoexcept

Definition at line 106 of file variant.h.

106 {
107 return _tag == type_to_tag<T>();
108 }

◆ move_construct_from()

template<typename... Types>
void fl::Variant< Types >::move_construct_from ( Variant< Types > & other)
inlineprivatenoexcept

Definition at line 245 of file variant.h.

245 {
246 using Fn = void (*)(void *, Variant &);
247 static constexpr Fn table[] = {&Variant::template move_fn<Types>...};
248 table[other._tag - 1](&_storage, other);
249 _tag = other._tag;
250 other.reset();
251 }
static void move_fn(void *storage, Variant &other)
Definition variant.h:253

Referenced by fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::Variant(), and fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::operator=().

+ Here is the caller graph for this function:

◆ move_fn()

template<typename... Types>
template<typename T>
static void fl::Variant< Types >::move_fn ( void * storage,
Variant< Types > & other )
inlinestaticprivate

Definition at line 253 of file variant.h.

253 {
254 // Use bit_cast_ptr for safe type-punning on properly aligned storage
255 // The storage is guaranteed to be properly aligned by alignas(max_align<Types...>::value)
257 new (storage) T(fl::move(*source_ptr));
258 }

◆ operator=() [1/4]

template<typename... Types>
template<typename T, typename = typename fl::enable_if< contains_type<T, Types...>::value>::type>
Variant & fl::Variant< Types >::operator= ( const T & value)
inline

Definition at line 72 of file variant.h.

72 {
73 reset();
75 return *this;
76 }

◆ operator=() [2/4]

template<typename... Types>
Variant & fl::Variant< Types >::operator= ( const Variant< Types > & other)
inline

Definition at line 48 of file variant.h.

48 {
49 if (this != &other) {
50 reset();
51 if (!other.empty()) {
53 }
54 }
55 return *this;
56 }

◆ operator=() [3/4]

template<typename... Types>
template<typename T, typename = typename fl::enable_if< contains_type<T, Types...>::value>::type>
Variant & fl::Variant< Types >::operator= ( T && value)
inline

Definition at line 80 of file variant.h.

80 {
81 reset();
83 return *this;
84 }

◆ operator=() [4/4]

template<typename... Types>
Variant & fl::Variant< Types >::operator= ( Variant< Types > && other)
inlinenoexcept

Definition at line 58 of file variant.h.

58 {
59 if (this != &other) {
60 reset();
61 if (!other.empty()) {
63 // After moving, mark other as empty to prevent destructor calls on moved-from objects
65 }
66 }
67 return *this;
68 }

◆ ptr() [1/2]

template<typename... Types>
template<typename T>
T * fl::Variant< Types >::ptr ( )
inline

Definition at line 110 of file variant.h.

110 {
111 if (!is<T>()) return nullptr;
112 // Use bit_cast_ptr for safe type-punning on properly aligned storage
113 // The storage is guaranteed to be properly aligned by alignas(max_align<Types...>::value)
114 return fl::bit_cast_ptr<T>(&_storage[0]);
115 }
bool is() const noexcept
Definition variant.h:106

Referenced by fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::emplace(), fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::get(), and fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::get().

+ Here is the caller graph for this function:

◆ ptr() [2/2]

template<typename... Types>
template<typename T>
const T * fl::Variant< Types >::ptr ( ) const
inline

Definition at line 117 of file variant.h.

117 {
118 if (!is<T>()) return nullptr;
119 // Use bit_cast_ptr for safe type-punning on properly aligned storage
120 // The storage is guaranteed to be properly aligned by alignas(max_align<Types...>::value)
122 }

◆ reset()

template<typename... Types>
void fl::Variant< Types >::reset ( )
inlinenoexcept

Definition at line 96 of file variant.h.

96 {
97 if (!empty()) {
99 _tag = Empty;
100 }
101 }
void destroy_current() noexcept
Definition variant.h:213

Referenced by fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::~Variant(), fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::emplace(), fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::operator=(), fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::operator=(), fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::operator=(), and fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::operator=().

+ Here is the caller graph for this function:

◆ tag()

template<typename... Types>
Tag fl::Variant< Types >::tag ( ) const
inlinenoexcept

Definition at line 103 of file variant.h.

103{ return _tag; }

◆ type_to_tag()

template<typename... Types>
template<typename T>
static constexpr Tag fl::Variant< Types >::type_to_tag ( )
inlinestaticconstexprprivate

Definition at line 267 of file variant.h.

Referenced by fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::construct(), and fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::is().

+ Here is the caller graph for this function:

◆ visit() [1/2]

template<typename... Types>
template<typename Visitor>
void fl::Variant< Types >::visit ( Visitor & visitor)
inline

Definition at line 154 of file variant.h.

154 {
155 if (_tag == Empty)
156 return;
157
158 // Fn is "a pointer to function taking (void* storage, Visitor&)"
159 using Fn = void (*)(void *, Visitor &);
160
161 // Build a constexpr array of one thunk per type in Types...
162 // Each thunk casts the storage back to the right T* and calls
163 // visitor.accept
164 static constexpr Fn table[] = {
166
167 // _tag is 1-based, so dispatch in O(1) via one indirect call:
168 // Check bounds to prevent out-of-bounds access
169 size_t index = _tag - 1;
170 if (index < sizeof...(Types)) {
172 }
173 }
static void visit_fn(void *storage, Visitor &v)
Definition variant.h:197

Referenced by fl::Gradient::Gradient().

+ Here is the caller graph for this function:

◆ visit() [2/2]

template<typename... Types>
template<typename Visitor>
void fl::Variant< Types >::visit ( Visitor & visitor) const
inline

Definition at line 175 of file variant.h.

175 {
176 if (_tag == Empty)
177 return;
178
179 // Fn is "a pointer to function taking (const void* storage, Visitor&)"
180 using Fn = void (*)(const void *, Visitor &);
181
182 // Build a constexpr array of one thunk per type in Types...
183 static constexpr Fn table[] = {
185
186 // _tag is 1-based, so dispatch in O(1) via one indirect call:
187 // Check bounds to prevent out-of-bounds access
188 size_t index = _tag - 1;
189 if (index < sizeof...(Types)) {
191 }
192 }
static void visit_fn_const(const void *storage, Visitor &v)
Definition variant.h:205

◆ visit_fn()

template<typename... Types>
template<typename T, typename Visitor>
static void fl::Variant< Types >::visit_fn ( void * storage,
Visitor & v )
inlinestaticprivate

Definition at line 197 of file variant.h.

197 {
198 // Use bit_cast_ptr for safe type-punning on properly aligned storage
199 // The storage is guaranteed to be properly aligned by alignas(max_align<Types...>::value)
201 v.accept(*typed_ptr);
202 }

◆ visit_fn_const()

template<typename... Types>
template<typename T, typename Visitor>
static void fl::Variant< Types >::visit_fn_const ( const void * storage,
Visitor & v )
inlinestaticprivate

Definition at line 205 of file variant.h.

205 {
206 // Use bit_cast_ptr for safe type-punning on properly aligned storage
207 // The storage is guaranteed to be properly aligned by alignas(max_align<Types...>::value)
209 v.accept(*typed_ptr);
210 }

Member Data Documentation

◆ _storage

template<typename... Types>
char fl::Variant< Types >::_storage[max_size< Types... >::value]
private

Definition at line 294 of file variant.h.

Referenced by fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::copy_fn(), and fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::move_fn().

◆ _tag

template<typename... Types>
Tag fl::Variant< Types >::_tag
private

Definition at line 296 of file variant.h.

Referenced by fl::Variant< fl::span< CRGB >, fl::vector< CRGB, fl::allocator_psram< CRGB > > >::copy_construct_from().

◆ Empty

template<typename... Types>
Tag fl::Variant< Types >::Empty = 0
staticconstexpr

Definition at line 14 of file variant.h.


The documentation for this class was generated from the following file: