17 template <
typename... TArgs>
20 std::aligned_union_t<4, TArgs...> storage;
26 template <
typename T,
typename... Ts>
29 new (&storage) T(std::forward<Ts>(args)...);
45 return reinterpret_cast<T&
>(storage);
51 return reinterpret_cast<const T&
>(storage);
59 template <
typename... TArgs>
70 template <
typename... TArgs>
81 template <
typename... TArgs>
85 template <
typename T,
typename TOther>
86 void visit(
const TOther& other) {
87 storage.template emplace<T>(other.template get<T>());
92 typename = std::enable_if_t<!std::is_lvalue_reference<TOther>::value>>
94 storage.template emplace<T>(std::move(other.template get<T>()));
99 template <
typename... TArgs>
103 template <
typename T,
typename TOther>
105 using TRaw = std::decay_t<TOther>;
106 storage.template get<TRaw>() = std::forward<TOther>(other);
111 template <
typename... TArgs>
115 template <
typename T,
typename TOther>
117 storage.template get<T>() = other.template get<T>();
120 template <
typename T,
122 typename = std::enable_if_t<!std::is_lvalue_reference<TOther>::value>>
124 storage.template get<T>() = std::move(other.template get<T>());
129 template <
typename... TArgs>
133 template <
typename T,
typename TOther>
143 template <
typename T0,
typename... TArgs>
145 template <
typename TVisitor,
typename... Ts>
146 static void visit(
Size idx, TVisitor&& visitor, Ts&&... args) {
148 visitor.template visit<T0>(std::forward<Ts>(args)...);
151 idx - 1, std::forward<TVisitor>(visitor), std::forward<Ts>(args)...);
156 template <
typename T0>
158 template <
typename TVisitor,
typename... Ts>
159 static void visit(
Size idx, TVisitor&& visitor, Ts&&... args) {
161 visitor.template visit<T0>(std::forward<Ts>(args)...);
166 static constexpr
struct ConstructTypeIdxTag {
167 } CONSTRUCT_TYPE_IDX;
170 template <
typename... TArgs>
181 static_assert(
sizeof...(TArgs) >= 1,
"Must have at least 1 variant");
190 storage.template emplace<T>();
195 template <
typename T,
typename = std::enable_if_t<!std::is_same<std::decay_t<T>, Variant>::value>>
197 using RawT = std::decay_t<T>;
199 static_assert(idx != -1,
"Type must be listed in Variant");
200 storage.template emplace<RawT>(std::forward<T>(value));
217 typeIdx = other.typeIdx;
223 typeIdx = other.typeIdx;
235 template <
typename T,
typename = std::enable_if_t<!std::is_same<std::decay_t<T>, Variant>::value>>
237 using RawT = std::decay_t<T>;
239 static_assert(idx != -1,
"Type must be listed in Variant");
240 if (
int(typeIdx) != idx) {
243 storage.template emplace<RawT>(std::forward<T>(value));
246 storage.template get<RawT>() = std::forward<T>(value);
258 if (typeIdx != other.typeIdx) {
266 typeIdx = other.typeIdx;
275 if (typeIdx != other.typeIdx) {
283 typeIdx = other.typeIdx;
299 template <
typename T,
typename... Ts>
301 using RawT = std::decay_t<T>;
303 static_assert(idx != -1,
"Type must be listed in Variant");
305 storage.template emplace<RawT>(std::forward<Ts>(args)...);
315 template <
typename T>
317 constexpr
int idx = getTypeIndex<std::decay_t<T>, TArgs...>;
318 return typeIdx == idx;
324 template <
typename T>
326 using RawT = std::decay_t<T>;
334 template <
typename T>
336 constexpr
int idx = getTypeIndex<std::decay_t<T>, TArgs...>;
337 static_assert(idx != -1,
"Cannot convert variant to this type");
339 return storage.template get<T>();
343 template <
typename T>
345 constexpr
int idx = getTypeIndex<std::decay_t<T>, TArgs...>;
346 static_assert(idx != -1,
"Cannot convert variant to this type");
348 return storage.template get<T>();
355 template <
typename T,
typename = std::enable_if_t<!std::is_same<std::decay_t<T>, Variant>::value>>
361 template <
typename T,
typename = std::enable_if_t<!std::is_same<std::decay_t<T>, Variant>::value>>
362 operator const T&()
const {
370 template <
typename T>
372 constexpr
int idx = getTypeIndex<std::decay_t<T>, TArgs...>;
373 static_assert(idx != -1,
"Cannot convert variant to this type");
374 if (typeIdx !=
getTypeIndex<std::decay_t<T>, TArgs...>) {
377 return storage.template get<T>();
383 template <
Size N,
typename T0,
typename... TArgs>
385 template <
typename TVariant,
typename TFunctor>
386 INLINE static decltype(
auto)
action(TVariant&& variant, TFunctor&& functor) {
387 if (variant.getTypeIdx() ==
N) {
388 return functor(variant.template get<T0>());
391 std::forward<TVariant>(variant), std::forward<TFunctor>(functor));
397 template <
Size N,
typename... TArgs>
399 template <
typename TVariant,
typename TFunctor>
400 INLINE static decltype(
auto)
action(TVariant&& variant, TFunctor&& functor) {
401 if (variant.getTypeIdx() !=
N) {
403 std::forward<TVariant>(variant), std::forward<TFunctor>(functor));
409 template <Size N,
typename T0>
411 template <
typename TVariant,
typename TFunctor>
412 INLINE static decltype(
auto)
action(TVariant&& variant, TFunctor&& functor) {
413 return functor(variant.template get<T0>());
427 template <
typename TFunctor,
typename... TArgs>
434 template <
typename TFunctor,
typename... TArgs>
443 template <
typename... TArgs>
444 void swap(Sph::Variant<TArgs...>& v1, Sph::Variant<TArgs...>& v2) {
INLINE bool isAligned(const T &value)
#define SPH_ASSERT(x,...)
Global parameters of the code.
uint32_t Size
Integral type used to index arrays (by default).
Additional math routines (with more includes).
#define INLINE
Macros for conditional compilation based on selected compiler.
#define NAMESPACE_SPH_END
Wrapper of type value of which may or may not be present.
const NothingType NOTHING
typename TypeSelector< n, TArgs... >::Type SelectType
constexpr int getTypeIndex
decltype(auto) INLINE forValue(Variant< TArgs... > &variant, TFunctor &&functor)
Stores value of type std::aligned_union, having size and alignment equal to maximum of sizes and alig...
INLINE void destroy()
Destroys value of type T.
INLINE void emplace(Ts &&... args)
Creates value of type T in place.
INLINE const T & get() const
Converts stored value to a reference of type T.
INLINE T & get()
Converts stored value to a reference of type T.
Wrapper of type value of which may or may not be present.
Variant, an implementation of type-safe union, similar to std::variant or boost::variant.
Variant(const ConstructTypeIdxTag, const Size typeIdx)
Default-constructs a type with given type index.
void swap(Variant &other)
Swaps value stored in the variant with value of different variant.
INLINE const T & get() const
Returns the stored value, const version.
INLINE Size getTypeIdx() const
Returns index of type currently stored in variant.
Variant & operator=(T &&value)
Universal copy/move operator with type of rhs being one of stored types.
static constexpr INLINE bool canHold()
Checks if the given type is one of the listed ones.
Optional< T > tryGet() const
Returns the stored value in the variant.
Variant()
Default constructor, constructs the object of type listed first in the type list using its default co...
INLINE bool has() const
Checks if the variant currently hold value of given type.
void emplace(Ts &&... args)
Creates a value of type T in place.
Variant & operator=(const Variant &other)
Assigns another variant into this.
Variant & operator=(Variant &&other)
Moves another variant into this.
Variant(T &&value)
Construct variant from value of stored type.
INLINE T & get()
Returns the stored value.
Variant(const Variant &other)
Helper visitors creating, deleting or modifying Variant.
Overload of std::swap for Sph::Array.
void swap(Sph::Array< T, TCounter > &ar1, Sph::Array< T, TCounter > &ar2)
static decltype(auto) INLINE action(TVariant &&variant, TFunctor &&functor)
Assigns a value type of which can be stored in variant.
void visit(TOther &&other)
AlignedUnion< TArgs... > & storage
Creates a variant by copying/moving value currently stored in other variant.
AlignedUnion< TArgs... > & storage
void visit(const TOther &other)
void visit(TOther &&other)
Creates a variant by copying/moving value currently stored in other variant.
void visit(const TOther &other)
void visit(TOther &&other)
AlignedUnion< TArgs... > & storage
Creates a variant using default constructor.
AlignedUnion< TArgs... > & storage
Destroys the object currently stored in variant.
AlignedUnion< TArgs... > & storage
Swaps content of two variants.
void visit(TOther &&other)
AlignedUnion< TArgs... > & storage
static void visit(Size idx, TVisitor &&visitor, Ts &&... args)
Iterates through types of variant until idx-th type is found, and executes given TVisitor,...
static void visit(Size idx, TVisitor &&visitor, Ts &&... args)