Sen API
Sen Libraries
Loading...
Searching...
No Matches
gen.h
Go to the documentation of this file.
1// === gen.h ===========================================================================================================
2// Sen Infrastructure
3// Released under the Apache License v2.0 (SPDX-License-Identifier Apache-2.0).
4// See the LICENSE.txt file for more information.
5// © Airbus SAS, Airbus Helicopters, and Airbus Defence and Space SAU/GmbH/SAS.
6// =====================================================================================================================
7
8#ifndef SEN_CORE_OBJ_DETAIL_GEN_H
9#define SEN_CORE_OBJ_DETAIL_GEN_H
10
11// sen
16#include "sen/core/base/span.h"
18#include "sen/core/io/util.h"
19#include "sen/core/lang/vm.h"
40
41// std
42#include <initializer_list> // NOLINT(misc-include-cleaner): used by not visible due to macros
43#include <iterator> // NOLINT(misc-include-cleaner): used by not visible due to macros
44#include <optional>
45#include <type_traits>
46#include <utility>
47
48#define SEN_IMPL_GEN_NATIVE_MEMBERS \
49protected: \
50 [[nodiscard]] inline ::sen::Var senImplGetPropertyImpl(::sen::MemberHash propertyId) const override; \
51 inline void senImplSetNextPropertyUntyped(::sen::MemberHash propertyId, const ::sen::Var& value) override; \
52 [[nodiscard]] inline ::sen::Var senImplGetNextPropertyUntyped(::sen::MemberHash propertyId) const override; \
53 [[nodiscard]] inline uint32_t senImplComputeMaxReliableSerializedPropertySizeImpl() const override; \
54 inline void senImplStreamCall(::sen::MemberHash methodId, ::sen::InputStream& in, ::sen::StreamCallForwarder&& func) \
55 override; \
56 inline void senImplVariantCall( \
57 ::sen::MemberHash methodId, const ::sen::VarList& args, ::sen::VariantCallForwarder&& func) override; \
58 inline void senImplCommitImpl(::sen::TimeStamp time) override; \
59 inline void senImplWriteChangedPropertiesToStream( \
60 ::sen::OutputStream& confirmed, ::sen::impl::BufferProvider uni, ::sen::impl::BufferProvider multi) override; \
61 inline void senImplWriteAllPropertiesToStream(::sen::OutputStream& out) const override; \
62 inline void senImplWriteStaticPropertiesToStream(::sen::OutputStream& out) const override; \
63 inline void senImplWriteDynamicPropertiesToStream(::sen::OutputStream& out) const override; \
64 inline void senImplRemoveTypedConnection(::sen::ConnId id) override; \
65 [[nodiscard]] inline ::sen::impl::FieldValueGetter senImplGetFieldValueGetter( \
66 ::sen::MemberHash propertyId, ::sen::Span<uint16_t> fields) const override; \
67 inline void invokeAllPropertyCallbacks() override;
68
70#define SEN_IMPL_GEN_BASE_CLASS(classname) \
71 SEN_IMPL_GEN_NATIVE_MEMBERS \
72 \
73private: \
74 bool somePropertyIsDirty_ = false; \
75 \
76public: \
77 inline classname(std::string name, const ::sen::VarMap& args); \
78 ~classname() override = default; \
79 [[nodiscard]] inline ::sen::ConstTypeHandle<::sen::ClassType> getClass() const noexcept override; \
80 [[nodiscard]] static inline ::sen::ConstTypeHandle<::sen::ClassType> meta() noexcept; \
81 \
82private:
83
85#define SEN_IMPL_GEN_REMOTE_CLASS(classname) \
86public: \
87 explicit classname(::sen::impl::RemoteObjectInfo&& info); \
88 ~classname() override = default; \
89 \
90protected: \
91 void senImplRemoveTypedConnection(::sen::ConnId id) override; \
92 void senImplWriteAllPropertiesToStream(::sen::OutputStream& out) const override; \
93 void senImplWriteStaticPropertiesToStream(::sen::OutputStream& out) const override; \
94 void senImplWriteDynamicPropertiesToStream(::sen::OutputStream& out) const override; \
95 [[nodiscard]] ::sen::Var senImplGetPropertyImpl(::sen::MemberHash propertyId) const override; \
96 [[nodiscard]] bool readPropertyFromStream(::sen::MemberHash id, ::sen::InputStream& in, bool initialState) override; \
97 [[nodiscard]] ::sen::Var deserializeMethodReturnValueAsVariant(::sen::MemberHash methodId, ::sen::InputStream& in) \
98 const override; \
99 void serializeMethodArgumentsFromVariants( \
100 ::sen::MemberHash methodId, const ::sen::VarList& args, ::sen::OutputStream& out) const override; \
101 void drainInputs() override; \
102 void eventReceived(::sen::MemberHash eventId, ::sen::TimeStamp creationTime, const ::sen::Span<const uint8_t>& args) \
103 override; \
104 void invokeAllPropertyCallbacks() override; \
105 \
106private:
107
109#define SEN_IMPL_GEN_LOCAL_PROXY_CLASS(classname) \
110public: \
111 explicit classname(::sen::NativeObject* owner, const std::string& localPrefix); \
112 ~classname() override = default; \
113 \
114protected: \
115 void senImplWriteAllPropertiesToStream(::sen::OutputStream& out) const override; \
116 void senImplWriteStaticPropertiesToStream(::sen::OutputStream& out) const override; \
117 void senImplWriteDynamicPropertiesToStream(::sen::OutputStream& out) const override; \
118 void senImplRemoveTypedConnection(::sen::ConnId id) override; \
119 [[nodiscard]] ::sen::Var senImplGetPropertyImpl(::sen::MemberHash propertyId) const override; \
120 void drainInputsImpl(::sen::TimeStamp lastCommitTime) override; \
121 \
122private:
123
125#define SEN_IMPL_GEN_UNBOUNDED_SEQUENCE(classname, elementtype) \
126 class classname final: private std::vector<elementtype> \
127 { \
128 using Parent = std::vector<elementtype>; \
129 \
130 public: \
131 using Parent::value_type; \
132 \
133 using Parent::Parent; \
134 using Parent::operator=; \
135 using Parent::assign; \
136 \
137 using Parent::at; \
138 using Parent::operator[]; \
139 using Parent::front; \
140 using Parent::back; \
141 /* std::vector<bool> declares no data(), and libc++ and the MSVC STL do not \
142 declare it at all, so a using-declaration is ill-formed there. A member \
143 template is instantiated only when called: a bool sequence has no data(). */ \
144 template <typename E = elementtype> \
145 auto data() \
146 { \
147 return static_cast<std::vector<E>&>(*this).data(); \
148 } \
149 template <typename E = elementtype> \
150 auto data() const \
151 { \
152 return static_cast<const std::vector<E>&>(*this).data(); \
153 } \
154 \
155 using Parent::begin; \
156 using Parent::cbegin; \
157 using Parent::rbegin; \
158 using Parent::crbegin; \
159 using Parent::end; \
160 using Parent::cend; \
161 using Parent::rend; \
162 using Parent::crend; \
163 \
164 using Parent::empty; \
165 using Parent::size; \
166 using Parent::max_size; \
167 using Parent::reserve; \
168 using Parent::capacity; \
169 using Parent::shrink_to_fit; \
170 \
171 using Parent::clear; \
172 using Parent::insert; \
173 using Parent::emplace; \
174 using Parent::erase; \
175 using Parent::push_back; \
176 using Parent::emplace_back; \
177 using Parent::pop_back; \
178 using Parent::resize; \
179 using Parent::swap; \
180 \
181 constexpr const Parent& asVector() const& noexcept { return *this; } \
182 Parent asVector() && noexcept(std::is_nothrow_move_constructible_v<Parent>) { return std::move(*this); } \
183 \
184 friend bool operator==(const classname& lhs, const classname& rhs) { return lhs.asVector() == rhs.asVector(); } \
185 friend bool operator!=(const classname& lhs, const classname& rhs) { return !(lhs == rhs); } \
186 \
187 template <typename P = Parent> \
188 std::enable_if_t<sen::HasOperator<P>::lt, bool> operator<(const classname& other) const \
189 { \
190 return static_cast<const P&>(*this) < static_cast<const P&>(other); \
191 } \
192 \
193 template <typename P = Parent> \
194 std::enable_if_t<sen::HasOperator<P>::lt, bool> operator>(const classname& other) const \
195 { \
196 return static_cast<const P&>(other) < static_cast<const P&>(*this); \
197 } \
198 };
201#define SEN_IMPL_GEN_BOUNDED_SEQUENCE(classname, element, maxSize) \
202 struct classname final: public ::sen::StaticVector<element, maxSize> \
203 { \
204 using Parent = ::sen::StaticVector<element, maxSize>; \
205 using Parent::Parent; \
206 using Parent::operator=; \
207 \
208 template <typename P = Parent> \
209 std::enable_if_t<sen::HasOperator<P>::lt, bool> operator<(const classname& other) const \
210 { \
211 return static_cast<const P&>(*this) < static_cast<const P&>(other); \
212 } \
213 \
214 template <typename P = Parent> \
215 std::enable_if_t<sen::HasOperator<P>::lt, bool> operator>(const classname& other) const \
216 { \
217 return static_cast<const P&>(other) < static_cast<const P&>(*this); \
218 } \
219 };
222#define SEN_IMPL_GEN_FIXED_SEQUENCE(classname, element, num_elements) \
223 class classname final: private std::array<element, num_elements> \
224 { \
225 using Parent = std::array<element, num_elements>; \
226 \
227 public: \
228 using Parent::value_type; \
229 using Parent::reference; \
230 using Parent::const_reference; \
231 using Parent::pointer; \
232 using Parent::const_pointer; \
233 using Parent::iterator; \
234 using Parent::const_iterator; \
235 using Parent::reverse_iterator; \
236 using Parent::const_reverse_iterator; \
237 \
238 using Parent::Parent; \
239 using Parent::operator=; \
240 \
241 using Parent::at; \
242 using Parent::operator[]; \
243 using Parent::front; \
244 using Parent::back; \
245 using Parent::data; \
246 \
247 using Parent::begin; \
248 using Parent::cbegin; \
249 using Parent::rbegin; \
250 using Parent::crbegin; \
251 using Parent::end; \
252 using Parent::cend; \
253 using Parent::rend; \
254 using Parent::crend; \
255 \
256 using Parent::empty; \
257 using Parent::size; \
258 using Parent::max_size; \
259 \
260 using Parent::fill; \
261 using Parent::swap; \
262 \
263 template <typename Y, typename = std::enable_if_t<std::is_convertible_v<Y, element>, int>> \
264 constexpr classname(std::initializer_list<Y> elems): Parent() \
265 { \
266 using DifferenceType = \
267 typename std::iterator_traits<typename std::initializer_list<Y>::iterator>::difference_type; \
268 SEN_ASSERT(std::distance(std::begin(elems), std::end(elems)) <= static_cast<DifferenceType>(num_elements)); \
269 std::move(std::begin(elems), \
270 std::next(std::begin(elems), \
271 std::min(std::distance(std::begin(elems), std::end(elems)), \
272 static_cast<DifferenceType>(num_elements))), \
273 std::begin(*this)); \
274 } \
275 \
276 constexpr const Parent& asArray() const& noexcept { return *this; } \
277 Parent asArray() && noexcept(std::is_nothrow_move_constructible_v<element>) { return std::move(*this); } \
278 \
279 friend bool operator==(const classname& lhs, const classname& rhs) { return lhs.asArray() == rhs.asArray(); } \
280 friend bool operator!=(const classname& lhs, const classname& rhs) { return !(lhs == rhs); } \
281 \
282 template <typename P = Parent> \
283 std::enable_if_t<sen::HasOperator<P>::lt, bool> operator<(const classname& other) const \
284 { \
285 return static_cast<const P&>(*this) < static_cast<const P&>(other); \
286 } \
287 \
288 template <typename P = Parent> \
289 std::enable_if_t<sen::HasOperator<P>::lt, bool> operator>(const classname& other) const \
290 { \
291 return static_cast<const P&>(other) < static_cast<const P&>(*this); \
292 } \
293 };
296#define SEN_IMPL_GEN_STRUCT_OPERATORS(classname, doExport) \
297 SEN_MAYBE_EXPORT(doExport) std::ostream& operator<<(std::ostream& out, const classname& val); \
298 SEN_MAYBE_EXPORT(doExport) bool operator==(const classname& lhs, const classname& rhs); \
299 SEN_MAYBE_EXPORT(doExport) bool operator!=(const classname& lhs, const classname& rhs);
302#define SEN_IMPL_GEN_OPTIONAL(classname, elementtype) \
303 class classname final: private std::optional<elementtype> \
304 { \
305 using Parent = std::optional<elementtype>; \
306 \
307 public: \
308 using Parent::value_type; \
309 \
310 using Parent::Parent; \
311 using Parent::operator=; \
312 \
313 using Parent::operator->; \
314 using Parent::operator*; \
315 using Parent::operator bool; \
316 using Parent::has_value; \
317 using Parent::value; \
318 using Parent::value_or; \
319 \
320 using Parent::reset; \
321 using Parent::swap; \
322 using Parent::emplace; \
323 \
324 constexpr const Parent& asOptional() const& noexcept { return *this; } \
325 Parent asOptional() && noexcept(std::is_nothrow_move_constructible_v<Parent>) { return std::move(*this); } \
326 \
327 friend constexpr bool operator==(const classname& lhs, const classname& rhs) \
328 { \
329 return lhs.asOptional() == rhs.asOptional(); \
330 } \
331 friend constexpr bool operator!=(const classname& lhs, const classname& rhs) { return !(lhs == rhs); } \
332 };
335#define SEN_IMPL_GEN_OPTIONAL_TRAITS(classname, doExport) \
336 template <> \
337 struct MetaTypeTrait<classname> \
338 { \
339 [[nodiscard]] SEN_MAYBE_EXPORT(doExport) static ConstTypeHandle<OptionalType> meta(); \
340 }; \
341 template <> \
342 struct VariantTraits<classname>: private OptionalTraitsBase<classname> \
343 { \
344 using OptionalTraitsBase<classname>::valueToVariant; \
345 using OptionalTraitsBase<classname>::variantToValue; \
346 }; \
347 template <> \
348 struct SerializationTraits<classname>: private OptionalTraitsBase<classname> \
349 { \
350 using OptionalTraitsBase<classname>::write; \
351 using OptionalTraitsBase<classname>::read; \
352 using OptionalTraitsBase<classname>::serializedSize; \
353 using OptionalTraitsBase<classname>::toJsonString; \
354 using OptionalTraitsBase<classname>::fromJsonString; \
355 };
358#define SEN_IMPL_GEN_ENUM_TRAITS(classname, doExport) \
359 template <> \
360 struct MetaTypeTrait<classname> \
361 { \
362 [[nodiscard]] SEN_MAYBE_EXPORT(doExport) static ConstTypeHandle<EnumType> meta(); \
363 }; \
364 template <> \
365 struct SEN_MAYBE_EXPORT(doExport) VariantTraits<classname>: private EnumTraitsBase<classname> \
366 { \
367 using EnumTraitsBase<classname>::valueToVariant; \
368 using EnumTraitsBase<classname>::variantToValue; \
369 }; \
370 template <> \
371 struct SEN_MAYBE_EXPORT(doExport) SerializationTraits<classname>: private EnumTraitsBase<classname> \
372 { \
373 using EnumTraitsBase<classname>::write; \
374 using EnumTraitsBase<classname>::read; \
375 using EnumTraitsBase<classname>::serializedSize; \
376 using EnumTraitsBase<classname>::toJsonString; \
377 using EnumTraitsBase<classname>::fromJsonString; \
378 }; \
379 template <> \
380 struct SEN_MAYBE_EXPORT(doExport) StringConversionTraits<classname> \
381 { \
382 [[nodiscard]] static std::string_view toString(classname val); \
383 [[nodiscard]] static classname fromString(std::string_view val); \
384 }; \
385 \
386 [[nodiscard]] SEN_MAYBE_EXPORT(doExport) std::string_view toString(classname value);
389#define SEN_IMPL_GEN_SEQUENCE_TRAITS(classname, doExport) \
390 template <> \
391 struct MetaTypeTrait<classname> \
392 { \
393 [[nodiscard]] SEN_MAYBE_EXPORT(doExport) static sen::ConstTypeHandle<SequenceType> meta(); \
394 }; \
395 template <> \
396 struct SEN_MAYBE_EXPORT(doExport) VariantTraits<classname>: private SequenceTraitsBase<classname> \
397 { \
398 using SequenceTraitsBase<classname>::valueToVariant; \
399 using SequenceTraitsBase<classname>::variantToValue; \
400 }; \
401 template <> \
402 struct SEN_MAYBE_EXPORT(doExport) SerializationTraits<classname>: private SequenceTraitsBase<classname> \
403 { \
404 using SequenceTraitsBase<classname>::write; \
405 using SequenceTraitsBase<classname>::read; \
406 using SequenceTraitsBase<classname>::serializedSize; \
407 using SequenceTraitsBase<classname>::toJsonString; \
408 using SequenceTraitsBase<classname>::fromJsonString; \
409 };
412#define SEN_IMPL_GEN_ARRAY_TRAITS(classname, doExport) \
413 template <> \
414 struct MetaTypeTrait<classname> \
415 { \
416 [[nodiscard]] SEN_MAYBE_EXPORT(doExport) static ConstTypeHandle<SequenceType> meta(); \
417 }; \
418 template <> \
419 struct SEN_MAYBE_EXPORT(doExport) VariantTraits<classname>: private ArrayTraitsBase<classname> \
420 { \
421 using ArrayTraitsBase<classname>::valueToVariant; \
422 using ArrayTraitsBase<classname>::variantToValue; \
423 }; \
424 template <> \
425 struct SEN_MAYBE_EXPORT(doExport) SerializationTraits<classname>: private ArrayTraitsBase<classname> \
426 { \
427 using ArrayTraitsBase<classname>::write; \
428 using ArrayTraitsBase<classname>::read; \
429 using ArrayTraitsBase<classname>::serializedSize; \
430 using ArrayTraitsBase<classname>::toJsonString; \
431 using ArrayTraitsBase<classname>::fromJsonString; \
432 };
435#define SEN_IMPL_GEN_STRUCT_TRAITS(classname, doExport) \
436 template <> \
437 struct MetaTypeTrait<classname> \
438 { \
439 [[nodiscard]] SEN_MAYBE_EXPORT(doExport) static ConstTypeHandle<StructType> meta(); \
440 }; \
441 template <> \
442 struct SEN_MAYBE_EXPORT(doExport) VariantTraits<classname>: protected StructTraitsBase \
443 { \
444 static void valueToVariant(const classname& val, Var& var); \
445 static void variantToValue(const Var& var, classname& val); \
446 static std::function<lang::Value(const void*)> getFieldValueGetterFunction(Span<uint16_t> fields); \
447 }; \
448 template <> \
449 struct SEN_MAYBE_EXPORT(doExport) SerializationTraits<classname>: protected StructTraitsBase \
450 { \
451 static void write(OutputStream& out, const classname& val); \
452 static void read(InputStream& in, classname& val); \
453 [[nodiscard]] static uint32_t serializedSize(const classname& val) noexcept; \
454 static std::string toJsonString(const classname& val); \
455 static void fromJsonString(const std::string& str, classname& val); \
456 };
459#define SEN_IMPL_GEN_VARIANT_TRAITS(classname, doExport) \
460 template <> \
461 struct SEN_MAYBE_EXPORT(doExport) MetaTypeTrait<classname> \
462 { \
463 [[nodiscard]] static ConstTypeHandle<VariantType> meta(); \
464 }; \
465 template <> \
466 struct SEN_MAYBE_EXPORT(doExport) VariantTraits<classname>: protected VariantTraitsBase<classname> \
467 { \
468 static void valueToVariant(const classname& val, Var& var); \
469 static void variantToValue(const Var& var, classname& val); \
470 static std::function<lang::Value(const void*)> getFieldValueGetterFunction(Span<uint16_t> fields); \
471 using VariantTraitsBase<classname>::tryPrintField; \
472 }; \
473 template <> \
474 struct SEN_MAYBE_EXPORT(doExport) SerializationTraits<classname>: protected VariantTraitsBase<classname> \
475 { \
476 static void write(OutputStream& out, const classname& val); \
477 static void read(InputStream& in, classname& val); \
478 [[nodiscard]] static uint32_t serializedSize(const classname& val) noexcept; \
479 static std::string toJsonString(const classname& val); \
480 static void fromJsonString(const std::string& str, classname& val); \
481 };
484#define SEN_IMPL_GEN_CLASS_META_TRAITS(classname, doExport) \
485 template <> \
486 struct MetaTypeTrait<classname> \
487 { \
488 [[nodiscard]] SEN_MAYBE_EXPORT(doExport) static ConstTypeHandle<ClassType> meta(); \
489 };
492#define SEN_IMPL_GEN_CLASS_TRAITS_TEMPLATE(interfaceName, remoteProxy, localProxy, baseName) \
493 template <> \
494 struct SenClassRelation<interfaceName> \
495 { \
496 using InterfaceType = interfaceName; \
497 template <typename T> \
498 using BaseType = baseName<T>; \
499 static constexpr bool isBaseTypeTemplate = true; \
500 using RemoteProxyType = remoteProxy; \
501 using LocalProxyType = localProxy; \
502 }; \
503 template <> \
504 struct SenClassRelation<remoteProxy> \
505 { \
506 using InterfaceType = interfaceName; \
507 template <typename T> \
508 using BaseType = baseName<T>; \
509 static constexpr bool isBaseTypeTemplate = true; \
510 using RemoteProxyType = remoteProxy; \
511 using LocalProxyType = localProxy; \
512 }; \
513 template <> \
514 struct SenClassRelation<localProxy> \
515 { \
516 using InterfaceType = interfaceName; \
517 template <typename T> \
518 using BaseType = baseName<T>; \
519 static constexpr bool isBaseTypeTemplate = true; \
520 using RemoteProxyType = remoteProxy; \
521 using LocalProxyType = localProxy; \
522 }; \
523 template <typename T> \
524 struct SenClassRelation<baseName<T>> \
525 { \
526 using InterfaceType = interfaceName; \
527 template <typename U> \
528 using BaseType = baseName<U>; \
529 static constexpr bool isBaseTypeTemplate = true; \
530 using RemoteProxyType = remoteProxy; \
531 using LocalProxyType = localProxy; \
532 };
535#define SEN_IMPL_GEN_CLASS_TRAITS_NORMAL(interfaceName, remoteProxy, localProxy, baseName) \
536 template <> \
537 struct SenClassRelation<interfaceName> \
538 { \
539 using InterfaceType = interfaceName; \
540 using BaseType = baseName; \
541 static constexpr bool isBaseTypeTemplate = false; \
542 using RemoteProxyType = remoteProxy; \
543 using LocalProxyType = localProxy; \
544 }; \
545 template <> \
546 struct SenClassRelation<remoteProxy> \
547 { \
548 using InterfaceType = interfaceName; \
549 using BaseType = baseName; \
550 static constexpr bool isBaseTypeTemplate = false; \
551 using RemoteProxyType = remoteProxy; \
552 using LocalProxyType = localProxy; \
553 }; \
554 template <> \
555 struct SenClassRelation<localProxy> \
556 { \
557 using InterfaceType = interfaceName; \
558 using BaseType = baseName; \
559 static constexpr bool isBaseTypeTemplate = false; \
560 using RemoteProxyType = remoteProxy; \
561 using LocalProxyType = localProxy; \
562 }; \
563 template <> \
564 struct SenClassRelation<baseName> \
565 { \
566 using InterfaceType = interfaceName; \
567 using BaseType = baseName; \
568 static constexpr bool isBaseTypeTemplate = false; \
569 using RemoteProxyType = remoteProxy; \
570 using LocalProxyType = localProxy; \
571 };
574#define SEN_IMPL_GEN_QUANTITY_TRAITS(classname, maxVal, minVal, doExport) \
575 template <> \
576 struct MetaTypeTrait<classname> \
577 { \
578 [[nodiscard]] SEN_MAYBE_EXPORT(doExport) static ConstTypeHandle<QuantityType> meta(); \
579 }; \
580 template <> \
581 struct SEN_MAYBE_EXPORT(doExport) VariantTraits<classname>: private QuantityTraitsBase<classname> \
582 { \
583 using QuantityTraitsBase<classname>::valueToVariant; \
584 using QuantityTraitsBase<classname>::variantToValue; \
585 }; \
586 template <> \
587 struct SEN_MAYBE_EXPORT(doExport) SerializationTraits<classname>: private QuantityTraitsBase<classname> \
588 { \
589 using QuantityTraitsBase<classname>::write; \
590 using QuantityTraitsBase<classname>::read; \
591 using QuantityTraitsBase<classname>::serializedSize; \
592 using QuantityTraitsBase<classname>::toJsonString; \
593 using QuantityTraitsBase<classname>::fromJsonString; \
594 }; \
595 template <> \
596 struct SEN_MAYBE_EXPORT(doExport) QuantityTraits<classname> \
597 { \
598 using ValueType = typename classname::ValueType; \
599 \
600 static constexpr ValueType max = maxVal; \
601 static constexpr ValueType min = minVal; \
602 \
603 [[nodiscard]] static ::std::optional<const sen::Unit*> unit() noexcept; \
604 [[nodiscard]] static const sen::Unit& unit(sen::Unit::EnsureTag); \
605 };
606
607#endif // SEN_CORE_OBJ_DETAIL_GEN_H
The following macros implement a replacement of assert that is connected to the overall fault handlin...