COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
Variant.h
1//
2// Copyright 2017 - 2024 (C). Alex Robenko. All rights reserved.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
8#pragma once
9
10#include <type_traits>
11#include <algorithm>
12
14#include "comms/Assert.h"
15#include "comms/ErrorStatus.h"
16#include "comms/util/Tuple.h"
18#include "comms/field/details/VersionStorage.h"
19#include "comms/field/details/FieldOpHelpers.h"
20#include "comms/field/details/MembersVersionDependency.h"
21#include "comms/details/tag.h"
22#include "comms/field/tag.h"
23#include "CommonFuncs.h"
24
25COMMS_MSVC_WARNING_PUSH
26COMMS_MSVC_WARNING_DISABLE(4324) // Disable warning about alignment padding
27
28namespace comms
29{
30
31namespace field
32{
33
34namespace basic
35{
36
37namespace details
38{
39
40template<typename...>
41class VariantFieldConstructHelper
42{
43public:
44 VariantFieldConstructHelper(void* storage) : storage_(storage) {}
45
46 template <std::size_t TIdx, typename TField>
47 void operator()() const
48 {
49 new (storage_) TField;
50 }
51private:
52 void* storage_ = nullptr;
53};
54
55template<typename...>
56class VariantLengthCalcHelper
57{
58public:
59 VariantLengthCalcHelper(std::size_t& len, const void* storage)
60 : len_(len),
61 storage_(storage)
62 {
63 }
64
65 template <std::size_t TIdx, typename TField>
66 void operator()()
67 {
68 len_ = reinterpret_cast<const TField*>(storage_)->length();
69 }
70
71private:
72 std::size_t& len_;
73 const void* storage_;
74};
75
76template<typename...>
77class VariantFieldCopyConstructHelper
78{
79public:
80 VariantFieldCopyConstructHelper(void* storage, const void* other) : storage_(storage), other_(other) {}
81
82 template <std::size_t TIdx, typename TField>
83 void operator()() const
84 {
85 new (storage_) TField(*(reinterpret_cast<const TField*>(other_)));
86 }
87
88private:
89 void* storage_ = nullptr;
90 const void* other_ = nullptr;
91};
92
93template<typename...>
94class VariantFieldMoveConstructHelper
95{
96public:
97 VariantFieldMoveConstructHelper(void* storage, void* other) : storage_(storage), other_(other) {}
98
99 template <std::size_t TIdx, typename TField>
100 void operator()() const
101 {
102 new (storage_) TField(std::move(*(reinterpret_cast<const TField*>(other_))));
103 }
104
105private:
106 void* storage_ = nullptr;
107 void* other_ = nullptr;
108};
109
110template<typename...>
111class VariantFieldDestructHelper
112{
113public:
114 VariantFieldDestructHelper(void* storage) : storage_(storage) {}
115
116 template <std::size_t TIdx, typename TField>
117 void operator()() const
118 {
119 reinterpret_cast<TField*>(storage_)->~TField();
120 }
121private:
122 void* storage_ = nullptr;
123};
124
125template <typename...>
126class VariantFieldValidCheckHelper
127{
128public:
129 VariantFieldValidCheckHelper(bool& result, const void* storage)
130 : result_(result),
131 storage_(storage)
132 {
133 }
134
135 template <std::size_t TIdx, typename TField>
136 void operator()()
137 {
138 result_ = reinterpret_cast<const TField*>(storage_)->valid();
139 }
140
141private:
142 bool& result_;
143 const void* storage_;
144};
145
146template <typename...>
147class VariantFieldRefreshHelper
148{
149public:
150 VariantFieldRefreshHelper(bool& result, void* storage)
151 : result_(result),
152 storage_(storage)
153 {
154 }
155
156 template <std::size_t TIdx, typename TField>
157 void operator()()
158 {
159 result_ = reinterpret_cast<TField*>(storage_)->refresh();
160 }
161
162private:
163 bool& result_;
164 void* storage_ = nullptr;
165};
166
167template <typename TFunc>
168class VariantExecHelper
169{
170 static_assert(std::is_lvalue_reference<TFunc>::value || std::is_rvalue_reference<TFunc>::value,
171 "Wrong type of template parameter");
172public:
173 template <typename U>
174 VariantExecHelper(void* storage, U&& func) : storage_(storage), func_(std::forward<U>(func)) {}
175
176 template <std::size_t TIdx, typename TField>
177 void operator()()
178 {
179#if COMMS_IS_MSVC
180 // VS compiler
181 func_.operator()<TIdx>(*(reinterpret_cast<TField*>(storage_)));
182#else // #if COMMS_IS_MSVC
183 func_.template operator()<TIdx>(*(reinterpret_cast<TField*>(storage_)));
184#endif // #if COMMS_IS_MSVC
185 }
186private:
187 void* storage_ = nullptr;
188 TFunc func_;
189};
190
191template <typename TFunc>
192class VariantConstExecHelper
193{
194 static_assert(std::is_lvalue_reference<TFunc>::value || std::is_rvalue_reference<TFunc>::value,
195 "Wrong type of template parameter");
196public:
197 template <typename U>
198 VariantConstExecHelper(const void* storage, U&& func) : storage_(storage), func_(std::forward<U>(func)) {}
199
200 template <std::size_t TIdx, typename TField>
201 void operator()()
202 {
203#if COMMS_IS_MSVC
204 // VS compiler
205 func_.operator()<TIdx>(*(reinterpret_cast<const TField*>(storage_)));
206#else // #if COMMS_IS_MSVC
207 func_.template operator()<TIdx>(*(reinterpret_cast<const TField*>(storage_)));
208#endif // #if COMMS_IS_MSVC
209 }
210private:
211 const void* storage_ = nullptr;
212 TFunc func_;
213};
214
215
216template <typename TIter, typename TVerBase, bool TVerDependent>
217class VariantReadHelper
218{
219 template <typename... TParams>
220 using VersionDependentTag = comms::details::tag::Tag1<>;
221
222 template <typename... TParams>
223 using NoVersionDependencyTag = comms::details::tag::Tag2<>;
224
225 template <typename... TParams>
226 using VersionTag =
227 typename comms::util::LazyShallowConditional<
228 TVerDependent
229 >::template Type<
230 VersionDependentTag,
231 NoVersionDependencyTag
232 >;
233public:
234 VariantReadHelper(
235 std::size_t& idx,
237 TIter& iter,
238 std::size_t len,
239 void* storage,
240 TVerBase& verBase)
241 : idx_(idx),
242 es_(es),
243 iter_(iter),
244 len_(len),
245 storage_(storage),
246 verBase_(verBase)
247 {
248 using IterType = typename std::decay<decltype(iter)>::type;
249 using IterCategory = typename std::iterator_traits<IterType>::iterator_category;
250 static_assert(std::is_base_of<std::random_access_iterator_tag, IterCategory>::value,
251 "Variant field only supports read with random access iterators");
252
254 }
255
256 template <typename TField>
257 void operator()()
258 {
259 if (readComplete_) {
260 return;
261 }
262
263 auto* field = new (storage_) TField;
264 updateMemberVersionInternal(*field, VersionTag<>());
265
266 auto iterTmp = iter_;
267 auto es = field->read(iterTmp, len_);
268 if (es == comms::ErrorStatus::Success) {
269 iter_ = iterTmp;
270 es_ = es;
271 readComplete_ = true;
272 return;
273 }
274
275 field->~TField();
276
279 es_ = es;
280 }
281
282 ++idx_;
283 }
284
285private:
286 template <typename TField, typename... TParams>
287 void updateMemberVersionInternal(TField& field, NoVersionDependencyTag<TParams...>)
288 {
289 static_cast<void>(field);
290 }
291
292 template <typename TField, typename... TParams>
293 void updateMemberVersionInternal(TField& field, VersionDependentTag<TParams...>)
294 {
295 field.setVersion(verBase_.getVersion());
296 }
297
298 std::size_t& idx_;
300 TIter& iter_;
301 std::size_t len_ = 0;
302 void* storage_ = nullptr;
303 TVerBase& verBase_;
304 bool readComplete_ = false;
305};
306
307template <typename TIter>
308class VariantFieldWriteHelper
309{
310public:
311 VariantFieldWriteHelper(ErrorStatus& es, TIter& iter, std::size_t len, const void* storage)
312 : es_(es),
313 iter_(iter),
314 len_(len),
315 storage_(storage)
316 {
317 }
318
319 template <std::size_t TIdx, typename TField>
320 void operator()()
321 {
322 es_ = reinterpret_cast<const TField*>(storage_)->write(iter_, len_);
323 }
324
325private:
326 ErrorStatus& es_;
327 TIter& iter_;
328 std::size_t len_ = 0U;
329 const void* storage_ = nullptr;
330};
331
332template <typename TIter>
333class VariantWriteNoStatusHelper
334{
335public:
336 VariantWriteNoStatusHelper(TIter& iter, const void* storage)
337 : iter_(iter),
338 storage_(storage)
339 {
340 }
341
342 template <std::size_t TIdx, typename TField>
343 void operator()()
344 {
345 reinterpret_cast<const TField*>(storage_)->writeNoStatus(iter_);
346 }
347
348private:
349 TIter& iter_;
350 const void* storage_ = nullptr;
351};
352
353template <typename TVersionType>
354class VariantSetVersionHelper
355{
356public:
357 VariantSetVersionHelper(TVersionType version, bool& updated, void* storage)
358 : version_(version),
359 updated_(updated),
360 storage_(storage)
361 {
362 }
363
364 template <std::size_t TIdx, typename TField>
365 void operator()()
366 {
367 updated_ = reinterpret_cast<TField*>(storage_)->setVersion(version_) || updated_;
368 }
369
370private:
371 TVersionType version_ = TVersionType();
372 bool& updated_;
373 void* storage_ = nullptr;
374};
375
376template<typename...>
377class VariantCanWriteHelper
378{
379public:
380 VariantCanWriteHelper(bool& result, const void* storage)
381 : result_(result),
382 storage_(storage)
383 {
384 }
385
386 template <std::size_t TIdx, typename TField>
387 void operator()()
388 {
389 result_ = reinterpret_cast<const TField*>(storage_)->canWrite();
390 }
391
392private:
393 bool& result_;
394 const void* storage_;
395};
396
397template <typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency, typename... TMembers>
398struct VariantVersionStorageBaseHelper;
399
400template <typename TFieldBase, typename... TMembers>
401struct VariantVersionStorageBaseHelper<TFieldBase, comms::field::details::MembersVersionDependency_NotSpecified, TMembers...>
402{
403 using Type =
404 typename comms::util::LazyShallowConditional<
405 CommonFuncs::IsAnyFieldVersionDependentBoolType<TMembers...>::value
406 >::template Type<
407 comms::field::details::VersionStorage,
408 comms::util::EmptyStruct,
409 typename TFieldBase::VersionType
410 >;
411};
412
413template <typename TFieldBase, typename... TMembers>
414struct VariantVersionStorageBaseHelper<TFieldBase, comms::field::details::MembersVersionDependency_Independent, TMembers...>
415{
416 using Type = comms::util::EmptyStruct<>;
417};
418
419template <typename TFieldBase, typename... TMembers>
420struct VariantVersionStorageBaseHelper<TFieldBase, comms::field::details::MembersVersionDependency_Dependent, TMembers...>
421{
422 using Type = comms::field::details::VersionStorage<typename TFieldBase::VersionType>;
423};
424
425template <typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency, typename... TMembers>
426using VariantVersionStorageBase =
427 typename VariantVersionStorageBaseHelper<TFieldBase, TVersionDependency, TMembers...>::Type;
428
429template <comms::field::details::MembersVersionDependency TVersionDependency, typename... TMembers>
430struct VariantVersionDependencyDetectHelper;
431
432template <typename... TMembers>
433struct VariantVersionDependencyDetectHelper<comms::field::details::MembersVersionDependency_NotSpecified, TMembers...>
434{
435 static constexpr bool Value = CommonFuncs::IsAnyFieldVersionDependentBoolType<TMembers...>::value;
436};
437
438template <typename... TMembers>
439struct VariantVersionDependencyDetectHelper<comms::field::details::MembersVersionDependency_Independent, TMembers...>
440{
441 static constexpr bool Value = false;
442};
443
444template <typename... TMembers>
445struct VariantVersionDependencyDetectHelper<comms::field::details::MembersVersionDependency_Dependent, TMembers...>
446{
447 static constexpr bool Value = true;
448};
449
450
451} // namespace details
452
453template <typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency, typename TMembers>
454class Variant;
455
456template <typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency, typename... TMembers>
457class Variant<TFieldBase, TVersionDependency, std::tuple<TMembers...> > :
458 public TFieldBase,
459 public details::VariantVersionStorageBase<TFieldBase, TVersionDependency, TMembers...>
460{
461 using BaseImpl = TFieldBase;
462 using VersionBaseImpl = details::VariantVersionStorageBase<TFieldBase, TVersionDependency, TMembers...>;
463
464public:
465 using Members = std::tuple<TMembers...>;
467 using VersionType = typename BaseImpl::VersionType;
468 using CommsTag = comms::field::tag::Variant;
469
470 static const std::size_t MembersCount = std::tuple_size<Members>::value;
471 static_assert(0U < MembersCount, "ValueType must be non-empty tuple");
472
473 Variant() = default;
474 Variant(const ValueType& val) : storage_(val) {}
475 Variant(ValueType&& val) : storage_(std::move(val)) {}
476
477 Variant(const Variant& other)
478 {
479 if (!other.currentFieldValid()) {
480 return;
481 }
482
483 comms::util::tupleForSelectedType<Members>(
484 other.memIdx_, details::VariantFieldCopyConstructHelper<>(&storage_, &other.storage_));
485
486 memIdx_ = other.memIdx_;
487 }
488
489 Variant(Variant&& other)
490 {
491 if (!other.currentFieldValid()) {
492 return;
493 }
494
495 comms::util::tupleForSelectedType<Members>(
496 other.memIdx_, details::VariantFieldMoveConstructHelper<>(&storage_, &other.storage_));
497
498 memIdx_ = other.memIdx_;
499 }
500
501 ~Variant() noexcept
502 {
503 COMMS_ASSERT(!currentFieldValid());
504 }
505
506 Variant& operator=(const Variant& other)
507 {
508 if (this == &other) {
509 return *this;
510 }
511
512 checkDestruct();
513 if (!other.currentFieldValid()) {
514 return *this;
515 }
516
517 comms::util::tupleForSelectedType<Members>(
518 other.memIdx_, details::VariantFieldCopyConstructHelper<>(&storage_, &other.storage_));
519
520 memIdx_ = other.memIdx_;
521 return *this;
522 }
523
524 Variant& operator=(Variant&& other)
525 {
526 if (this == &other) {
527 return *this;
528 }
529
530 checkDestruct();
531
532 if (!other.currentFieldValid()) {
533 return *this;
534 }
535
536 comms::util::tupleForSelectedType<Members>(
537 other.memIdx_, details::VariantFieldMoveConstructHelper<>(&storage_, &other.storage_));
538
539 memIdx_ = other.memIdx_;
540 return *this;
541 }
542
543 const ValueType& value() const
544 {
545 return storage_;
546 }
547
548 ValueType& value()
549 {
550 return storage_;
551 }
552
553 const ValueType& getValue() const
554 {
555 return value();
556 }
557
558 template <typename T>
559 void setValue(T&& val)
560 {
561 value() = std::forward<T>(val);
562 }
563
564 std::size_t length() const
565 {
566 if (!currentFieldValid()) {
567 return 0U;
568 }
569
570 std::size_t len = std::numeric_limits<std::size_t>::max();
571 comms::util::tupleForSelectedType<Members>(memIdx_, details::VariantLengthCalcHelper<>(len, &storage_));
572 return len;
573 }
574
575 static constexpr std::size_t minLength()
576 {
577 return 0U;
578 }
579
580 static constexpr std::size_t maxLength()
581 {
582 return CommonFuncs::FieldSelectMaxLengthIntType<TMembers...>::value;
583 }
584
585 bool valid() const
586 {
587 if (!currentFieldValid()) {
588 return false;
589 }
590
591 bool val = false;
592 comms::util::tupleForSelectedType<Members>(
593 memIdx_, details::VariantFieldValidCheckHelper<>(val, &storage_));
594 return val;
595 }
596
597 static constexpr bool hasNonDefaultRefresh()
598 {
599 return CommonFuncs::AnyFieldHasNonDefaultRefreshBoolType<TMembers...>::value;
600 }
601
602 bool refresh()
603 {
604 if (!currentFieldValid()) {
605 return false;
606 }
607
608 bool val = false;
609 comms::util::tupleForSelectedType<Members>(
610 memIdx_, details::VariantFieldRefreshHelper<>(val, &storage_));
611 return val;
612 }
613
614 template <typename TIter>
615 ErrorStatus read(TIter& iter, std::size_t len)
616 {
617 checkDestruct();
619 comms::util::tupleForEachType<Members>(makeReadHelper(es, iter, len, &storage_, static_cast<VersionBaseImpl&>(*this)));
620 COMMS_ASSERT((es == comms::ErrorStatus::Success) || (MembersCount <= memIdx_));
621 COMMS_ASSERT((es != comms::ErrorStatus::Success) || (memIdx_ < MembersCount));
622
623 return es;
624 }
625
626 static constexpr bool hasReadNoStatus()
627 {
628 return false;
629 }
630
631 template <typename TIter>
632 void readNoStatus(TIter& iter) = delete;
633
634 bool canWrite() const
635 {
636 if (!currentFieldValid()) {
637 return true;
638 }
639
640 bool val = false;
641 comms::util::tupleForSelectedType<Members>(
642 memIdx_, details::VariantCanWriteHelper<>(val, &storage_));
643 return val;
644 }
645
646 template <typename TIter>
647 ErrorStatus write(TIter& iter, std::size_t len) const
648 {
649 if (!currentFieldValid()) {
651 }
652
653 auto es = ErrorStatus::NumOfErrorStatuses;
654 comms::util::tupleForSelectedType<Members>(memIdx_, makeWriteHelper(es, iter, len, &storage_));
655 return es;
656 }
657
658 static constexpr bool hasWriteNoStatus()
659 {
660 return comms::util::tupleTypeAccumulate<Members>(
661 true, comms::field::details::FieldHasWriteNoStatusHelper<>());
662 }
663
664 template <typename TIter>
665 void writeNoStatus(TIter& iter) const
666 {
667 if (!currentFieldValid()) {
668 return;
669 }
670
671 comms::util::tupleForSelectedType<Members>(memIdx_, makeWriteNoStatusHelper(iter, &storage_));
672 }
673
674
675 std::size_t currentField() const
676 {
677 return memIdx_;
678 }
679
680 void selectField(std::size_t idx)
681 {
682 if (idx == memIdx_) {
683 return;
684 }
685
686 checkDestruct();
687 if (!isIdxValid(idx)) {
688 return;
689 }
690
691 comms::util::tupleForSelectedType<Members>(
692 idx, details::VariantFieldConstructHelper<>(&storage_));
693 memIdx_ = idx;
694 }
695
696 template <typename TFunc>
697 void currentFieldExec(TFunc&& func)
698 {
699 if (!currentFieldValid()) {
700 static constexpr bool Invalid_field_execution = false;
701 static_cast<void>(Invalid_field_execution);
702 COMMS_ASSERT(Invalid_field_execution);
703 return;
704 }
705
706 comms::util::tupleForSelectedType<Members>(memIdx_, makeExecHelper(std::forward<TFunc>(func)));
707 }
708
709 template <typename TFunc>
710 void currentFieldExec(TFunc&& func) const
711 {
712 if (!currentFieldValid()) {
713 static constexpr bool Invalid_field_execution = false;
714 static_cast<void>(Invalid_field_execution);
715 COMMS_ASSERT(Invalid_field_execution);
716 return;
717 }
718
719 comms::util::tupleForSelectedType<Members>(memIdx_, makeConstExecHelper(std::forward<TFunc>(func)));
720 }
721
722 template <std::size_t TIdx, typename... TArgs>
723 typename std::tuple_element<TIdx, Members>::type& initField(TArgs&&... args)
724 {
725 static_assert(isIdxValid(TIdx), "Only valid field index can be used");
726 COMMS_ASSERT(!currentFieldValid());
727
728 using FieldType = typename std::tuple_element<TIdx, Members>::type;
729 new (&storage_) FieldType(std::forward<TArgs>(args)...);
730 memIdx_ = TIdx;
731 updateVersionInternal(VersionTag<>());
732 return reinterpret_cast<FieldType&>(storage_);
733 }
734
735 template <std::size_t TIdx>
736 void deinitField()
737 {
738 static_assert(isIdxValid(TIdx), "Only valid field index can be used");
739 COMMS_ASSERT(memIdx_ == TIdx);
740
741 using FieldType = typename std::tuple_element<TIdx, Members>::type;
742 reinterpret_cast<FieldType*>(&storage_)->~FieldType();
743 memIdx_ = MembersCount;
744 }
745
746 template <std::size_t TIdx>
747 typename std::tuple_element<TIdx, Members>::type& accessField()
748 {
749 static_assert(isIdxValid(TIdx), "Only valid field index can be used");
750 COMMS_ASSERT(TIdx == memIdx_); // Accessing non initialised field
751
752 using FieldType = typename std::tuple_element<TIdx, Members>::type;
753 return reinterpret_cast<FieldType&>(storage_);
754 }
755
756 template <std::size_t TIdx>
757 const typename std::tuple_element<TIdx, Members>::type& accessField() const
758 {
759 static_assert(isIdxValid(TIdx), "Something is wrong");
760 COMMS_ASSERT(TIdx == memIdx_); // Accessing non initialised field
761
762 using FieldType = typename std::tuple_element<TIdx, Members>::type;
763 return reinterpret_cast<const FieldType&>(storage_);
764 }
765
766 bool currentFieldValid() const
767 {
768 return isIdxValid(memIdx_);
769 }
770
771 void reset()
772 {
773 checkDestruct();
774 COMMS_ASSERT(!currentFieldValid());
775 }
776
777 static constexpr bool isVersionDependent()
778 {
779 return details::VariantVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value;
780 }
781
782 bool setVersion(VersionType version)
783 {
784 return setVersionInternal(version, VersionTag<>());
785 }
786
787 VersionType getVersion() const
788 {
789 return getVersionInternal(VersionTag<>());
790 }
791
792private:
793 template <typename... TParams>
794 using VersionDependentTag = comms::details::tag::Tag1<>;
795
796 template <typename... TParams>
797 using NoVersionDependencyTag = comms::details::tag::Tag2<>;
798
799 template <typename... TParams>
800 using ForcedVersionDependencyTag = comms::details::tag::Tag3<>;
801
802 template <typename... TParams>
803 using NoForcedVersionDependencyTag = comms::details::tag::Tag4<>;
804
805 template <typename... TParams>
806 using VersionTag =
807 typename comms::util::LazyShallowConditional<
808 details::VariantVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value
809 >::template Type<
810 VersionDependentTag,
811 NoVersionDependencyTag
812 >;
813
814 template <typename TFunc>
815 auto makeExecHelper(TFunc&& func) -> details::VariantExecHelper<decltype(std::forward<TFunc>(func))>
816 {
817 using FuncType = decltype(std::forward<TFunc>(func));
818 return details::VariantExecHelper<FuncType>(&storage_, std::forward<TFunc>(func));
819 }
820
821 template <typename TFunc>
822 auto makeConstExecHelper(TFunc&& func) const -> details::VariantConstExecHelper<decltype(std::forward<TFunc>(func))>
823 {
824 using FuncType = decltype(std::forward<TFunc>(func));
825 return details::VariantConstExecHelper<FuncType>(&storage_, std::forward<TFunc>(func));
826 }
827
828 template <typename TIter, typename TVerBase>
829 details::VariantReadHelper<TIter, TVerBase, details::VariantVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value>
830 makeReadHelper(
832 TIter& iter,
833 std::size_t len,
834 void* storage,
835 TVerBase& verBase)
836 {
837 memIdx_ = 0;
838 static constexpr bool VerDependent = isVersionDependent();
839 return
840 details::VariantReadHelper<TIter, TVerBase, VerDependent>(
841 memIdx_, es, iter, len, storage, verBase);
842 }
843
844 template <typename TIter>
845 static details::VariantFieldWriteHelper<TIter> makeWriteHelper(comms::ErrorStatus& es, TIter& iter, std::size_t len, const void* storage)
846 {
847 return details::VariantFieldWriteHelper<TIter>(es, iter, len, storage);
848 }
849
850 template <typename TIter>
851 static details::VariantWriteNoStatusHelper<TIter> makeWriteNoStatusHelper(TIter& iter, const void* storage)
852 {
853 return details::VariantWriteNoStatusHelper<TIter>(iter, storage);
854 }
855
856 void checkDestruct()
857 {
858 if (currentFieldValid()) {
859 comms::util::tupleForSelectedType<Members>(
860 memIdx_, details::VariantFieldDestructHelper<>(&storage_));
861 memIdx_ = MembersCount;
862 }
863 }
864
865 static constexpr bool isIdxValid(std::size_t idx)
866 {
867 return idx < MembersCount;
868 }
869
870 template <typename... TParams>
871 bool setVersionInternal(VersionType version, NoVersionDependencyTag<TParams...>)
872 {
873 static_cast<void>(version);
874 return false;
875 }
876
877 template <typename... TParams>
878 bool setVersionInternal(VersionType version, VersionDependentTag<TParams...>)
879 {
880 VersionBaseImpl::version_ = version;
881 bool updated = false;
882 if (currentFieldValid()) {
883 comms::util::tupleForSelectedType<Members>(
884 memIdx_, details::VariantSetVersionHelper<VersionType>(version, updated, &storage_));
885 }
886 return updated;
887 }
888
889
890 template <typename... TParams>
891 VersionType getVersionInternal(VersionDependentTag<TParams...>) const
892 {
893 return VersionBaseImpl::version_;;
894 }
895
896 template <typename... TParams>
897 void updateVersionInternal(NoVersionDependencyTag<TParams...>)
898 {
899 }
900
901 template <typename... TParams>
902 void updateVersionInternal(VersionDependentTag<TParams...>)
903 {
904 setVersion(VersionBaseImpl::version_);
905 }
906
907 alignas(8) ValueType storage_;
908 std::size_t memIdx_ = MembersCount;
909};
910
911} // namespace basic
912
913} // namespace field
914
915} // namespace comms
916
917COMMS_MSVC_WARNING_POP
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:170
Contains various compiler related definitions.
This file contain definition of error statuses used by comms module.
Contains various tuple type manipulation classes and functions.
Contains definition of various tag classes.
comms::option::def::VersionType< T > VersionType
Same as comms::option::def::VersionType.
Definition options.h:1797
comms::option::def::FieldType< TMsg > FieldType
Same as comms::option::def::FieldType.
Definition options.h:1463
typename TupleAsAlignedUnion< TTuple >::Type TupleAsAlignedUnionT
Alias to TupleAsAlignedUnion::Type.
Definition Tuple.h:185
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition ErrorStatus.h:17
@ Success
Used to indicate successful outcome of the operation.
@ NumOfErrorStatuses
Number of supported error statuses, must be last.
constexpr unsigned version()
Version of the COMMS library as single numeric value.
Definition version.h:64
STL namespace.
Replacement to some types from standard type_traits.