Itasca C++ Interface
Loading...
Searching...
No Matches
property.h
1#pragma once
2
3// This is intended to replace Variant as a property container in constitutive models
4// in a way that makes more use of modern C++ (and is also less complex)
5
6#include "basestring.h"
7#include "mat.h"
8#include "quat.h"
9#include "vect.h"
10#include <variant>
11#include <vector>
12
13#ifdef INTELCOMP
14#pragma warning(disable:2586) // Disable warning about name length
15#endif
16
17namespace std {
18 class any;
19}
20
21namespace base {
22 class Property;
23
24 class PropArray : public std::vector<Property> {
25 public:
26 using std::vector<Property>::vector;
27 };
28
29 BASE_EXPORT UVect2 size(const PropArray &p);
30 template <> string ts(const PropArray &p, int width, char notation, int precision, char fill);
31
32 using PropBase = std::variant<int64, double, bool, string, DVect2,
33 DVect3, I64Vect2, I64Vect3, itasca::Mat, DAVect2,
34 DAVect3, Quat2, Quat3, SymTensor, std::nullptr_t,
35 PropArray>;
36
37 namespace PropertyConcepts {
38 // These are used to allow Property Contructors without the peril of directly using
39 // the variant (PropBase) constructors, which have problems with implicit conversions.
40 // I specifically allow integer implicit conversion, despite my qualms about that
41 // in general, because for now we have to accept is a C++ standard....
42 template <class T, class V>
43 concept IsIn = requires {
44 std::holds_alternative<T>(std::declval<V>());
45 };
46 template <class T>
47 concept IntNoBool = std::integral<T> and (not std::same_as<T, bool>);
48 template <class T>
50 }
51
52 class Property : public PropBase {
53 public:
54 using PropBase::PropBase; // TODO: JBC: It is unsafe to inherit parent constructors from
55 // std::variant. Implicit class conversion is possible
56 // and results in unpredictable behavior, e.g.,
57 // Property::setValue(uint64) will create a Quat2 !!!
58
59 enum class Type { Int, Double, Bool, String, DVect2,
60 DVect3, I64Vect2, I64Vect3, Matrix, DAVect2,
61 DAVect3, Quat2 , Quat3, Tensor, Null,
62 Array };
63
64 Property(): PropBase(nullptr) {}
65 template <class T> requires PropertyConcepts::NonInt<T> Property(const T &t) : PropBase(t) { }
66 template <class T> requires PropertyConcepts::IntNoBool<T> Property(const T &t) : PropBase(::to<int64>(t)) { }
67 BASE_EXPORT std::partial_ordering operator<=>(const Property &p) const;
68 template <class T> requires PropertyConcepts::NonInt<T> Property &operator=(const T &t) { PropBase::operator=(t); return *this; }
69 template <class T> requires PropertyConcepts::IntNoBool<T> Property &operator=(const T &t) { PropBase::operator=(::to<int64>(t)); return *this; }
70
71 inline Type type() const;
72 BASE_EXPORT std::tuple<Type,UVect2> desc() const;
73 BASE_EXPORT const Property &reset(); // Keep type but set value to default construction.
74 inline bool isNull() const { return type()==Type::Null; }
75 inline bool isValid() const { return not isNull(); }
76
77 // Returns TRUE if the type can be converted to the provided type. Does minimal computation.
78 // In theory we can add more type specializations (int, float, etc) based on existing.
79 template <typename T>
80 bool canConvert() const { static_assert(sizeof(T)==0); return false; } // Default
81 BASE_EXPORT bool canConvert(Type type) const; // Runtime type conversion query
82
83 template <typename T>
84 bool canConvertVec() const;
85
86 // Same as canConvert but takes a Type enum as a template argument.
87 template <Type t>
88 bool canConvertType() const { return canConvert<decltype(std::get<static_cast<int>(t)>(*this))>(); }
89
90 // Converts to the type - throws exeption if not able to convert.
91 template <typename T>
92 T to() const { static_assert(sizeof(T)==0); return false; } // DEFAULT
93 template <typename T>
94 std::vector<T> toVec() const;
95
96 // Save as to<>() but uses the Type enum as the template argument.
97 template <Type t>
98 auto toType() const { return to<decltype(std::get<static_cast<int>(t)>(*this))>(); }
99
100 // Single call test, returns both value and success boolean. Value is default init if
101 // success is false.
102 template <typename T>
103 typename std::tuple<T,bool> toTest() const;
104
105 // Same as toTest<>() but using Type enum.
106 template <Type t>
107 typename std::variant_alternative_t<static_cast<int>(t),Property> toTestType() const;
108
109 template <typename T>
110 void setValue(const T &t) { *this = t; }
111 template <typename T>
112 void setVec(const std::vector<T> &v);
113
114 template <typename T>
115 T value() const { return to<T>(); }
116
117 BASE_EXPORT static string nameFromType(Type t);
118 inline double toDouble() const;
119 inline string toString() const;
120 inline int64 toInt() const;
121 inline uint32 toUInt() const;
122 inline double toDouble(bool *ok) const;
123 inline int64 toInt(bool *ok) const;
124
125 static constexpr Type DVectType(uint32 dim) { return dim==2 ? Type::DVect2 : Type::DVect3; }
126 static constexpr Type DAVectType(uint32 dim) { return dim==2 ? Type::DAVect2 : Type::DAVect3; }
127 static constexpr Type IVectType(uint32 dim) { return dim==2 ? Type::I64Vect2 : Type::I64Vect3; }
128 };
129
130 Property::Type Property::type() const {
131 return static_cast<Type>(index());
132 }
133
134 constexpr auto operator<=>(const base::PropArray &lhs,const base::PropArray &rhs) {
135 auto &vl = static_cast<const std::vector<base::Property> &>(lhs);
136 auto &vr = static_cast<const std::vector<base::Property> &>(rhs);
137 return vl <=> vr;
138 }
139
140 template <> BASE_EXPORT bool Property::canConvert<int64>() const;
141 template <> BASE_EXPORT bool Property::canConvert<double>() const;
142 template <> BASE_EXPORT bool Property::canConvert<bool>() const;
143 template <> BASE_EXPORT bool Property::canConvert<string>() const;
144 template <> BASE_EXPORT bool Property::canConvert<DVect2>() const;
145 template <> BASE_EXPORT bool Property::canConvert<DVect3>() const;
146 template <> BASE_EXPORT bool Property::canConvert<I64Vect2>() const;
147 template <> BASE_EXPORT bool Property::canConvert<I64Vect3>() const;
148 template <> BASE_EXPORT bool Property::canConvert<itasca::Mat>() const;
149 template <> BASE_EXPORT bool Property::canConvert<DAVect2>() const;
150 template <> BASE_EXPORT bool Property::canConvert<DAVect3>() const;
151 template <> BASE_EXPORT bool Property::canConvert<Quat2>() const;
152 template <> BASE_EXPORT bool Property::canConvert<Quat3>() const;
153 template <> BASE_EXPORT bool Property::canConvert<SymTensor>() const;
154 template <> BASE_EXPORT bool Property::canConvert<PropArray>() const;
155
156 template <> BASE_EXPORT int64 Property::to<int64>() const;
157 template <> BASE_EXPORT double Property::to<double>() const;
158 template <> BASE_EXPORT bool Property::to<bool>() const;
159 template <> BASE_EXPORT string Property::to<string>() const;
160 template <> BASE_EXPORT DVect2 Property::to<DVect2>() const;
161 template <> BASE_EXPORT DVect3 Property::to<DVect3>() const;
162 template <> BASE_EXPORT I64Vect2 Property::to<I64Vect2>() const;
163 template <> BASE_EXPORT I64Vect3 Property::to<I64Vect3>() const;
164 template <> BASE_EXPORT itasca::Mat Property::to<itasca::Mat>() const;
165 template <> BASE_EXPORT DAVect2 Property::to<DAVect2>() const;
166 template <> BASE_EXPORT DAVect3 Property::to<DAVect3>() const;
167 template <> BASE_EXPORT Quat2 Property::to<Quat2>() const;
168 template <> BASE_EXPORT Quat3 Property::to<Quat3>() const;
169 template <> BASE_EXPORT SymTensor Property::to<SymTensor>() const;
170 template <> BASE_EXPORT PropArray Property::to<PropArray>() const;
171
172 class PropertyConvertException : public Exception {
173 public:
174 PropertyConvertException(Property::Type from,Property::Type to) :
175 Exception("Error converting Property from {} to {}.",
176 Property::nameFromType(from),Property::nameFromType(to)) {
177 }
178 };
179
180 template <typename T>
181 void Property::setVec(const std::vector<T> &v) {
182 PropArray pa;
183 Type t{};
184 for (size_t i=0;i<v.size();++i) {
185 pa.push_back({});
186 pa.back().setValue(v[i]);
187 if (not i) t = pa.back().type();
188 else if (t!=pa.back().type()) throw Exception("All elements of a property array must be of the same type.");
189 }
190 operator=(pa);
191 }
192
193 double Property::toDouble() const { return to<double>(); }
194 string Property::toString() const { return to<string>(); }
195 int64 Property::toInt() const { return to<int64>();}
196 uint32 Property::toUInt() const { return static_cast<uint32>(to<int64>()); }
197
198 double Property::toDouble(bool *ok) const {
199 *ok = canConvert<double>();
200 if (*ok) return to<double>();
201 return 0.0;
202 }
203
204 int64 Property::toInt(bool *ok) const {
205 *ok = canConvert<int64>();
206 if (*ok) return to<int64>();
207 return 0;
208 }
209
210 template <typename T>
211 typename std::tuple<T,bool> Property::toTest() const {
212 bool b = canConvert<T>();
213 if (b)
214 return {to<T>(),b};
215 return {T{},false};
216 }
217
218 template <Property::Type t>
219 typename std::variant_alternative_t<static_cast<int>(t),Property> Property::toTestType() const {
220 using target_type = decltype(std::get<static_cast<int>(t)>(*this));
221 using return_type = std::tuple<target_type,bool>;
222 bool b = canConvert<target_type>();
223 if (b) return return_type(to<target_type>(),true);
224 return return_type(target_type{},false);
225 }
226
227 template <typename T>
228 bool Property::canConvertVec() const {
229 if (type()!=Type::Array) return false;
230 auto &a = std::get<PropArray>(*this);
231 if (not a.size()) return true;
232 return a[0].canConvert<T>();
233 }
234
235 template <typename T>
236 std::vector<T> Property::toVec() const {
237 if (type()!=Type::Array) throw PropertyConvertException(type(),Type::Array);
238 auto &a = std::get<PropArray>(*this);
239 if (not a.size()) return {};
240 std::vector<T> ret;
241 for (auto &v : a)
242 ret.push_back(v.to<T>());
243 return ret;
244 }
245
246 // This allows using the Type enum as a selector in a get, so
247 // get<Property::Bool>(p);
248 template <Property::Type t>
249 const auto &get(const Property &v) { return std::get<static_cast<int>(t)>(v); }
250
251 // String conversion, using the base::ts standard
252 template <>
253 BASE_EXPORT string ts<base::Property>(const base::Property &p, int width, char notation, int precision, char fill);
254
255 // Description of a property type. The information necessary to parse.
256 struct PropDesc {
257 PropDesc() { }
258 PropDesc(const string &name,Property::Type type,UVect2 size) : name_(name), type_(type), size_(size) { }
259 BASE_EXPORT PropDesc(const string &name,const Property &prop);
260 string name_;
261 Property::Type type_ = Property::Type::Int;
262 UVect2 size_ = UVect2(0);
263 auto operator<=>(const PropDesc &p) const = default;
264 };
265
266 BASE_EXPORT Property toProperty(const std::any &a);
267 BASE_EXPORT std::any toAny(const Property &p);
268
269} // namespace base
270
271// This allows you to send Properties to a std::format
272template <>
273struct std::formatter<base::Property> : public std::formatter<string> {
274 template <typename ParseContext>
275 constexpr auto parse(ParseContext &ctx) { return std::formatter<string>::parse(ctx); }
276
277 template <typename FormatContext>
278 constexpr auto format(base::Property const &val, FormatContext &ctx) const {
279 return std::formatter<string>::format(val.to<string>(), ctx);
280 }
281};
282
283// EoF
284
includes std::string and additional functions not included in the standard.
A template-based matrix class, size fixed at compile time. Defaults to symmetric sized matrix.
Definition matrix.h:22
2D quaternion-like utility class. In this case only the angle (in radians) is stored as opposed to th...
Definition quat.h:20
3D quaternion utility class.
Definition quat.h:112
A symmetric 2nd order tensor.
Definition symtensor.h:22
Definition property.h:24
Definition property.h:52
Definition mat.h:28
Definition property.h:47
Definition property.h:43
Definition property.h:49
std::basic_string< char8 > String
std::string of type Char
Definition basebool.h:9
#define BASE_EXPORT
Definition basedef.h:25
constexpr D to(const T &t)
This template function serves as an alternative to static_cast<T>().
Definition to.h:28
2D and 3D quaternion utility classes.
2D and 3D vector utility classes.