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