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
32
33namespace original{
34
52 template<typename... TYPES>
53 class tuple final : public printable, public comparable<tuple<TYPES...>>{
54 static constexpr u_integer SIZE = sizeof...(TYPES);
55
67 template<u_integer I, typename... TS>
68 class tupleImpl;
69
70 template<u_integer I, typename T>
71 class tupleImpl<I, T> : public printable, public comparable<tupleImpl<I, T>>{
72 T cur_elem;
73
78 explicit tupleImpl(const T& cur = T{});
79
80 tupleImpl(tupleImpl<I, T>&& other) noexcept;
81
82 tupleImpl(const tupleImpl<I, T>& other);
83
84 tupleImpl<I, T>& operator=(tupleImpl<I, T>&& other) noexcept;
85
86 template<u_integer I_DIFF>
87 const auto& get() const;
88
89 template<u_integer I_DIFF>
90 auto& get();
91
92 template<u_integer I_DIFF, typename E>
93 void set(const E& e);
94 public:
95 friend class tuple;
96 integer compareTo(const tupleImpl<I, T>& other) const override;
97
98 std::string toString(bool enter) const override;
99 };
100
101 template<u_integer I, typename T, typename TS>
102 class tupleImpl<I, T, TS> : public printable, public comparable<tupleImpl<I, T, TS>>{
103 T cur_elem;
104 tupleImpl<I + 1, TS> next;
105
111 explicit tupleImpl(const T& cur = T{}, const TS& next_elems = TS{});
112
113 tupleImpl(tupleImpl<I, T, TS>&& other) noexcept;
114
115 tupleImpl(const tupleImpl<I, T, TS>& other);
116
117 tupleImpl<I, T, TS>& operator=(tupleImpl<I, T, TS>&& other) noexcept;
118
119 template<u_integer I_DIFF>
120 const auto& get() const;
121
122 template<u_integer I_DIFF>
123 auto& get();
124
125 template<u_integer I_DIFF, typename E>
126 void set(const E& e);
127 public:
128 friend class tuple;
129 integer compareTo(const tupleImpl<I, T, TS>& other) const override;
130
131 std::string toString(bool enter) const override;
132 };
133
134 template<u_integer I, typename T, typename... TS>
135 class tupleImpl<I, T, TS...> : public printable, public comparable<tupleImpl<I, T, TS...>>{
136 T cur_elem;
137 tupleImpl<I + 1, TS...> next;
138
144 explicit tupleImpl(const T& cur, const TS&... next_elems);
145
146 explicit tupleImpl(const T& cur = T{}, const tupleImpl<I + 1, TS...>& nt = tupleImpl<I + 1, TS...>{});
147
148 tupleImpl(tupleImpl<I, T, TS...>&& other) noexcept;
149
150 tupleImpl(const tupleImpl<I, T, TS...>& other);
151
152 tupleImpl<I, T, TS...>& operator=(tupleImpl<I, T, TS...>&& other) noexcept;
153
154 template<u_integer I_DIFF>
155 const auto& get() const;
156
157 template<u_integer I_DIFF>
158 auto& get();
159
160 template<u_integer I_DIFF, typename E>
161 void set(const E& e);
162 public:
163 friend class tuple;
164 integer compareTo(const tupleImpl<I, T, TS...>& other) const override;
165
166 std::string toString(bool enter) const override;
167 };
168
169 tupleImpl<0, TYPES...> elems;
170
177 template<u_integer... IDX_S, u_integer BEGIN_IDX>
178 auto _slice(std::integer_sequence<u_integer, IDX_S...> indexes,
179 std::integral_constant<u_integer, BEGIN_IDX> begin) const;
180
191 template<typename... O_TYPES, u_integer... T_SIZE, u_integer... O_SIZE>
192 tuple<TYPES..., O_TYPES...> _concat(const tuple<O_TYPES...>& other,
193 std::integer_sequence<u_integer, T_SIZE...> ts,
194 std::integer_sequence<u_integer, O_SIZE...> os) const;
195
196 public:
197
198 explicit tuple();
199
204 explicit tuple(const TYPES&... e);
205
210 tuple(const tuple& other);
211
217 tuple& operator=(const tuple& other);
218
223 tuple(tuple&& other) noexcept;
224
230 tuple& operator=(tuple&& other) noexcept;
231
236 static constexpr u_integer size();
237
246 template<u_integer IDX>
247 const auto& get() const;
248
257 template<u_integer IDX>
258 auto& get();
259
272 template<u_integer IDX, typename E>
273 tuple& set(const E& e);
274
281 template<u_integer BEGIN_IDX, u_integer N_ELEMS>
282 auto slice() const;
283
297 integer compareTo(const tuple& other) const override;
298
304 std::string toString(bool enter) const override;
305
310 std::string className() const override;
311
312 ~tuple() override = default;
313
321 template<typename F_TYPE, typename S_TYPE>
322 friend tuple<F_TYPE, S_TYPE> makeTuple(const couple<F_TYPE, S_TYPE>& cp);
323
332 template<typename... L_TYPES, typename... R_TYPES>
333 friend tuple<L_TYPES..., R_TYPES...> operator+(const tuple<L_TYPES...>& lt, const tuple<R_TYPES...>& rt);
334 };
335
336 template<typename F_TYPE, typename S_TYPE>
338
339 template<typename... L_TYPES, typename... R_TYPES>
340 tuple<L_TYPES..., R_TYPES...> operator+(const tuple<L_TYPES...>& lt, const tuple<R_TYPES...>& rt);
341}
342
343namespace std {
344
349 template<typename... TYPES>
350 struct tuple_size<original::tuple<TYPES...>> //NOLINT
351 : std::integral_constant<std::size_t, sizeof...(TYPES)> {};
352
364 template<std::size_t I, typename... TYPES>
365 struct tuple_element<I, original::tuple<TYPES...>> { //NOLINT
366 using type = std::tuple_element_t<I, std::tuple<TYPES...>>;
367 };
368
377 template<std::size_t I, typename... TYPES>
378 constexpr auto& get(original::tuple<TYPES...>& t) noexcept; //NOLINT
379
388 template<std::size_t I, typename... TYPES>
389 constexpr const auto& get(const original::tuple<TYPES...>& t) noexcept; //NOLINT
390
399 template<std::size_t I, typename... TYPES>
400 constexpr auto&& get(original::tuple<TYPES...>&& t) noexcept; //NOLINT
401}
402
403
404template<typename... TYPES>
405template<original::u_integer I, typename T>
407 : cur_elem(cur) {}
408
409template<typename... TYPES>
410template<original::u_integer I, typename T>
411original::tuple<TYPES...>::tupleImpl<I, T>::tupleImpl(tupleImpl<I, T>&& other) noexcept
412 : cur_elem(std::move(other.cur_elem)) {}
413
414template<typename... TYPES>
415template<original::u_integer I, typename T>
416original::tuple<TYPES...>::tupleImpl<I, T>::tupleImpl(const tupleImpl<I, T>& other)
417 : cur_elem(other.cur_elem) {}
418
419template<typename... TYPES>
420template<original::u_integer I, typename T>
421auto original::tuple<TYPES...>::tupleImpl<I, T>::operator=(tupleImpl<I, T>&& other) noexcept -> tupleImpl<I, T>&
422{
423 if (this == &other)
424 return *this;
425 cur_elem = std::move(other.cur_elem);
426 return *this;
427}
428
429template<typename... TYPES>
430template<original::u_integer I, typename T>
431template<original::u_integer I_DIFF>
433 staticError<outOfBoundError, (I_DIFF > 0)>{};
434
435 return cur_elem;
436}
437
438template<typename... TYPES>
439template<original::u_integer I, typename T>
440template<original::u_integer I_DIFF>
442 staticError<outOfBoundError, (I_DIFF > 0)>{};
443
444 return cur_elem;
445}
446
447template<typename... TYPES>
448template<original::u_integer I, typename T>
449template<original::u_integer I_DIFF, typename E>
451 staticError<outOfBoundError, (I_DIFF > 0)>{};
452 staticError<valueError, !std::is_convertible_v<E, T>>{};
453
454 cur_elem = static_cast<T>(e);
455}
456
457template<typename... TYPES>
458template<original::u_integer I, typename T>
459auto original::tuple<TYPES...>::tupleImpl<I, T>::compareTo(const tupleImpl<I, T>& other) const -> integer
460{
461 if constexpr (Comparable<T>){
462 if (cur_elem != other.cur_elem)
463 return cur_elem < other.cur_elem ? -1 : 1;
464 }
465 return 0;
466}
467
468template<typename... TYPES>
469template<original::u_integer I, typename T>
470std::string original::tuple<TYPES...>::tupleImpl<I, T>::toString(bool enter) const {
471 std::stringstream ss;
472 if constexpr (I != 0)
473 ss << ", ";
474 ss << formatString(cur_elem);
475 return ss.str();
476}
477
478template<typename... TYPES>
479template<original::u_integer I, typename T, typename TS>
480original::tuple<TYPES...>::tupleImpl<I, T, TS>::tupleImpl(const T& cur, const TS& next_elems)
481 : cur_elem(cur), next(next_elems) {}
482
483template<typename... TYPES>
484template<original::u_integer I, typename T, typename TS>
485original::tuple<TYPES...>::tupleImpl<I, T, TS>::tupleImpl(tupleImpl<I, T, TS>&& other) noexcept
486 : cur_elem(std::move(other.cur_elem)), next(std::move(other.next)) {}
487
488template<typename... TYPES>
489template<original::u_integer I, typename T, typename TS>
490original::tuple<TYPES...>::tupleImpl<I, T, TS>::tupleImpl(const tupleImpl<I, T, TS>& other)
491 : cur_elem(other.cur_elem), next(other.next) {}
492
493template<typename... TYPES>
494template<original::u_integer I, typename T, typename TS>
496 tupleImpl<I, T, TS>&& other) noexcept -> tupleImpl<I, T, TS>&
497{
498 if (this == &other)
499 return *this;
500 cur_elem = std::move(other.cur_elem);
501 next = std::move(other.next);
502 return *this;
503}
504
505template<typename... TYPES>
506template<original::u_integer I, typename T, typename TS>
507template<original::u_integer I_DIFF>
509 if constexpr (I_DIFF == 0){
510 return cur_elem;
511 } else{
512 return next.template get<I_DIFF - 1>();
513 }
514}
515
516template<typename... TYPES>
517template<original::u_integer I, typename T, typename TS>
518template<original::u_integer I_DIFF>
520 if constexpr (I_DIFF == 0){
521 return cur_elem;
522 } else{
523 return next.template get<I_DIFF - 1>();
524 }
525}
526
527template<typename... TYPES>
528template<original::u_integer I, typename T, typename TS>
529template<original::u_integer I_DIFF, typename E>
531 if constexpr (I_DIFF == 0){
532 staticError<valueError, !std::is_convertible_v<E, T>>{};
533
534 cur_elem = static_cast<T>(e);
535 } else{
536 next.template set<I_DIFF - 1, E>(e);
537 }
538}
539
540template<typename... TYPES>
541template<original::u_integer I, typename T, typename TS>
543 const tupleImpl<I, T, TS>& other) const -> integer
544{
545 if constexpr (Comparable<T>){
546 if (cur_elem != other.cur_elem)
547 return cur_elem < other.cur_elem ? -1 : 1;
548 }
549 return next.compareTo(other.next);
550}
551
552template<typename... TYPES>
553template<original::u_integer I, typename T, typename TS>
555 std::stringstream ss;
556 if constexpr (I != 0)
557 ss << ", ";
558 ss << formatString(cur_elem);
559 ss << formatString(next);
560 return ss.str();
561}
562
563template<typename... TYPES>
564template<original::u_integer I, typename T, typename... TS>
565original::tuple<TYPES...>::tupleImpl<I, T, TS...>::tupleImpl(const T& cur, const TS&... next_elems)
566 : cur_elem(cur), next(next_elems...) {}
567
568template<typename... TYPES>
569template<original::u_integer I, typename T, typename... TS>
570original::tuple<TYPES...>::tupleImpl<I, T, TS...>::tupleImpl(const T& cur, const tupleImpl<I + 1, TS...>& nt)
571 : cur_elem(cur), next(nt) {}
572
573template<typename... TYPES>
574template<original::u_integer I, typename T, typename... TS>
575original::tuple<TYPES...>::tupleImpl<I, T, TS...>::tupleImpl(tupleImpl<I, T, TS...> &&other) noexcept
576 : cur_elem(std::move(other.cur_elem)), next(std::move(other.next)) {}
577
578template<typename... TYPES>
579template<original::u_integer I, typename T, typename... TS>
580original::tuple<TYPES...>::tupleImpl<I, T, TS...>::tupleImpl(const tupleImpl<I, T, TS...>& other)
581 : cur_elem(other.cur_elem), next(other.next) {}
582
583template<typename... TYPES>
584template<original::u_integer I, typename T, typename... TS>
586 tupleImpl<I, T, TS...>&& other) noexcept -> tupleImpl<I, T, TS...>&
587{
588 if (this == &other)
589 return *this;
590 cur_elem = std::move(other.cur_elem);
591 next = std::move(other.next);
592 return *this;
593}
594
595template<typename... TYPES>
596template<original::u_integer I, typename T, typename... TS>
597template<original::u_integer I_DIFF>
599 if constexpr (I_DIFF == 0){
600 return cur_elem;
601 } else{
602 return next.template get<I_DIFF - 1>();
603 }
604}
605
606template<typename... TYPES>
607template<original::u_integer I, typename T, typename... TS>
608template<original::u_integer I_DIFF>
610 if constexpr (I_DIFF == 0){
611 return cur_elem;
612 } else{
613 return next.template get<I_DIFF - 1>();
614 }
615}
616
617template<typename... TYPES>
618template<original::u_integer I, typename T, typename... TS>
619template<original::u_integer I_DIFF, typename E>
621 if constexpr (I_DIFF == 0){
622 staticError<valueError, !std::is_convertible_v<E, T>>{};
623
624 cur_elem = static_cast<T>(e);
625 } else{
626 next.template set<I_DIFF - 1, E>(e);
627 }
628}
629
630template<typename... TYPES>
631template<original::u_integer I, typename T, typename... TS>
633original::tuple<TYPES...>::tupleImpl<I, T, TS...>::compareTo(const tupleImpl<I, T, TS...>& other) const {
634 if constexpr (Comparable<T>){
635 if (cur_elem != other.cur_elem)
636 return cur_elem < other.cur_elem ? -1 : 1;
637 }
638 return next.compareTo(other.next);
639}
640
641template<typename... TYPES>
642template<original::u_integer I, typename T, typename... TS>
644 std::stringstream ss;
645 if constexpr (I != 0)
646 ss << ", ";
647 ss << formatString(cur_elem);
648 ss << formatString(next);
649 return ss.str();
650}
651
652template<typename... TYPES>
653template<original::u_integer... IDX_S, original::u_integer BEGIN_IDX>
654auto original::tuple<TYPES...>::_slice(std::integer_sequence<u_integer, IDX_S...>,
655 std::integral_constant<u_integer, BEGIN_IDX>) const {
656 return tuple<decltype(this->get<BEGIN_IDX + IDX_S>())...>(this->get<BEGIN_IDX + IDX_S>()...);
657}
658
659template<typename... TYPES>
660template<typename... O_TYPES, original::u_integer... T_SIZE, original::u_integer... O_SIZE>
661original::tuple<TYPES..., O_TYPES...>
662original::tuple<TYPES...>::_concat(const tuple<O_TYPES...> &other,
663 std::integer_sequence<u_integer, T_SIZE...>,
664 std::integer_sequence<u_integer, O_SIZE...>) const {
665 return tuple<TYPES..., O_TYPES...>{this->get<T_SIZE>()..., other.template get<O_SIZE>()...};
666}
667
668template<typename... TYPES>
669original::tuple<TYPES...>::tuple() : elems() {}
670
671template<typename... TYPES>
672original::tuple<TYPES...>::tuple(const TYPES&... e) : elems(e...) {}
673
674template<typename... TYPES>
675original::tuple<TYPES...>::tuple(const tuple& other) : elems(other.elems) {}
676
677template<typename... TYPES>
679 if (this == &other) return *this;
680 this->elems = other.elems;
681 return *this;
682}
683
684template<typename... TYPES>
685original::tuple<TYPES...>::tuple(tuple&& other) noexcept
686 : elems(std::move(other.elems)) {}
687
688template<typename... TYPES>
689original::tuple<TYPES...>& original::tuple<TYPES...>::operator=(tuple&& other) noexcept {
690 if (this == &other) return *this;
691 this->elems = std::move(other.elems);
692 return *this;
693}
694
695template<typename... TYPES>
697{
698 return SIZE;
699}
700
701template<typename... TYPES>
702template<original::u_integer IDX>
704 return elems.template get<IDX>();
705}
706
707template<typename... TYPES>
708template<original::u_integer IDX>
710 return elems.template get<IDX>();
711}
712
713template<typename... TYPES>
714template<original::u_integer IDX, typename E>
716 elems.template set<IDX, E>(e);
717 return *this;
718}
719
720template<typename... TYPES>
721template<original::u_integer BEGIN_IDX, original::u_integer N_ELEMS>
723 constexpr bool out_of_bound = BEGIN_IDX >= SIZE || BEGIN_IDX + N_ELEMS > SIZE;
725
726 return this->_slice(
727 std::make_integer_sequence<u_integer, N_ELEMS>{},
728 std::integral_constant<u_integer, BEGIN_IDX>{}
729 );
730}
731
732template<typename... TYPES>
734 return elems.compareTo(other.elems);
735}
736
737template<typename... TYPES>
738std::string original::tuple<TYPES...>::toString(bool enter) const {
739 std::stringstream ss;
740 ss << this->className();
741 ss << "(" << elems << ")";
742 return ss.str();
743}
744
745template<typename... TYPES>
747 return "tuple";
748}
749
750template<typename F_TYPE, typename S_TYPE>
752 return original::tuple<F_TYPE, S_TYPE>{cp.template get<0>(), cp.template get<1>()};
753}
754
755template<typename... L_TYPES, typename... R_TYPES>
756original::tuple<L_TYPES..., R_TYPES...>
758 return lt._concat(rt,
759 std::make_integer_sequence<u_integer, sizeof...(L_TYPES)>{},
760 std::make_integer_sequence<u_integer, sizeof...(R_TYPES)>{});
761}
762
763template<std::size_t I, typename... TYPES>
764constexpr auto& std::get(original::tuple<TYPES...> &t) noexcept { //NOLINT
765 return t.template get<I>();
766}
767
768template<std::size_t I, typename... TYPES>
769constexpr const auto& std::get(const original::tuple<TYPES...> &t) noexcept { //NOLINT
770 return t.template get<I>();
771}
772
773template<std::size_t I, typename... TYPES>
774constexpr auto&& std::get(original::tuple<TYPES...> &&t) noexcept { //NOLINT
775 return std::move(t.template get<I>());
776}
777
778#endif //TUPLE_H
Base class for comparable objects.
Definition comparable.h:31
Container for two heterogeneous elements.
Definition couple.h:37
Base class providing polymorphic string conversion capabilities.
Definition printable.h:29
Abstract base class for unique element containers.
Definition set.h:44
Compile-time error assertion utility.
Definition error.h:73
Container for multiple heterogeneous elements.
Definition tuple.h:53
tuple & operator=(const tuple &other)
Copy assignment operator.
Definition tuple.h:678
std::string toString(bool enter) const override
Generate formatted string representation.
Definition tuple.h:738
const auto & get() const
Access element by index (const lvalue-reference version)
Definition tuple.h:703
friend tuple< L_TYPES..., R_TYPES... > operator+(const tuple< L_TYPES... > &lt, const tuple< R_TYPES... > &rt)
Concatenate two tuples (friend function)
std::string className() const override
Get class name identifier.
Definition tuple.h:746
integer compareTo(const tuple &other) const override
Compare two tuples lexicographically.
Definition tuple.h:733
static constexpr u_integer size()
Get the number of elements in the tuple.
Definition tuple.h:696
tuple & set(const E &e)
Set (modify) the value of the element at the specified index.
friend tuple< F_TYPE, S_TYPE > makeTuple(const couple< F_TYPE, S_TYPE > &cp)
Create a tuple from a couple.
auto slice() const
Slice the tuple from a specific index.
Definition tuple.h:722
Interface for objects that can be compared.
Generic pair container implementation.
constexpr auto & get(original::couple< F, S > &c) noexcept
Structured binding support - get for non-const lvalue reference.
Definition couple.h:364
Main namespace for the project Original.
Definition algorithms.h:21
auto operator+(const iterator< T > &it, integer steps) -> iterator< T > *
Adds a number of steps to the iterator's current position and returns a new iterator.
std::uint32_t u_integer
32-bit unsigned integer type for sizes and indexes
Definition config.h:43
std::int64_t integer
64-bit signed integer type for arithmetic operations
Definition config.h:35
tuple< F_TYPE, S_TYPE > makeTuple(const couple< F_TYPE, S_TYPE > &cp)
constexpr long double E
The mathematical constant E (Euler's number).
Definition maths.h:22
Interface for polymorphic string formatting and output.
Core type system foundations and concept definitions.