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 enum class Type { Int, Double, Bool, String, DVect2,
55 DVect3, I64Vect2, I64Vect3, Matrix, DAVect2,
56 DAVect3, Quat2 , Quat3, Tensor, Null,
57 Array };
58
59 Property(): PropBase(nullptr) {}
60 template <class T> requires PropertyConcepts::NonInt<T> Property(const T &t) : PropBase(t) { }
61 template <class T> requires PropertyConcepts::IntNoBool<T> Property(const T &t) : PropBase(::to<int64>(t)) { }
62 BASE_EXPORT std::partial_ordering operator<=>(const Property &p) const;
63 template <class T> requires PropertyConcepts::NonInt<T> Property &operator=(const T &t) { PropBase::operator=(t); return *this; }
64 template <class T> requires PropertyConcepts::IntNoBool<T> Property &operator=(const T &t) { PropBase::operator=(::to<int64>(t)); return *this; }
65
66 inline Type type() const;
67 BASE_EXPORT std::tuple<Type,UVect2> desc() const;
68 BASE_EXPORT const Property &reset(); // Keep type but set value to default construction.
69 inline bool isNull() const { return type()==Type::Null; }
70 inline bool isValid() const { return not isNull(); }
71
72 // Returns TRUE if the type can be converted to the provided type. Does minimal computation.
73 // In theory we can add more type specializations (int, float, etc) based on existing.
74 template <typename T>
75 bool canConvert() const { static_assert(sizeof(T)==0); return false; } // Default
76 BASE_EXPORT bool canConvert(Type type) const; // Runtime type conversion query
77
78 template <typename T>
79 bool canConvertVec() const;
80
81 // Same as canConvert but takes a Type enum as a template argument.
82 template <Type t>
83 bool canConvertType() const { return canConvert<decltype(std::get<static_cast<int>(t)>(*this))>(); }
84
85 // Converts to the type - throws exeption if not able to convert.
86 template <typename T>
87 T to() const { static_assert(sizeof(T)==0); return false; } // DEFAULT
88 template <typename T>
89 std::vector<T> toVec() const;
90
91 // Save as to<>() but uses the Type enum as the template argument.
92 template <Type t>
93 auto toType() const { return to<decltype(std::get<static_cast<int>(t)>(*this))>(); }
94
95 // Single call test, returns both value and success boolean. Value is default init if
96 // success is false.
97 template <typename T>
98 typename std::tuple<T,bool> toTest() const;
99
100 // Same as toTest<>() but using Type enum.
101 template <Type t>
102 typename std::variant_alternative_t<static_cast<int>(t),Property> toTestType() const;
103
104 template <typename T>
105 void setValue(const T &t) { *this = t; }
106 template <typename T>
107 void setVec(const std::vector<T> &v);
108
109 template <typename T>
110 T value() const { return to<T>(); }
111
112 BASE_EXPORT static string nameFromType(Type t);
113 inline double toDouble() const;
114 inline string toString() const;
115 inline int64 toInt() const;
116 inline uint32 toUInt() const;
117 inline double toDouble(bool *ok) const;
118 inline int64 toInt(bool *ok) const;
119
120 static constexpr Type DVectType(uint32 dim) { return dim==2 ? Type::DVect2 : Type::DVect3; }
121 static constexpr Type DAVectType(uint32 dim) { return dim==2 ? Type::DAVect2 : Type::DAVect3; }
122 static constexpr Type IVectType(uint32 dim) { return dim==2 ? Type::I64Vect2 : Type::I64Vect3; }
123 };
124
125 Property::Type Property::type() const {
126 return static_cast<Type>(index());
127 }
128
129 constexpr auto operator<=>(const base::PropArray &lhs,const base::PropArray &rhs) {
130 auto &vl = static_cast<const std::vector<base::Property> &>(lhs);
131 auto &vr = static_cast<const std::vector<base::Property> &>(rhs);
132 return vl <=> vr;
133 }
134
135 template <> BASE_EXPORT bool Property::canConvert<int64>() const;
136 template <> BASE_EXPORT bool Property::canConvert<double>() const;
137 template <> BASE_EXPORT bool Property::canConvert<bool>() const;
138 template <> BASE_EXPORT bool Property::canConvert<string>() const;
139 template <> BASE_EXPORT bool Property::canConvert<DVect2>() const;
140 template <> BASE_EXPORT bool Property::canConvert<DVect3>() const;
141 template <> BASE_EXPORT bool Property::canConvert<I64Vect2>() const;
142 template <> BASE_EXPORT bool Property::canConvert<I64Vect3>() const;
143 template <> BASE_EXPORT bool Property::canConvert<itasca::Mat>() const;
144 template <> BASE_EXPORT bool Property::canConvert<DAVect2>() const;
145 template <> BASE_EXPORT bool Property::canConvert<DAVect3>() const;
146 template <> BASE_EXPORT bool Property::canConvert<Quat2>() const;
147 template <> BASE_EXPORT bool Property::canConvert<Quat3>() const;
148 template <> BASE_EXPORT bool Property::canConvert<SymTensor>() const;
149 template <> BASE_EXPORT bool Property::canConvert<PropArray>() const;
150
151 template <> BASE_EXPORT int64 Property::to<int64>() const;
152 template <> BASE_EXPORT double Property::to<double>() const;
153 template <> BASE_EXPORT bool Property::to<bool>() const;
154 template <> BASE_EXPORT string Property::to<string>() const;
155 template <> BASE_EXPORT DVect2 Property::to<DVect2>() const;
156 template <> BASE_EXPORT DVect3 Property::to<DVect3>() const;
157 template <> BASE_EXPORT I64Vect2 Property::to<I64Vect2>() const;
158 template <> BASE_EXPORT I64Vect3 Property::to<I64Vect3>() const;
159 template <> BASE_EXPORT itasca::Mat Property::to<itasca::Mat>() const;
160 template <> BASE_EXPORT DAVect2 Property::to<DAVect2>() const;
161 template <> BASE_EXPORT DAVect3 Property::to<DAVect3>() const;
162 template <> BASE_EXPORT Quat2 Property::to<Quat2>() const;
163 template <> BASE_EXPORT Quat3 Property::to<Quat3>() const;
164 template <> BASE_EXPORT SymTensor Property::to<SymTensor>() const;
165 template <> BASE_EXPORT PropArray Property::to<PropArray>() const;
166
167 class PropertyConvertException : public Exception {
168 public:
169 PropertyConvertException(Property::Type from,Property::Type to) :
170 Exception("Error converting Property from {} to {}.",
171 Property::nameFromType(from),Property::nameFromType(to)) {
172 }
173 };
174
175 template <typename T>
176 void Property::setVec(const std::vector<T> &v) {
177 PropArray pa;
178 Type t{};
179 for (size_t i=0;i<v.size();++i) {
180 pa.push_back({});
181 pa.back().setValue(v[i]);
182 if (not i) t = pa.back().type();
183 else if (t!=pa.back().type()) throw Exception("All elements of a property array must be of the same type.");
184 }
185 operator=(pa);
186 }
187
188 double Property::toDouble() const { return to<double>(); }
189 string Property::toString() const { return to<string>(); }
190 int64 Property::toInt() const { return to<int64>();}
191 uint32 Property::toUInt() const { return static_cast<uint32>(to<int64>()); }
192
193 double Property::toDouble(bool *ok) const {
194 *ok = canConvert<double>();
195 if (*ok) return to<double>();
196 return 0.0;
197 }
198
199 int64 Property::toInt(bool *ok) const {
200 *ok = canConvert<int64>();
201 if (*ok) return to<int64>();
202 return 0;
203 }
204
205 template <typename T>
206 typename std::tuple<T,bool> Property::toTest() const {
207 bool b = canConvert<T>();
208 if (b)
209 return {to<T>(),b};
210 return {T{},false};
211 }
212
213 template <Property::Type t>
214 typename std::variant_alternative_t<static_cast<int>(t),Property> Property::toTestType() const {
215 using target_type = decltype(std::get<static_cast<int>(t)>(*this));
216 using return_type = std::tuple<target_type,bool>;
217 bool b = canConvert<target_type>();
218 if (b) return return_type(to<target_type>(),true);
219 return return_type(target_type{},false);
220 }
221
222 template <typename T>
223 bool Property::canConvertVec() const {
224 if (type()!=Type::Array) return false;
225 auto &a = std::get<PropArray>(*this);
226 if (not a.size()) return true;
227 return a[0].canConvert<T>();
228 }
229
230 template <typename T>
231 std::vector<T> Property::toVec() const {
232 if (type()!=Type::Array) throw PropertyConvertException(type(),Type::Array);
233 auto &a = std::get<PropArray>(*this);
234 if (not a.size()) return {};
235 std::vector<T> ret;
236 for (auto &v : a)
237 ret.push_back(v.to<T>());
238 return ret;
239 }
240
241 // This allows using the Type enum as a selector in a get, so
242 // get<Property::Bool>(p);
243 template <Property::Type t>
244 const auto &get(const Property &v) { return std::get<static_cast<int>(t)>(v); }
245
246 // String conversion, using the base::ts standard
247 template <>
248 BASE_EXPORT string ts<base::Property>(const base::Property &p, int width, char notation, int precision, char fill);
249
250 // Description of a property type. The information necessary to parse.
251 struct PropDesc {
252 PropDesc() { }
253 PropDesc(const string &name,Property::Type type,UVect2 size) : name_(name), type_(type), size_(size) { }
254 BASE_EXPORT PropDesc(const string &name,const Property &prop);
255 string name_;
256 Property::Type type_ = Property::Type::Int;
257 UVect2 size_ = UVect2(0);
258 auto operator<=>(const PropDesc &p) const = default;
259 };
260
261 BASE_EXPORT Property toProperty(const std::any &a);
262 BASE_EXPORT std::any toAny(const Property &p);
263
264} // namespace base
265
266// This allows you to send Properties to a std::format
267template <>
268struct std::formatter<base::Property> : public std::formatter<string> {
269 template <typename ParseContext>
270 constexpr auto parse(ParseContext &ctx) { return std::formatter<string>::parse(ctx); }
271
272 template <typename FormatContext>
273 constexpr auto format(base::Property const &val, FormatContext &ctx) const {
274 return std::formatter<string>::format(val.to<string>(), ctx);
275 }
276};
277
278// EoF
279
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.