ORIGINAL
Loading...
Searching...
No Matches
tuple.h
Go to the documentation of this file.
1#ifndef TUPLE_H
2#define TUPLE_H
3
4#include "printable.h"
5#include "comparable.h"
6#include "couple.h"
7#include "types.h"
8
37namespace original {
38
56 template<typename... TYPES>
57 class tuple final : public printable, public comparable<tuple<TYPES...>> {
58 static constexpr u_integer SIZE = sizeof...(TYPES);
59
71 template<u_integer I, typename... TS>
72 class tupleImpl;
73
83 template<u_integer I, typename T>
84 class tupleImpl<I, T> : public printable, public comparable<tupleImpl<I, T>> {
85 T cur_elem;
86
87 public:
88 explicit tupleImpl() = default;
89 explicit tupleImpl(T&& cur);
90 tupleImpl(tupleImpl&& other) noexcept;
91 tupleImpl(const tupleImpl& other);
92 tupleImpl& operator=(tupleImpl&& other) noexcept;
93 void swap(tupleImpl& other) noexcept;
94
95 template<u_integer I_DIFF>
96 const auto& get() const;
97
98 template<u_integer I_DIFF>
99 auto& get();
100
101 template<u_integer I_DIFF, typename E>
102 void set(const E& e);
103
104 integer compareTo(const tupleImpl& other) const override;
105 std::string toString(bool enter) const override;
106
107 friend class tuple;
108 };
109
120 template<u_integer I, typename T, typename TS>
121 class tupleImpl<I, T, TS> : public printable, public comparable<tupleImpl<I, T, TS>> {
122 T cur_elem;
124
125 public:
126 tupleImpl() = default;
127 explicit tupleImpl(T&& cur, TS&& next_elems);
128 tupleImpl(tupleImpl&& other) noexcept;
129 tupleImpl(const tupleImpl& other);
130 tupleImpl& operator=(tupleImpl&& other) noexcept;
131 void swap(tupleImpl& other) noexcept;
132
133 template<u_integer I_DIFF>
134 const auto& get() const;
135
136 template<u_integer I_DIFF>
137 auto& get();
138
139 template<u_integer I_DIFF, typename E>
140 void set(const E& e);
141
142 integer compareTo(const tupleImpl& other) const override;
143 std::string toString(bool enter) const override;
144
145 friend class tuple;
146 };
147
158 template<u_integer I, typename T, typename... TS>
159 class tupleImpl<I, T, TS...> : public printable, public comparable<tupleImpl<I, T, TS...>> {
160 T cur_elem;
161 tupleImpl<I + 1, TS...> next;
162
163 public:
164 explicit tupleImpl(T&& cur, TS&&... next_elems);
165 explicit tupleImpl(const T& cur = T{}, const tupleImpl<I + 1, TS...>& nt = tupleImpl<I + 1, TS...>{});
166 tupleImpl(tupleImpl&& other) noexcept;
167 tupleImpl(const tupleImpl& other);
168 tupleImpl& operator=(tupleImpl&& other) noexcept;
169 void swap(tupleImpl& other) noexcept;
170
171 template<u_integer I_DIFF>
172 const auto& get() const;
173
174 template<u_integer I_DIFF>
175 auto& get();
176
177 template<u_integer I_DIFF, typename E>
178 void set(const E& e);
179
180 integer compareTo(const tupleImpl& other) const override;
181 std::string toString(bool enter) const override;
182
183 friend class tuple;
184 };
185
186 tupleImpl<0, TYPES...> elems;
187
198 template<u_integer... IDX_S, u_integer BEGIN_IDX>
199 auto _slice(std::integer_sequence<u_integer, IDX_S...> indexes,
200 std::integral_constant<u_integer, BEGIN_IDX> begin) const;
201
214 template<typename... O_TYPES, u_integer... T_SIZE, u_integer... O_SIZE>
215 tuple<TYPES..., O_TYPES...> _concat(const tuple<O_TYPES...>& other,
218
219 public:
220 tuple() = default;
221
228 explicit tuple(TYPES&&... e);
229
238
249
259 tuple(tuple&& other) noexcept;
260
273
284 void swap(tuple& other) noexcept;
285
295 static consteval u_integer size() noexcept;
296
306
316
328
339
354
367
378
389
391
394
397 };
398
410
422}
423
425 template<typename... TYPES>
427
432 template<typename... TYPES>
433 struct tuple_size<original::tuple<TYPES...>> //NOLINT
434 : std::integral_constant<std::size_t, sizeof...(TYPES)> {};
435
447 template<std::size_t I, typename... TYPES>
448 struct tuple_element<I, original::tuple<TYPES...>> { //NOLINT
449 using type = std::tuple_element_t<I, std::tuple<TYPES...>>;
450 };
451
460 template<std::size_t I, typename... TYPES>
461 constexpr auto& get(original::tuple<TYPES...>& t) noexcept; //NOLINT
462
471 template<std::size_t I, typename... TYPES>
472 constexpr const auto& get(const original::tuple<TYPES...>& t) noexcept; //NOLINT
473
482 template<std::size_t I, typename... TYPES>
483 constexpr auto&& get(original::tuple<TYPES...>&& t) noexcept; //NOLINT
484}
485
486template <typename ... TYPES>
487template <original::u_integer I, typename T>
489 : cur_elem(std::forward<T>(cur)) {}
490
491template<typename... TYPES>
492template<original::u_integer I, typename T>
494 : cur_elem(std::move(other.cur_elem)) {}
495
496template<typename... TYPES>
497template<original::u_integer I, typename T>
499 : cur_elem(other.cur_elem) {}
500
501template<typename... TYPES>
502template<original::u_integer I, typename T>
503auto original::tuple<TYPES...>::tupleImpl<I, T>::operator=(tupleImpl&& other) noexcept -> tupleImpl&
504{
505 if (this == &other)
506 return *this;
507 cur_elem = std::move(other.cur_elem);
508 return *this;
509}
510
511template <typename ... TYPES>
512template <original::u_integer I, typename T>
513void original::tuple<TYPES...>::tupleImpl<I, T>::swap(tupleImpl& other) noexcept
514{
515 if (this == &other)
516 return;
517
518 std::swap(this->cur_elem, other.cur_elem);
519}
520
521template<typename... TYPES>
522template<original::u_integer I, typename T>
523template<original::u_integer I_DIFF>
525 staticError<outOfBoundError, (I_DIFF > 0)>::asserts();
526
527 return cur_elem;
528}
529
530template<typename... TYPES>
531template<original::u_integer I, typename T>
532template<original::u_integer I_DIFF>
534 staticError<outOfBoundError, (I_DIFF > 0)>::asserts();
535
536 return cur_elem;
537}
538
539template<typename... TYPES>
540template<original::u_integer I, typename T>
541template<original::u_integer I_DIFF, typename E>
543 staticError<outOfBoundError, (I_DIFF > 0)>::asserts();
544 staticError<valueError, !std::is_convertible_v<E, T>>::asserts();
545
546 cur_elem = static_cast<T>(e);
547}
548
549template<typename... TYPES>
550template<original::u_integer I, typename T>
551auto original::tuple<TYPES...>::tupleImpl<I, T>::compareTo(const tupleImpl& other) const -> integer
552{
553 if constexpr (Comparable<T>){
554 if (cur_elem != other.cur_elem)
555 return cur_elem < other.cur_elem ? -1 : 1;
556 }
557 return 0;
558}
559
560template<typename... TYPES>
561template<original::u_integer I, typename T>
562std::string original::tuple<TYPES...>::tupleImpl<I, T>::toString(bool enter) const {
563 std::stringstream ss;
564 if constexpr (I != 0)
565 ss << ", ";
566 ss << formatString(cur_elem);
567 return ss.str();
568}
569
570template <typename ... TYPES>
571template <original::u_integer I, typename T, typename TS>
573 : cur_elem(std::forward<T>(cur)), next(std::forward<TS>(next_elems)) {}
574
575template<typename... TYPES>
576template<original::u_integer I, typename T, typename TS>
578 : cur_elem(std::move(other.cur_elem)), next(std::move(other.next)) {}
579
580template<typename... TYPES>
581template<original::u_integer I, typename T, typename TS>
583 : cur_elem(other.cur_elem), next(other.next) {}
584
585template<typename... TYPES>
586template<original::u_integer I, typename T, typename TS>
588 tupleImpl&& other) noexcept -> tupleImpl&
589{
590 if (this == &other)
591 return *this;
592 cur_elem = std::move(other.cur_elem);
593 next = std::move(other.next);
594 return *this;
595}
596
597template <typename ... TYPES>
598template <original::u_integer I, typename T, typename TS>
599void original::tuple<TYPES...>::tupleImpl<I, T, TS>::swap(tupleImpl& other) noexcept
600{
601 if (this == &other)
602 return;
603
604 std::swap(this->cur_elem, other.cur_elem);
605 this->next.swap(other.next);
606}
607
608template<typename... TYPES>
609template<original::u_integer I, typename T, typename TS>
610template<original::u_integer I_DIFF>
612 if constexpr (I_DIFF == 0){
613 return cur_elem;
614 } else{
615 return next.template get<I_DIFF - 1>();
616 }
617}
618
619template<typename... TYPES>
620template<original::u_integer I, typename T, typename TS>
621template<original::u_integer I_DIFF>
623 if constexpr (I_DIFF == 0){
624 return cur_elem;
625 } else{
626 return next.template get<I_DIFF - 1>();
627 }
628}
629
630template<typename... TYPES>
631template<original::u_integer I, typename T, typename TS>
632template<original::u_integer I_DIFF, typename E>
634 if constexpr (I_DIFF == 0){
635 staticError<valueError, !std::is_convertible_v<E, T>>::asserts();
636
637 cur_elem = static_cast<T>(e);
638 } else{
639 next.template set<I_DIFF - 1, E>(e);
640 }
641}
642
643template<typename... TYPES>
644template<original::u_integer I, typename T, typename TS>
646 const tupleImpl& other) const -> integer
647{
648 if constexpr (Comparable<T>){
649 if (cur_elem != other.cur_elem)
650 return cur_elem < other.cur_elem ? -1 : 1;
651 }
652 return next.compareTo(other.next);
653}
654
655template<typename... TYPES>
656template<original::u_integer I, typename T, typename TS>
658 std::stringstream ss;
659 if constexpr (I != 0)
660 ss << ", ";
661 ss << formatString(cur_elem);
662 ss << formatString(next);
663 return ss.str();
664}
665
666template <typename ... TYPES>
667template <original::u_integer I, typename T, typename ... TS>
669 : cur_elem(std::forward<T>(cur)), next(std::forward<TS>(next_elems)...) {}
670
671template<typename... TYPES>
672template<original::u_integer I, typename T, typename... TS>
673original::tuple<TYPES...>::tupleImpl<I, T, TS...>::tupleImpl(const T& cur, const tupleImpl<I + 1, TS...>& nt)
674 : cur_elem(cur), next(nt) {}
675
676template<typename... TYPES>
677template<original::u_integer I, typename T, typename... TS>
679 : cur_elem(std::move(other.cur_elem)), next(std::move(other.next)) {}
680
681template<typename... TYPES>
682template<original::u_integer I, typename T, typename... TS>
684 : cur_elem(other.cur_elem), next(other.next) {}
685
686template<typename... TYPES>
687template<original::u_integer I, typename T, typename... TS>
689 tupleImpl&& other) noexcept -> tupleImpl&
690{
691 if (this == &other)
692 return *this;
693 cur_elem = std::move(other.cur_elem);
694 next = std::move(other.next);
695 return *this;
696}
697
698template <typename ... TYPES>
699template <original::u_integer I, typename T, typename ... TS>
701{
702 if (this == &other)
703 return;
704
705 std::swap(this->cur_elem, other.cur_elem);
706 this->next.swap(other.next);
707}
708
709template<typename... TYPES>
710template<original::u_integer I, typename T, typename... TS>
711template<original::u_integer I_DIFF>
713 if constexpr (I_DIFF == 0){
714 return cur_elem;
715 } else{
716 return next.template get<I_DIFF - 1>();
717 }
718}
719
720template<typename... TYPES>
721template<original::u_integer I, typename T, typename... TS>
722template<original::u_integer I_DIFF>
724 if constexpr (I_DIFF == 0){
725 return cur_elem;
726 } else{
727 return next.template get<I_DIFF - 1>();
728 }
729}
730
731template<typename... TYPES>
732template<original::u_integer I, typename T, typename... TS>
733template<original::u_integer I_DIFF, typename E>
735 if constexpr (I_DIFF == 0){
736 staticError<valueError, !std::is_convertible_v<E, T>>::asserts();
737
738 cur_elem = static_cast<T>(e);
739 } else{
740 next.template set<I_DIFF - 1, E>(e);
741 }
742}
743
744template<typename... TYPES>
745template<original::u_integer I, typename T, typename... TS>
748 if constexpr (Comparable<T>){
749 if (cur_elem != other.cur_elem)
750 return cur_elem < other.cur_elem ? -1 : 1;
751 }
752 return next.compareTo(other.next);
753}
754
755template<typename... TYPES>
756template<original::u_integer I, typename T, typename... TS>
758 std::stringstream ss;
759 if constexpr (I != 0)
760 ss << ", ";
761 ss << formatString(cur_elem);
762 ss << formatString(next);
763 return ss.str();
764}
765
766template<typename... TYPES>
767template<original::u_integer... IDX_S, original::u_integer BEGIN_IDX>
768auto original::tuple<TYPES...>::_slice(std::integer_sequence<u_integer, IDX_S...>,
769 std::integral_constant<u_integer, BEGIN_IDX>) const {
770 return tuple<decltype(this->get<BEGIN_IDX + IDX_S>())...>(this->get<BEGIN_IDX + IDX_S>()...);
771}
772
773template<typename... TYPES>
774template<typename... O_TYPES, original::u_integer... T_SIZE, original::u_integer... O_SIZE>
775original::tuple<TYPES..., O_TYPES...>
776original::tuple<TYPES...>::_concat(const tuple<O_TYPES...> &other,
777 indexSequence<T_SIZE...>,
778 indexSequence<O_SIZE...>) const {
779 return tuple<TYPES..., O_TYPES...>{TYPES(this->get<T_SIZE>())..., O_TYPES(other.template get<O_SIZE>())...};
780}
781
782template <typename ... TYPES>
785
786template<typename... TYPES>
788
789template<typename... TYPES>
791 if (this == &other) return *this;
792 this->elems = other.elems;
793 return *this;
794}
795
796template<typename... TYPES>
798 : elems(std::move(other.elems)) {}
799
800template<typename... TYPES>
802 if (this == &other) return *this;
803 this->elems = std::move(other.elems);
804 return *this;
805}
806
807template <typename ... TYPES>
809{
810 if (this == &other)
811 return;
812
813 this->elems.swap(other.elems);
814}
815
816template<typename... TYPES>
818 return SIZE;
819}
820
821template<typename... TYPES>
822template<original::u_integer IDX>
824 return elems.template get<IDX>();
825}
826
827template<typename... TYPES>
828template<original::u_integer IDX>
830 return elems.template get<IDX>();
831}
832
833template<typename... TYPES>
834template<original::u_integer IDX, typename E>
836 elems.template set<IDX, E>(e);
837 return *this;
838}
839
840template<typename... TYPES>
841template<original::u_integer BEGIN_IDX, original::u_integer N_ELEMS>
843 constexpr bool out_of_bound = BEGIN_IDX >= SIZE || BEGIN_IDX + N_ELEMS > SIZE;
845
846 return this->_slice(
847 std::make_integer_sequence<u_integer, N_ELEMS>{},
848 std::integral_constant<u_integer, BEGIN_IDX>{}
849 );
850}
851
852template<typename... TYPES>
854 return elems.compareTo(other.elems);
855}
856
857template<typename... TYPES>
859 std::stringstream ss;
860 ss << this->className();
861 ss << "(" << elems << ")";
862 return ss.str();
863}
864
865template<typename... TYPES>
867 return "tuple";
868}
869
870template <typename ... TYPES>
871template <typename ... O_TYPES>
874{
875 return this->_concat(other,
876 makeSequence<sizeof...(TYPES)>(),
877 makeSequence<sizeof...(O_TYPES)>());
878}
879
880template<typename F_TYPE, typename S_TYPE>
881original::tuple<F_TYPE, S_TYPE> original::makeTuple(const couple<F_TYPE, S_TYPE> &cp) {
883 F_TYPE(cp.template get<0>()),
884 S_TYPE(cp.template get<1>())
885 };
886}
887
888template <typename F_TYPE, typename S_TYPE>
889original::tuple<F_TYPE, S_TYPE> original::makeTuple(couple<F_TYPE, S_TYPE>&& cp)
890{
892 std::move(cp).template get<0>(),
893 std::move(cp).template get<1>()
894 };
895}
896
897template <typename... TYPES>
898void std::swap(original::tuple<TYPES...>& lhs, original::tuple<TYPES...>& rhs) noexcept // NOLINT
899{
900 lhs.swap(rhs);
901}
902
903template<std::size_t I, typename... TYPES>
904constexpr auto& std::get(original::tuple<TYPES...> &t) noexcept { //NOLINT
905 return t.template get<I>();
906}
907
908template<std::size_t I, typename... TYPES>
909constexpr const auto& std::get(const original::tuple<TYPES...> &t) noexcept { //NOLINT
910 return t.template get<I>();
911}
912
913template<std::size_t I, typename... TYPES>
914constexpr auto&& std::get(original::tuple<TYPES...> &&t) noexcept { //NOLINT
915 return std::move(t.template get<I>());
916}
917
918#endif //TUPLE_H
integer compareTo(const autoPtr &other) const override
Compare reference counters.
Definition autoPtr.h:714
void swap(autoPtr &other) noexcept
Swaps the reference counters between two autoPtr instances.
Definition autoPtr.h:703
Base class for comparable objects.
Definition comparable.h:35
Container for two heterogeneous elements.
Definition couple.h:55
Unique ownership smart pointer with move semantics.
Definition ownerPtr.h:37
Base class providing polymorphic string conversion capabilities.
Definition printable.h:39
Abstract base class for unique element containers.
Definition set.h:44
static void asserts()
Triggers static assertion if the condition is true.
Definition error.h:174
Container for multiple heterogeneous elements.
Definition tuple.h:57
tuple(TYPES &&... e)
Constructs a tuple with the given elements.
Definition tuple.h:783
tuple & operator=(const tuple &other)
Copy assignment operator - assigns contents from another tuple.
Definition tuple.h:790
std::string toString(bool enter) const override
Converts the tuple to a human-readable string representation.
Definition tuple.h:858
tuple< TYPES..., O_TYPES... > operator+(const tuple< O_TYPES... > &other) const
Concatenates this tuple with another tuple.
const auto & get() const
Gets the element at the specified index (const version)
Definition tuple.h:823
tuple(const tuple &other)
Copy constructor - creates a deep copy of another tuple.
Definition tuple.h:787
void swap(tuple &other) noexcept
Swaps contents with another tuple.
Definition tuple.h:808
std::string className() const override
Returns the class name identifier for this tuple type.
Definition tuple.h:866
tuple & set(const E &e)
Sets the element at the specified index.
tuple & operator=(tuple &&other) noexcept
Move assignment operator - transfers ownership from another tuple.
Definition tuple.h:801
friend tuple< F_TYPE, S_TYPE > makeTuple(const couple< F_TYPE, S_TYPE > &cp)
Creates a tuple from a couple (copy version)
tuple(tuple &&other) noexcept
Move constructor - transfers ownership from another tuple.
Definition tuple.h:797
auto slice() const
Extracts a sub-tuple from this tuple.
Definition tuple.h:842
Interface for objects that can be compared.
Generic pair container implementation.
std::uint32_t u_integer
32-bit unsigned integer type for sizes and indexes
Definition config.h:263
std::int64_t integer
64-bit signed integer type for arithmetic operations
Definition config.h:254
Main namespace for the project Original.
Definition algorithms.h:21
consteval auto makeSequence() noexcept
Creates an index sequence of given length.
Definition types.h:659
tuple< F_TYPE, S_TYPE > makeTuple(const couple< F_TYPE, S_TYPE > &cp)
Creates a tuple from a couple (copy version)
constexpr l_floating E
The mathematical constant E (Euler's number).
Definition maths.h:31
Standard namespace extensions for original::alternative.
Definition allocator.h:351
void swap(original::objPoolAllocator< TYPE > &lhs, original::objPoolAllocator< TYPE > &rhs) noexcept
Specialization of std::swap for objPoolAllocator.
Definition allocator.h:635
constexpr auto & get(original::couple< F, S > &c) noexcept
Structured binding support - get for non-const lvalue reference.
Definition couple.h:426
Interface for polymorphic string formatting and output.
Core type system foundations and concept definitions.