COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
Variant.h
1//
2// Copyright 2017 - 2025 (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 "comms/Assert.h"
12#include "comms/details/tag.h"
13#include "comms/ErrorStatus.h"
14#include "comms/field/basic/CommonFuncs.h"
15#include "comms/field/details/FieldOpHelpers.h"
16#include "comms/field/details/MembersVersionDependency.h"
17#include "comms/field/details/VersionStorage.h"
18#include "comms/field/tag.h"
19#include "comms/util/Tuple.h"
21
22#include <algorithm>
23#include <type_traits>
24#include <utility>
25
26COMMS_MSVC_WARNING_PUSH
27COMMS_MSVC_WARNING_DISABLE(4324) // Disable warning about alignment padding
28
29namespace comms
30{
31
32namespace field
33{
34
35namespace basic
36{
37
38namespace details
39{
40
41template<typename...>
42class VariantFieldConstructHelper
43{
44public:
45 VariantFieldConstructHelper(void* storage) : m_storage(storage) {}
46
47 template <std::size_t TIdx, typename TField>
48 void operator()() const
49 {
50 new (m_storage) TField;
51 }
52private:
53 void* m_storage = nullptr;
54};
55
56template<typename...>
57class VariantLengthCalcHelper
58{
59public:
60 VariantLengthCalcHelper(std::size_t& len, const void* storage) :
61 m_len(len),
62 m_storage(storage)
63 {
64 }
65
66 template <std::size_t TIdx, typename TField>
67 void operator()()
68 {
69 m_len = reinterpret_cast<const TField*>(m_storage)->length();
70 }
71
72private:
73 std::size_t& m_len;
74 const void* m_storage;
75};
76
77template<typename...>
78class VariantFieldCopyConstructHelper
79{
80public:
81 VariantFieldCopyConstructHelper(void* storage, const void* other) : m_storage(storage), m_other(other) {}
82
83 template <std::size_t TIdx, typename TField>
84 void operator()() const
85 {
86 new (m_storage) TField(*(reinterpret_cast<const TField*>(m_other)));
87 }
88
89private:
90 void* m_storage = nullptr;
91 const void* m_other = nullptr;
92};
93
94template<typename...>
95class VariantFieldMoveConstructHelper
96{
97public:
98 VariantFieldMoveConstructHelper(void* storage, void* other) : m_storage(storage), m_other(other) {}
99
100 template <std::size_t TIdx, typename TField>
101 void operator()() const
102 {
103 new (m_storage) TField(std::move(*(reinterpret_cast<const TField*>(m_other))));
104 }
105
106private:
107 void* m_storage = nullptr;
108 void* m_other = nullptr;
109};
110
111template<typename...>
112class VariantFieldDestructHelper
113{
114public:
115 VariantFieldDestructHelper(void* storage) : m_storage(storage) {}
116
117 template <std::size_t TIdx, typename TField>
118 void operator()() const
119 {
120 reinterpret_cast<TField*>(m_storage)->~TField();
121 }
122private:
123 void* m_storage = nullptr;
124};
125
126template <typename...>
127class VariantFieldValidCheckHelper
128{
129public:
130 VariantFieldValidCheckHelper(bool& result, const void* storage)
131 : m_result(result),
132 m_storage(storage)
133 {
134 }
135
136 template <std::size_t TIdx, typename TField>
137 void operator()()
138 {
139 m_result = reinterpret_cast<const TField*>(m_storage)->valid();
140 }
141
142private:
143 bool& m_result;
144 const void* m_storage;
145};
146
147template <typename...>
148class VariantFieldRefreshHelper
149{
150public:
151 VariantFieldRefreshHelper(bool& result, void* storage)
152 : m_result(result),
153 m_storage(storage)
154 {
155 }
156
157 template <std::size_t TIdx, typename TField>
158 void operator()()
159 {
160 m_result = reinterpret_cast<TField*>(m_storage)->refresh();
161 }
162
163private:
164 bool& m_result;
165 void* m_storage = nullptr;
166};
167
168template <typename TFunc>
169class VariantExecHelper
170{
171 static_assert(std::is_lvalue_reference<TFunc>::value || std::is_rvalue_reference<TFunc>::value,
172 "Wrong type of template parameter");
173public:
174 template <typename U>
175 VariantExecHelper(void* storage, U&& func) : m_storage(storage), m_func(std::forward<U>(func)) {}
176
177 template <std::size_t TIdx, typename TField>
178 void operator()()
179 {
180#if COMMS_IS_MSVC
181 // VS compiler
182 m_func.operator()<TIdx>(*(reinterpret_cast<TField*>(m_storage)));
183#else // #if COMMS_IS_MSVC
184 m_func.template operator()<TIdx>(*(reinterpret_cast<TField*>(m_storage)));
185#endif // #if COMMS_IS_MSVC
186 }
187private:
188 void* m_storage = nullptr;
189 TFunc m_func;
190};
191
192template <typename TFunc>
193class VariantConstExecHelper
194{
195 static_assert(std::is_lvalue_reference<TFunc>::value || std::is_rvalue_reference<TFunc>::value,
196 "Wrong type of template parameter");
197public:
198 template <typename U>
199 VariantConstExecHelper(const void* storage, U&& func) : m_storage(storage), m_func(std::forward<U>(func)) {}
200
201 template <std::size_t TIdx, typename TField>
202 void operator()()
203 {
204#if COMMS_IS_MSVC
205 // VS compiler
206 m_func.operator()<TIdx>(*(reinterpret_cast<const TField*>(m_storage)));
207#else // #if COMMS_IS_MSVC
208 m_func.template operator()<TIdx>(*(reinterpret_cast<const TField*>(m_storage)));
209#endif // #if COMMS_IS_MSVC
210 }
211private:
212 const void* m_storage = nullptr;
213 TFunc m_func;
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 : m_idx(idx),
242 m_es(es),
243 m_iter(iter),
244 m_len(len),
245 m_storage(storage),
246 m_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 (m_readComplete) {
260 return;
261 }
262
263 auto* field = new (m_storage) TField;
264 updateMemberVersionInternal(*field, VersionTag<>());
265
266 auto iterTmp = m_iter;
267 auto es = field->read(iterTmp, m_len);
268 if (es == comms::ErrorStatus::Success) {
269 m_iter = iterTmp;
270 m_es = es;
271 m_readComplete = true;
272 return;
273 }
274
275 field->~TField();
276
279 m_es = es;
280 }
281
282 ++m_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(m_verBase.getVersion());
296 }
297
298 std::size_t& m_idx;
299 comms::ErrorStatus& m_es;
300 TIter& m_iter;
301 std::size_t m_len = 0;
302 void* m_storage = nullptr;
303 TVerBase& m_verBase;
304 bool m_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 : m_es(es),
313 m_iter(iter),
314 m_len(len),
315 m_storage(storage)
316 {
317 }
318
319 template <std::size_t TIdx, typename TField>
320 void operator()()
321 {
322 m_es = reinterpret_cast<const TField*>(m_storage)->write(m_iter, m_len);
323 }
324
325private:
326 ErrorStatus& m_es;
327 TIter& m_iter;
328 std::size_t m_len = 0U;
329 const void* m_storage = nullptr;
330};
331
332template <typename TIter>
333class VariantWriteNoStatusHelper
334{
335public:
336 VariantWriteNoStatusHelper(TIter& iter, const void* storage)
337 : m_iter(iter),
338 m_storage(storage)
339 {
340 }
341
342 template <std::size_t TIdx, typename TField>
343 void operator()()
344 {
345 reinterpret_cast<const TField*>(m_storage)->writeNoStatus(m_iter);
346 }
347
348private:
349 TIter& m_iter;
350 const void* m_storage = nullptr;
351};
352
353template <typename TVersionType>
354class VariantSetVersionHelper
355{
356public:
357 VariantSetVersionHelper(TVersionType version, bool& updated, void* storage) :
358 m_version(version),
359 m_updated(updated),
360 m_storage(storage)
361 {
362 }
363
364 template <std::size_t TIdx, typename TField>
365 void operator()()
366 {
367 m_updated = reinterpret_cast<TField*>(m_storage)->setVersion(m_version) || m_updated;
368 }
369
370private:
371 TVersionType m_version = TVersionType();
372 bool& m_updated;
373 void* m_storage = nullptr;
374};
375
376template<typename...>
377class VariantCanWriteHelper
378{
379public:
380 VariantCanWriteHelper(bool& result, const void* storage)
381 : m_result(result),
382 m_storage(storage)
383 {
384 }
385
386 template <std::size_t TIdx, typename TField>
387 void operator()()
388 {
389 m_result = reinterpret_cast<const TField*>(m_storage)->canWrite();
390 }
391
392private:
393 bool& m_result;
394 const void* m_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} // namespace details
451
452template <typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency, typename TMembers>
453class Variant;
454
455template <typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency, typename... TMembers>
456class Variant<TFieldBase, TVersionDependency, std::tuple<TMembers...> > :
457 public TFieldBase,
458 public details::VariantVersionStorageBase<TFieldBase, TVersionDependency, TMembers...>
459{
460 using BaseImpl = TFieldBase;
461 using VersionBaseImpl = details::VariantVersionStorageBase<TFieldBase, TVersionDependency, TMembers...>;
462
463public:
464 using Members = std::tuple<TMembers...>;
466 using VersionType = typename BaseImpl::VersionType;
467 using CommsTag = comms::field::tag::Variant;
468
469 static const std::size_t MembersCount = std::tuple_size<Members>::value;
470 static_assert(0U < MembersCount, "ValueType must be non-empty tuple");
471
472 Variant() = default;
473 Variant(const ValueType& val) : m_storage(val) {}
474 Variant(ValueType&& val) : m_storage(std::move(val)) {}
475
476 Variant(const Variant& other)
477 {
478 if (!other.currentFieldValid()) {
479 return;
480 }
481
482 comms::util::tupleForSelectedType<Members>(
483 other.m_memIdx, details::VariantFieldCopyConstructHelper<>(&m_storage, &other.m_storage));
484
485 m_memIdx = other.m_memIdx;
486 }
487
488 Variant(Variant&& other)
489 {
490 if (!other.currentFieldValid()) {
491 return;
492 }
493
494 comms::util::tupleForSelectedType<Members>(
495 other.m_memIdx, details::VariantFieldMoveConstructHelper<>(&m_storage, &other.m_storage));
496
497 m_memIdx = other.m_memIdx;
498 }
499
500 ~Variant() noexcept
501 {
502 COMMS_ASSERT(!currentFieldValid());
503 }
504
505 Variant& operator=(const Variant& other)
506 {
507 if (this == &other) {
508 return *this;
509 }
510
511 checkDestruct();
512 if (!other.currentFieldValid()) {
513 return *this;
514 }
515
516 comms::util::tupleForSelectedType<Members>(
517 other.m_memIdx, details::VariantFieldCopyConstructHelper<>(&m_storage, &other.m_storage));
518
519 m_memIdx = other.m_memIdx;
520 return *this;
521 }
522
523 Variant& operator=(Variant&& other)
524 {
525 if (this == &other) {
526 return *this;
527 }
528
529 checkDestruct();
530
531 if (!other.currentFieldValid()) {
532 return *this;
533 }
534
535 comms::util::tupleForSelectedType<Members>(
536 other.m_memIdx, details::VariantFieldMoveConstructHelper<>(&m_storage, &other.m_storage));
537
538 m_memIdx = other.m_memIdx;
539 return *this;
540 }
541
542 const ValueType& value() const
543 {
544 return m_storage;
545 }
546
547 ValueType& value()
548 {
549 return m_storage;
550 }
551
552 const ValueType& getValue() const
553 {
554 return value();
555 }
556
557 template <typename T>
558 void setValue(T&& val)
559 {
560 value() = std::forward<T>(val);
561 }
562
563 std::size_t length() const
564 {
565 if (!currentFieldValid()) {
566 return 0U;
567 }
568
569 std::size_t len = std::numeric_limits<std::size_t>::max();
570 comms::util::tupleForSelectedType<Members>(m_memIdx, details::VariantLengthCalcHelper<>(len, &m_storage));
571 return len;
572 }
573
574 static constexpr std::size_t minLength()
575 {
576 return 0U;
577 }
578
579 static constexpr std::size_t maxLength()
580 {
581 return CommonFuncs::FieldSelectMaxLengthIntType<TMembers...>::value;
582 }
583
584 bool valid() const
585 {
586 if (!currentFieldValid()) {
587 return false;
588 }
589
590 bool val = false;
591 comms::util::tupleForSelectedType<Members>(
592 m_memIdx, details::VariantFieldValidCheckHelper<>(val, &m_storage));
593 return val;
594 }
595
596 static constexpr bool hasNonDefaultRefresh()
597 {
598 return CommonFuncs::AnyFieldHasNonDefaultRefreshBoolType<TMembers...>::value;
599 }
600
601 bool refresh()
602 {
603 if (!currentFieldValid()) {
604 return false;
605 }
606
607 bool val = false;
608 comms::util::tupleForSelectedType<Members>(
609 m_memIdx, details::VariantFieldRefreshHelper<>(val, &m_storage));
610 return val;
611 }
612
613 template <typename TIter>
614 ErrorStatus read(TIter& iter, std::size_t len)
615 {
616 checkDestruct();
618 comms::util::tupleForEachType<Members>(makeReadHelper(es, iter, len, &m_storage, static_cast<VersionBaseImpl&>(*this)));
619 COMMS_ASSERT((es == comms::ErrorStatus::Success) || (MembersCount <= m_memIdx));
620 COMMS_ASSERT((es != comms::ErrorStatus::Success) || (m_memIdx < MembersCount));
621
622 return es;
623 }
624
625 static constexpr bool hasReadNoStatus()
626 {
627 return false;
628 }
629
630 template <typename TIter>
631 void readNoStatus(TIter& iter) = delete;
632
633 bool canWrite() const
634 {
635 if (!currentFieldValid()) {
636 return true;
637 }
638
639 bool val = false;
640 comms::util::tupleForSelectedType<Members>(
641 m_memIdx, details::VariantCanWriteHelper<>(val, &m_storage));
642 return val;
643 }
644
645 template <typename TIter>
646 ErrorStatus write(TIter& iter, std::size_t len) const
647 {
648 if (!currentFieldValid()) {
650 }
651
652 auto es = ErrorStatus::NumOfErrorStatuses;
653 comms::util::tupleForSelectedType<Members>(m_memIdx, makeWriteHelper(es, iter, len, &m_storage));
654 return es;
655 }
656
657 static constexpr bool hasWriteNoStatus()
658 {
659 return comms::util::tupleTypeAccumulate<Members>(
660 true, comms::field::details::FieldHasWriteNoStatusHelper<>());
661 }
662
663 template <typename TIter>
664 void writeNoStatus(TIter& iter) const
665 {
666 if (!currentFieldValid()) {
667 return;
668 }
669
670 comms::util::tupleForSelectedType<Members>(m_memIdx, makeWriteNoStatusHelper(iter, &m_storage));
671 }
672
673 std::size_t currentField() const
674 {
675 return m_memIdx;
676 }
677
678 void selectField(std::size_t idx)
679 {
680 if (idx == m_memIdx) {
681 return;
682 }
683
684 checkDestruct();
685 if (!isIdxValid(idx)) {
686 return;
687 }
688
689 comms::util::tupleForSelectedType<Members>(
690 idx, details::VariantFieldConstructHelper<>(&m_storage));
691 m_memIdx = idx;
692 }
693
694 template <typename TFunc>
695 void currentFieldExec(TFunc&& func)
696 {
697 if (!currentFieldValid()) {
698 static constexpr bool Invalid_field_execution = false;
699 static_cast<void>(Invalid_field_execution);
700 COMMS_ASSERT(Invalid_field_execution);
701 return;
702 }
703
704 comms::util::tupleForSelectedType<Members>(m_memIdx, makeExecHelper(std::forward<TFunc>(func)));
705 }
706
707 template <typename TFunc>
708 void currentFieldExec(TFunc&& func) const
709 {
710 if (!currentFieldValid()) {
711 static constexpr bool Invalid_field_execution = false;
712 static_cast<void>(Invalid_field_execution);
713 COMMS_ASSERT(Invalid_field_execution);
714 return;
715 }
716
717 comms::util::tupleForSelectedType<Members>(m_memIdx, makeConstExecHelper(std::forward<TFunc>(func)));
718 }
719
720 template <std::size_t TIdx, typename... TArgs>
721 typename std::tuple_element<TIdx, Members>::type& initField(TArgs&&... args)
722 {
723 static_assert(isIdxValid(TIdx), "Only valid field index can be used");
724 COMMS_ASSERT(!currentFieldValid());
725
726 using FieldType = typename std::tuple_element<TIdx, Members>::type;
727 new (&m_storage) FieldType(std::forward<TArgs>(args)...);
728 m_memIdx = TIdx;
729 updateVersionInternal(VersionTag<>());
730 return reinterpret_cast<FieldType&>(m_storage);
731 }
732
733 template <std::size_t TIdx>
734 void deinitField()
735 {
736 static_assert(isIdxValid(TIdx), "Only valid field index can be used");
737 COMMS_ASSERT(m_memIdx == TIdx);
738
739 using FieldType = typename std::tuple_element<TIdx, Members>::type;
740 reinterpret_cast<FieldType*>(&m_storage)->~FieldType();
741 m_memIdx = MembersCount;
742 }
743
744 template <std::size_t TIdx>
745 typename std::tuple_element<TIdx, Members>::type& accessField()
746 {
747 static_assert(isIdxValid(TIdx), "Only valid field index can be used");
748 COMMS_ASSERT(TIdx == m_memIdx); // Accessing non initialised field
749
750 using FieldType = typename std::tuple_element<TIdx, Members>::type;
751 return reinterpret_cast<FieldType&>(m_storage);
752 }
753
754 template <std::size_t TIdx>
755 const typename std::tuple_element<TIdx, Members>::type& accessField() const
756 {
757 static_assert(isIdxValid(TIdx), "Something is wrong");
758 COMMS_ASSERT(TIdx == m_memIdx); // Accessing non initialised field
759
760 using FieldType = typename std::tuple_element<TIdx, Members>::type;
761 return reinterpret_cast<const FieldType&>(m_storage);
762 }
763
764 bool currentFieldValid() const
765 {
766 return isIdxValid(m_memIdx);
767 }
768
769 void reset()
770 {
771 checkDestruct();
772 COMMS_ASSERT(!currentFieldValid());
773 }
774
775 static constexpr bool isVersionDependent()
776 {
777 return details::VariantVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value;
778 }
779
780 bool setVersion(VersionType version)
781 {
782 return setVersionInternal(version, VersionTag<>());
783 }
784
785 VersionType getVersion() const
786 {
787 return getVersionInternal(VersionTag<>());
788 }
789
790private:
791 template <typename... TParams>
792 using VersionDependentTag = comms::details::tag::Tag1<>;
793
794 template <typename... TParams>
795 using NoVersionDependencyTag = comms::details::tag::Tag2<>;
796
797 template <typename... TParams>
798 using ForcedVersionDependencyTag = comms::details::tag::Tag3<>;
799
800 template <typename... TParams>
801 using NoForcedVersionDependencyTag = comms::details::tag::Tag4<>;
802
803 template <typename... TParams>
804 using VersionTag =
805 typename comms::util::LazyShallowConditional<
806 details::VariantVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value
807 >::template Type<
808 VersionDependentTag,
809 NoVersionDependencyTag
810 >;
811
812 template <typename TFunc>
813 auto makeExecHelper(TFunc&& func) -> details::VariantExecHelper<decltype(std::forward<TFunc>(func))>
814 {
815 using FuncType = decltype(std::forward<TFunc>(func));
816 return details::VariantExecHelper<FuncType>(&m_storage, std::forward<TFunc>(func));
817 }
818
819 template <typename TFunc>
820 auto makeConstExecHelper(TFunc&& func) const -> details::VariantConstExecHelper<decltype(std::forward<TFunc>(func))>
821 {
822 using FuncType = decltype(std::forward<TFunc>(func));
823 return details::VariantConstExecHelper<FuncType>(&m_storage, std::forward<TFunc>(func));
824 }
825
826 template <typename TIter, typename TVerBase>
827 details::VariantReadHelper<TIter, TVerBase, details::VariantVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value>
828 makeReadHelper(
830 TIter& iter,
831 std::size_t len,
832 void* storage,
833 TVerBase& verBase)
834 {
835 m_memIdx = 0;
836 static constexpr bool VerDependent = isVersionDependent();
837 return
838 details::VariantReadHelper<TIter, TVerBase, VerDependent>(
839 m_memIdx, es, iter, len, storage, verBase);
840 }
841
842 template <typename TIter>
843 static details::VariantFieldWriteHelper<TIter> makeWriteHelper(comms::ErrorStatus& es, TIter& iter, std::size_t len, const void* storage)
844 {
845 return details::VariantFieldWriteHelper<TIter>(es, iter, len, storage);
846 }
847
848 template <typename TIter>
849 static details::VariantWriteNoStatusHelper<TIter> makeWriteNoStatusHelper(TIter& iter, const void* storage)
850 {
851 return details::VariantWriteNoStatusHelper<TIter>(iter, storage);
852 }
853
854 void checkDestruct()
855 {
856 if (currentFieldValid()) {
857 comms::util::tupleForSelectedType<Members>(
858 m_memIdx, details::VariantFieldDestructHelper<>(&m_storage));
859 m_memIdx = MembersCount;
860 }
861 }
862
863 static constexpr bool isIdxValid(std::size_t idx)
864 {
865 return idx < MembersCount;
866 }
867
868 template <typename... TParams>
869 bool setVersionInternal(VersionType version, NoVersionDependencyTag<TParams...>)
870 {
871 static_cast<void>(version);
872 return false;
873 }
874
875 template <typename... TParams>
876 bool setVersionInternal(VersionType version, VersionDependentTag<TParams...>)
877 {
878 VersionBaseImpl::m_version = version;
879 bool updated = false;
880 if (currentFieldValid()) {
881 comms::util::tupleForSelectedType<Members>(
882 m_memIdx, details::VariantSetVersionHelper<VersionType>(version, updated, &m_storage));
883 }
884 return updated;
885 }
886
887 template <typename... TParams>
888 VersionType getVersionInternal(VersionDependentTag<TParams...>) const
889 {
890 return VersionBaseImpl::m_version;;
891 }
892
893 template <typename... TParams>
894 void updateVersionInternal(NoVersionDependencyTag<TParams...>)
895 {
896 }
897
898 template <typename... TParams>
899 void updateVersionInternal(VersionDependentTag<TParams...>)
900 {
901 setVersion(VersionBaseImpl::m_version);
902 }
903
904 alignas(8) ValueType m_storage;
905 std::size_t m_memIdx = MembersCount;
906};
907
908} // namespace basic
909
910} // namespace field
911
912} // namespace comms
913
914COMMS_MSVC_WARNING_POP
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:168
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:1928
comms::option::def::FieldType< TMsg > FieldType
Same as comms::option::def::FieldType.
Definition options.h:1503
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.