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
216
217template <typename TIter, typename TVerBase, bool TVerDependent>
218class VariantReadHelper
219{
220 template <typename... TParams>
221 using VersionDependentTag = comms::details::tag::Tag1<>;
222
223 template <typename... TParams>
224 using NoVersionDependencyTag = comms::details::tag::Tag2<>;
225
226 template <typename... TParams>
227 using VersionTag =
228 typename comms::util::LazyShallowConditional<
229 TVerDependent
230 >::template Type<
231 VersionDependentTag,
232 NoVersionDependencyTag
233 >;
234public:
235 VariantReadHelper(
236 std::size_t& idx,
238 TIter& iter,
239 std::size_t len,
240 void* storage,
241 TVerBase& verBase)
242 : m_idx(idx),
243 m_es(es),
244 m_iter(iter),
245 m_len(len),
246 m_storage(storage),
247 m_verBase(verBase)
248 {
249 using IterType = typename std::decay<decltype(iter)>::type;
250 using IterCategory = typename std::iterator_traits<IterType>::iterator_category;
251 static_assert(std::is_base_of<std::random_access_iterator_tag, IterCategory>::value,
252 "Variant field only supports read with random access iterators");
253
255 }
256
257 template <typename TField>
258 void operator()()
259 {
260 if (m_readComplete) {
261 return;
262 }
263
264 auto* field = new (m_storage) TField;
265 updateMemberVersionInternal(*field, VersionTag<>());
266
267 auto iterTmp = m_iter;
268 auto es = field->read(iterTmp, m_len);
269 if (es == comms::ErrorStatus::Success) {
270 m_iter = iterTmp;
271 m_es = es;
272 m_readComplete = true;
273 return;
274 }
275
276 field->~TField();
277
280 m_es = es;
281 }
282
283 ++m_idx;
284 }
285
286private:
287 template <typename TField, typename... TParams>
288 void updateMemberVersionInternal(TField& field, NoVersionDependencyTag<TParams...>)
289 {
290 static_cast<void>(field);
291 }
292
293 template <typename TField, typename... TParams>
294 void updateMemberVersionInternal(TField& field, VersionDependentTag<TParams...>)
295 {
296 field.setVersion(m_verBase.getVersion());
297 }
298
299 std::size_t& m_idx;
300 comms::ErrorStatus& m_es;
301 TIter& m_iter;
302 std::size_t m_len = 0;
303 void* m_storage = nullptr;
304 TVerBase& m_verBase;
305 bool m_readComplete = false;
306};
307
308template <typename TIter>
309class VariantFieldWriteHelper
310{
311public:
312 VariantFieldWriteHelper(ErrorStatus& es, TIter& iter, std::size_t len, const void* storage)
313 : m_es(es),
314 m_iter(iter),
315 m_len(len),
316 m_storage(storage)
317 {
318 }
319
320 template <std::size_t TIdx, typename TField>
321 void operator()()
322 {
323 m_es = reinterpret_cast<const TField*>(m_storage)->write(m_iter, m_len);
324 }
325
326private:
327 ErrorStatus& m_es;
328 TIter& m_iter;
329 std::size_t m_len = 0U;
330 const void* m_storage = nullptr;
331};
332
333template <typename TIter>
334class VariantWriteNoStatusHelper
335{
336public:
337 VariantWriteNoStatusHelper(TIter& iter, const void* storage)
338 : m_iter(iter),
339 m_storage(storage)
340 {
341 }
342
343 template <std::size_t TIdx, typename TField>
344 void operator()()
345 {
346 reinterpret_cast<const TField*>(m_storage)->writeNoStatus(m_iter);
347 }
348
349private:
350 TIter& m_iter;
351 const void* m_storage = nullptr;
352};
353
354template <typename TVersionType>
355class VariantSetVersionHelper
356{
357public:
358 VariantSetVersionHelper(TVersionType version, bool& updated, void* storage) :
359 m_version(version),
360 m_updated(updated),
361 m_storage(storage)
362 {
363 }
364
365 template <std::size_t TIdx, typename TField>
366 void operator()()
367 {
368 m_updated = reinterpret_cast<TField*>(m_storage)->setVersion(m_version) || m_updated;
369 }
370
371private:
372 TVersionType m_version = TVersionType();
373 bool& m_updated;
374 void* m_storage = nullptr;
375};
376
377template<typename...>
378class VariantCanWriteHelper
379{
380public:
381 VariantCanWriteHelper(bool& result, const void* storage)
382 : m_result(result),
383 m_storage(storage)
384 {
385 }
386
387 template <std::size_t TIdx, typename TField>
388 void operator()()
389 {
390 m_result = reinterpret_cast<const TField*>(m_storage)->canWrite();
391 }
392
393private:
394 bool& m_result;
395 const void* m_storage;
396};
397
398template <typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency, typename... TMembers>
399struct VariantVersionStorageBaseHelper;
400
401template <typename TFieldBase, typename... TMembers>
402struct VariantVersionStorageBaseHelper<TFieldBase, comms::field::details::MembersVersionDependency_NotSpecified, TMembers...>
403{
404 using Type =
405 typename comms::util::LazyShallowConditional<
406 CommonFuncs::IsAnyFieldVersionDependentBoolType<TMembers...>::value
407 >::template Type<
408 comms::field::details::VersionStorage,
409 comms::util::EmptyStruct,
410 typename TFieldBase::VersionType
411 >;
412};
413
414template <typename TFieldBase, typename... TMembers>
415struct VariantVersionStorageBaseHelper<TFieldBase, comms::field::details::MembersVersionDependency_Independent, TMembers...>
416{
417 using Type = comms::util::EmptyStruct<>;
418};
419
420template <typename TFieldBase, typename... TMembers>
421struct VariantVersionStorageBaseHelper<TFieldBase, comms::field::details::MembersVersionDependency_Dependent, TMembers...>
422{
423 using Type = comms::field::details::VersionStorage<typename TFieldBase::VersionType>;
424};
425
426template <typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency, typename... TMembers>
427using VariantVersionStorageBase =
428 typename VariantVersionStorageBaseHelper<TFieldBase, TVersionDependency, TMembers...>::Type;
429
430template <comms::field::details::MembersVersionDependency TVersionDependency, typename... TMembers>
431struct VariantVersionDependencyDetectHelper;
432
433template <typename... TMembers>
434struct VariantVersionDependencyDetectHelper<comms::field::details::MembersVersionDependency_NotSpecified, TMembers...>
435{
436 static constexpr bool Value = CommonFuncs::IsAnyFieldVersionDependentBoolType<TMembers...>::value;
437};
438
439template <typename... TMembers>
440struct VariantVersionDependencyDetectHelper<comms::field::details::MembersVersionDependency_Independent, TMembers...>
441{
442 static constexpr bool Value = false;
443};
444
445template <typename... TMembers>
446struct VariantVersionDependencyDetectHelper<comms::field::details::MembersVersionDependency_Dependent, TMembers...>
447{
448 static constexpr bool Value = true;
449};
450
451
452} // namespace details
453
454template <typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency, typename TMembers>
455class Variant;
456
457template <typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency, typename... TMembers>
458class Variant<TFieldBase, TVersionDependency, std::tuple<TMembers...> > :
459 public TFieldBase,
460 public details::VariantVersionStorageBase<TFieldBase, TVersionDependency, TMembers...>
461{
462 using BaseImpl = TFieldBase;
463 using VersionBaseImpl = details::VariantVersionStorageBase<TFieldBase, TVersionDependency, TMembers...>;
464
465public:
466 using Members = std::tuple<TMembers...>;
468 using VersionType = typename BaseImpl::VersionType;
469 using CommsTag = comms::field::tag::Variant;
470
471 static const std::size_t MembersCount = std::tuple_size<Members>::value;
472 static_assert(0U < MembersCount, "ValueType must be non-empty tuple");
473
474 Variant() = default;
475 Variant(const ValueType& val) : m_storage(val) {}
476 Variant(ValueType&& val) : m_storage(std::move(val)) {}
477
478 Variant(const Variant& other)
479 {
480 if (!other.currentFieldValid()) {
481 return;
482 }
483
484 comms::util::tupleForSelectedType<Members>(
485 other.m_memIdx, details::VariantFieldCopyConstructHelper<>(&m_storage, &other.m_storage));
486
487 m_memIdx = other.m_memIdx;
488 }
489
490 Variant(Variant&& other)
491 {
492 if (!other.currentFieldValid()) {
493 return;
494 }
495
496 comms::util::tupleForSelectedType<Members>(
497 other.m_memIdx, details::VariantFieldMoveConstructHelper<>(&m_storage, &other.m_storage));
498
499 m_memIdx = other.m_memIdx;
500 }
501
502 ~Variant() noexcept
503 {
504 COMMS_ASSERT(!currentFieldValid());
505 }
506
507 Variant& operator=(const Variant& other)
508 {
509 if (this == &other) {
510 return *this;
511 }
512
513 checkDestruct();
514 if (!other.currentFieldValid()) {
515 return *this;
516 }
517
518 comms::util::tupleForSelectedType<Members>(
519 other.m_memIdx, details::VariantFieldCopyConstructHelper<>(&m_storage, &other.m_storage));
520
521 m_memIdx = other.m_memIdx;
522 return *this;
523 }
524
525 Variant& operator=(Variant&& other)
526 {
527 if (this == &other) {
528 return *this;
529 }
530
531 checkDestruct();
532
533 if (!other.currentFieldValid()) {
534 return *this;
535 }
536
537 comms::util::tupleForSelectedType<Members>(
538 other.m_memIdx, details::VariantFieldMoveConstructHelper<>(&m_storage, &other.m_storage));
539
540 m_memIdx = other.m_memIdx;
541 return *this;
542 }
543
544 const ValueType& value() const
545 {
546 return m_storage;
547 }
548
549 ValueType& value()
550 {
551 return m_storage;
552 }
553
554 const ValueType& getValue() const
555 {
556 return value();
557 }
558
559 template <typename T>
560 void setValue(T&& val)
561 {
562 value() = std::forward<T>(val);
563 }
564
565 std::size_t length() const
566 {
567 if (!currentFieldValid()) {
568 return 0U;
569 }
570
571 std::size_t len = std::numeric_limits<std::size_t>::max();
572 comms::util::tupleForSelectedType<Members>(m_memIdx, details::VariantLengthCalcHelper<>(len, &m_storage));
573 return len;
574 }
575
576 static constexpr std::size_t minLength()
577 {
578 return 0U;
579 }
580
581 static constexpr std::size_t maxLength()
582 {
583 return CommonFuncs::FieldSelectMaxLengthIntType<TMembers...>::value;
584 }
585
586 bool valid() const
587 {
588 if (!currentFieldValid()) {
589 return false;
590 }
591
592 bool val = false;
593 comms::util::tupleForSelectedType<Members>(
594 m_memIdx, details::VariantFieldValidCheckHelper<>(val, &m_storage));
595 return val;
596 }
597
598 static constexpr bool hasNonDefaultRefresh()
599 {
600 return CommonFuncs::AnyFieldHasNonDefaultRefreshBoolType<TMembers...>::value;
601 }
602
603 bool refresh()
604 {
605 if (!currentFieldValid()) {
606 return false;
607 }
608
609 bool val = false;
610 comms::util::tupleForSelectedType<Members>(
611 m_memIdx, details::VariantFieldRefreshHelper<>(val, &m_storage));
612 return val;
613 }
614
615 template <typename TIter>
616 ErrorStatus read(TIter& iter, std::size_t len)
617 {
618 checkDestruct();
620 comms::util::tupleForEachType<Members>(makeReadHelper(es, iter, len, &m_storage, static_cast<VersionBaseImpl&>(*this)));
621 COMMS_ASSERT((es == comms::ErrorStatus::Success) || (MembersCount <= m_memIdx));
622 COMMS_ASSERT((es != comms::ErrorStatus::Success) || (m_memIdx < MembersCount));
623
624 return es;
625 }
626
627 static constexpr bool hasReadNoStatus()
628 {
629 return false;
630 }
631
632 template <typename TIter>
633 void readNoStatus(TIter& iter) = delete;
634
635 bool canWrite() const
636 {
637 if (!currentFieldValid()) {
638 return true;
639 }
640
641 bool val = false;
642 comms::util::tupleForSelectedType<Members>(
643 m_memIdx, details::VariantCanWriteHelper<>(val, &m_storage));
644 return val;
645 }
646
647 template <typename TIter>
648 ErrorStatus write(TIter& iter, std::size_t len) const
649 {
650 if (!currentFieldValid()) {
652 }
653
654 auto es = ErrorStatus::NumOfErrorStatuses;
655 comms::util::tupleForSelectedType<Members>(m_memIdx, makeWriteHelper(es, iter, len, &m_storage));
656 return es;
657 }
658
659 static constexpr bool hasWriteNoStatus()
660 {
661 return comms::util::tupleTypeAccumulate<Members>(
662 true, comms::field::details::FieldHasWriteNoStatusHelper<>());
663 }
664
665 template <typename TIter>
666 void writeNoStatus(TIter& iter) const
667 {
668 if (!currentFieldValid()) {
669 return;
670 }
671
672 comms::util::tupleForSelectedType<Members>(m_memIdx, makeWriteNoStatusHelper(iter, &m_storage));
673 }
674
675
676 std::size_t currentField() const
677 {
678 return m_memIdx;
679 }
680
681 void selectField(std::size_t idx)
682 {
683 if (idx == m_memIdx) {
684 return;
685 }
686
687 checkDestruct();
688 if (!isIdxValid(idx)) {
689 return;
690 }
691
692 comms::util::tupleForSelectedType<Members>(
693 idx, details::VariantFieldConstructHelper<>(&m_storage));
694 m_memIdx = idx;
695 }
696
697 template <typename TFunc>
698 void currentFieldExec(TFunc&& func)
699 {
700 if (!currentFieldValid()) {
701 static constexpr bool Invalid_field_execution = false;
702 static_cast<void>(Invalid_field_execution);
703 COMMS_ASSERT(Invalid_field_execution);
704 return;
705 }
706
707 comms::util::tupleForSelectedType<Members>(m_memIdx, makeExecHelper(std::forward<TFunc>(func)));
708 }
709
710 template <typename TFunc>
711 void currentFieldExec(TFunc&& func) const
712 {
713 if (!currentFieldValid()) {
714 static constexpr bool Invalid_field_execution = false;
715 static_cast<void>(Invalid_field_execution);
716 COMMS_ASSERT(Invalid_field_execution);
717 return;
718 }
719
720 comms::util::tupleForSelectedType<Members>(m_memIdx, makeConstExecHelper(std::forward<TFunc>(func)));
721 }
722
723 template <std::size_t TIdx, typename... TArgs>
724 typename std::tuple_element<TIdx, Members>::type& initField(TArgs&&... args)
725 {
726 static_assert(isIdxValid(TIdx), "Only valid field index can be used");
727 COMMS_ASSERT(!currentFieldValid());
728
729 using FieldType = typename std::tuple_element<TIdx, Members>::type;
730 new (&m_storage) FieldType(std::forward<TArgs>(args)...);
731 m_memIdx = TIdx;
732 updateVersionInternal(VersionTag<>());
733 return reinterpret_cast<FieldType&>(m_storage);
734 }
735
736 template <std::size_t TIdx>
737 void deinitField()
738 {
739 static_assert(isIdxValid(TIdx), "Only valid field index can be used");
740 COMMS_ASSERT(m_memIdx == TIdx);
741
742 using FieldType = typename std::tuple_element<TIdx, Members>::type;
743 reinterpret_cast<FieldType*>(&m_storage)->~FieldType();
744 m_memIdx = MembersCount;
745 }
746
747 template <std::size_t TIdx>
748 typename std::tuple_element<TIdx, Members>::type& accessField()
749 {
750 static_assert(isIdxValid(TIdx), "Only valid field index can be used");
751 COMMS_ASSERT(TIdx == m_memIdx); // Accessing non initialised field
752
753 using FieldType = typename std::tuple_element<TIdx, Members>::type;
754 return reinterpret_cast<FieldType&>(m_storage);
755 }
756
757 template <std::size_t TIdx>
758 const typename std::tuple_element<TIdx, Members>::type& accessField() const
759 {
760 static_assert(isIdxValid(TIdx), "Something is wrong");
761 COMMS_ASSERT(TIdx == m_memIdx); // Accessing non initialised field
762
763 using FieldType = typename std::tuple_element<TIdx, Members>::type;
764 return reinterpret_cast<const FieldType&>(m_storage);
765 }
766
767 bool currentFieldValid() const
768 {
769 return isIdxValid(m_memIdx);
770 }
771
772 void reset()
773 {
774 checkDestruct();
775 COMMS_ASSERT(!currentFieldValid());
776 }
777
778 static constexpr bool isVersionDependent()
779 {
780 return details::VariantVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value;
781 }
782
783 bool setVersion(VersionType version)
784 {
785 return setVersionInternal(version, VersionTag<>());
786 }
787
788 VersionType getVersion() const
789 {
790 return getVersionInternal(VersionTag<>());
791 }
792
793private:
794 template <typename... TParams>
795 using VersionDependentTag = comms::details::tag::Tag1<>;
796
797 template <typename... TParams>
798 using NoVersionDependencyTag = comms::details::tag::Tag2<>;
799
800 template <typename... TParams>
801 using ForcedVersionDependencyTag = comms::details::tag::Tag3<>;
802
803 template <typename... TParams>
804 using NoForcedVersionDependencyTag = comms::details::tag::Tag4<>;
805
806 template <typename... TParams>
807 using VersionTag =
808 typename comms::util::LazyShallowConditional<
809 details::VariantVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value
810 >::template Type<
811 VersionDependentTag,
812 NoVersionDependencyTag
813 >;
814
815 template <typename TFunc>
816 auto makeExecHelper(TFunc&& func) -> details::VariantExecHelper<decltype(std::forward<TFunc>(func))>
817 {
818 using FuncType = decltype(std::forward<TFunc>(func));
819 return details::VariantExecHelper<FuncType>(&m_storage, std::forward<TFunc>(func));
820 }
821
822 template <typename TFunc>
823 auto makeConstExecHelper(TFunc&& func) const -> details::VariantConstExecHelper<decltype(std::forward<TFunc>(func))>
824 {
825 using FuncType = decltype(std::forward<TFunc>(func));
826 return details::VariantConstExecHelper<FuncType>(&m_storage, std::forward<TFunc>(func));
827 }
828
829 template <typename TIter, typename TVerBase>
830 details::VariantReadHelper<TIter, TVerBase, details::VariantVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value>
831 makeReadHelper(
833 TIter& iter,
834 std::size_t len,
835 void* storage,
836 TVerBase& verBase)
837 {
838 m_memIdx = 0;
839 static constexpr bool VerDependent = isVersionDependent();
840 return
841 details::VariantReadHelper<TIter, TVerBase, VerDependent>(
842 m_memIdx, es, iter, len, storage, verBase);
843 }
844
845 template <typename TIter>
846 static details::VariantFieldWriteHelper<TIter> makeWriteHelper(comms::ErrorStatus& es, TIter& iter, std::size_t len, const void* storage)
847 {
848 return details::VariantFieldWriteHelper<TIter>(es, iter, len, storage);
849 }
850
851 template <typename TIter>
852 static details::VariantWriteNoStatusHelper<TIter> makeWriteNoStatusHelper(TIter& iter, const void* storage)
853 {
854 return details::VariantWriteNoStatusHelper<TIter>(iter, storage);
855 }
856
857 void checkDestruct()
858 {
859 if (currentFieldValid()) {
860 comms::util::tupleForSelectedType<Members>(
861 m_memIdx, details::VariantFieldDestructHelper<>(&m_storage));
862 m_memIdx = MembersCount;
863 }
864 }
865
866 static constexpr bool isIdxValid(std::size_t idx)
867 {
868 return idx < MembersCount;
869 }
870
871 template <typename... TParams>
872 bool setVersionInternal(VersionType version, NoVersionDependencyTag<TParams...>)
873 {
874 static_cast<void>(version);
875 return false;
876 }
877
878 template <typename... TParams>
879 bool setVersionInternal(VersionType version, VersionDependentTag<TParams...>)
880 {
881 VersionBaseImpl::m_version = version;
882 bool updated = false;
883 if (currentFieldValid()) {
884 comms::util::tupleForSelectedType<Members>(
885 m_memIdx, details::VariantSetVersionHelper<VersionType>(version, updated, &m_storage));
886 }
887 return updated;
888 }
889
890
891 template <typename... TParams>
892 VersionType getVersionInternal(VersionDependentTag<TParams...>) const
893 {
894 return VersionBaseImpl::m_version;;
895 }
896
897 template <typename... TParams>
898 void updateVersionInternal(NoVersionDependencyTag<TParams...>)
899 {
900 }
901
902 template <typename... TParams>
903 void updateVersionInternal(VersionDependentTag<TParams...>)
904 {
905 setVersion(VersionBaseImpl::m_version);
906 }
907
908 alignas(8) ValueType m_storage;
909 std::size_t m_memIdx = MembersCount;
910};
911
912} // namespace basic
913
914} // namespace field
915
916} // namespace comms
917
918COMMS_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:1917
comms::option::def::FieldType< TMsg > FieldType
Same as comms::option::def::FieldType.
Definition options.h:1492
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.