1 #pragma once 2 3 /// \file Dynamic.h 4 /// \brief Object holding a single values of various types 5 /// \author Pavel Sevecek (sevecek at sirrah.troja.mff.cuni.cz) 6 /// \date 2016-2021 7 8 #include "math/Means.h" 9 #include "objects/containers/String.h" 10 #include "objects/geometry/Tensor.h" 11 #include "objects/geometry/TracelessTensor.h" 12 #include "objects/wrappers/Variant.h" 13 14 NAMESPACE_SPH_BEGIN 15 16 /// \brief Enum representing a value type stored in a Value object. 17 /// 18 /// Has to be kept in sync with ValueVariant defined below. 19 enum class DynamicId { 20 SIZE = 1, 21 FLOAT, 22 VECTOR, 23 TENSOR, 24 SYMMETRIC_TENSOR, 25 TRACELESS_TENSOR, 26 MIN_MAX_MEAN, 27 STRING, 28 }; 29 30 /// \brief Convenient object for storing a single value of different types 31 /// 32 /// Object can currently store scalar, vector, tensor, unsigned integer and \ref MinMaxMean. 33 /// This is intended mainly for logging and output routines, as the object provides generic way to store 34 /// different types and print stored values. There is no need to pass types as template arguments, so the 35 /// object Value is a suitable return value or parameter of virtual functions (that cannot be templated). 36 class Dynamic { 37 private: 38 /// \note If bool is added into the variant, it will probably clash with operator bool(). 39 using DynamicVariant = Variant<NothingType, 40 Size, 41 Float, 42 Vector, 43 Tensor, 44 SymmetricTensor, 45 TracelessTensor, 46 MinMaxMean, 47 String>; 48 49 DynamicVariant storage; 50 51 public: 52 /// Construct an uninitialized value 53 Dynamic(); 54 55 ~Dynamic(); 56 57 /// Contruct value from one of possible value types 58 template <typename T, typename = std::enable_if_t<DynamicVariant::canHold<T>()>> Dynamic(T && value)59 Dynamic(T&& value) 60 : storage(std::forward<T>(value)) {} 61 Dynamic(const Dynamic & other)62 Dynamic(const Dynamic& other) 63 : storage(other.storage) {} 64 Dynamic(Dynamic && other)65 Dynamic(Dynamic&& other) 66 : storage(std::move(other.storage)) {} 67 68 /// Assign one of possible value types into the value 69 template <typename T, typename = std::enable_if_t<DynamicVariant::canHold<T>()>> 70 Dynamic& operator=(T&& rhs) { 71 storage = std::forward<T>(rhs); 72 return *this; 73 } 74 75 Dynamic& operator=(const Dynamic& other) { 76 storage = other.storage; 77 return *this; 78 } 79 80 Dynamic& operator=(Dynamic&& other) { 81 storage = std::move(other.storage); 82 return *this; 83 } 84 85 /// \brief Returns the reference to the stored value given its type. 86 /// 87 /// The stored value must indeed have a type T, checked by assert. 88 template <typename T, typename = std::enable_if_t<DynamicVariant::canHold<T>()>> get()89 INLINE T& get() { 90 return storage.get<T>(); 91 } 92 93 /// Returns the const reference to the stored value given its type. 94 template <typename T, typename = std::enable_if_t<DynamicVariant::canHold<T>()>> get()95 const T& get() const { 96 return storage.get<T>(); 97 } 98 99 /// Conversion operator to one of stored types 100 template <typename T, typename = std::enable_if_t<DynamicVariant::canHold<T>()>> 101 operator T&() { 102 return this->get<T>(); 103 } 104 105 /// Coversion operator to one of stored types, const version 106 template <typename T, typename = std::enable_if_t<DynamicVariant::canHold<T>()>> 107 operator const T&() const { 108 return this->get<T>(); 109 } 110 111 /// Converts the stored value into a single number, using one of possible conversions 112 Float getScalar() const; 113 getType()114 DynamicId getType() const { 115 return DynamicId(storage.getTypeIdx()); 116 } 117 118 /// Checks if the value has been initialized. empty()119 bool empty() const { 120 return storage.getTypeIdx() == 0; 121 } 122 123 explicit operator bool() const { 124 return !this->empty(); 125 } 126 127 bool operator!() const { 128 return this->empty(); 129 } 130 131 /// Equality operator with one of stored types. 132 template <typename T, typename = std::enable_if_t<DynamicVariant::canHold<T>()>> 133 bool operator==(const T& value) const { 134 return this->get<T>() == value; 135 } 136 137 /// Prints the currently stored value into the stream, using << operator of its type. 138 template <typename TStream> 139 friend TStream& operator<<(TStream& stream, const Dynamic& value) { 140 forValue(value.storage, [&stream](const auto& v) { stream << std::setw(20) << v; }); 141 return stream; 142 } 143 }; 144 145 NAMESPACE_SPH_END 146