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
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
73 template<u_integer I, typename T>
74 class tupleImpl<I, T> : public printable, public comparable<tupleImpl<I, T>> {
75 T cur_elem;
76
77 public:
78 explicit tupleImpl() = default;
79 explicit tupleImpl(T&& cur);
80 tupleImpl(tupleImpl&& other) noexcept;
81 tupleImpl(const tupleImpl& other);
82 tupleImpl& operator=(tupleImpl&& other) noexcept;
83
84 template<u_integer I_DIFF>
85 const auto& get() const;
86
87 template<u_integer I_DIFF>
88 auto& get();
89
90 template<u_integer I_DIFF, typename E>
91 void set(const E& e);
92
93 integer compareTo(const tupleImpl& other) const override;
94 std::string toString(bool enter) const override;
95
96 friend class tuple;
97 };
98
102 template<u_integer I, typename T, typename TS>
103 class tupleImpl<I, T, TS> : public printable, public comparable<tupleImpl<I, T, TS>> {
104 T cur_elem;
105 tupleImpl<I + 1, TS> next;
106
107 public:
108 tupleImpl() = default;
109 explicit tupleImpl(T&& cur, TS&& next_elems);
110 tupleImpl(tupleImpl&& other) noexcept;
111 tupleImpl(const tupleImpl& other);
112 tupleImpl& operator=(tupleImpl&& other) noexcept;
113
114 template<u_integer I_DIFF>
115 const auto& get() const;
116
117 template<u_integer I_DIFF>
118 auto& get();
119
120 template<u_integer I_DIFF, typename E>
121 void set(const E& e);
122
123 integer compareTo(const tupleImpl& other) const override;
124 std::string toString(bool enter) const override;
125
126 friend class tuple;
127 };
128
132 template<u_integer I, typename T, typename... TS>
133 class tupleImpl<I, T, TS...> : public printable, public comparable<tupleImpl<I, T, TS...>> {
134 T cur_elem;
135 tupleImpl<I + 1, TS...> next;
136
137 public:
138 explicit tupleImpl(T&& cur, TS&&... next_elems);
139 explicit tupleImpl(const T& cur = T{}, const tupleImpl<I + 1, TS...>& nt = tupleImpl<I + 1, TS...>{});
140 tupleImpl(tupleImpl&& other) noexcept;
141 tupleImpl(const tupleImpl& other);
142 tupleImpl& operator=(tupleImpl&& other) noexcept;
143
144 template<u_integer I_DIFF>
145 const auto& get() const;
146
147 template<u_integer I_DIFF>
148 auto& get();
149
150 template<u_integer I_DIFF, typename E>
151 void set(const E& e);
152
153 integer compareTo(const tupleImpl& other) const override;
154 std::string toString(bool enter) const override;
155
156 friend class tuple;
157 };
158
159 tupleImpl<0, TYPES...> elems;
160
167 template<u_integer... IDX_S, u_integer BEGIN_IDX>
168 auto _slice(std::integer_sequence<u_integer, IDX_S...> indexes,
169 std::integral_constant<u_integer, BEGIN_IDX> begin) const;
170
171 template<typename... O_TYPES, u_integer... T_SIZE, u_integer... O_SIZE>
172 tuple<TYPES..., O_TYPES...> _concat(const tuple<O_TYPES...>& other,
173 std::integer_sequence<u_integer, T_SIZE...> ts,
174 std::integer_sequence<u_integer, O_SIZE...> os) const;
175
186 template<typename... O_TYPES, u_integer... T_SIZE, u_integer... O_SIZE>
187 tuple<TYPES..., O_TYPES...> _concat(tuple<O_TYPES...>&& other,
188 std::integer_sequence<u_integer, T_SIZE...> ts,
189 std::integer_sequence<u_integer, O_SIZE...> os) const;
190
191 public:
192 tuple() = default;
193 explicit tuple(TYPES&&... e);
194 tuple(const tuple& other);
195 tuple& operator=(const tuple& other);
196 tuple(tuple&& other) noexcept;
197 tuple& operator=(tuple&& other) noexcept;
198
199 static consteval u_integer size() noexcept;
200
201 template<u_integer IDX>
202 const auto& get() const;
203
204 template<u_integer IDX>
205 auto& get();
206
207 template<u_integer IDX, typename E>
208 tuple& set(const E& e);
209
210 template<u_integer BEGIN_IDX, u_integer N_ELEMS>
211 auto slice() const;
212
213 integer compareTo(const tuple& other) const override;
214 std::string toString(bool enter) const override;
215 std::string className() const override;
216
217 ~tuple() override = default;
218
219 template<typename F_TYPE, typename S_TYPE>
220 friend tuple<F_TYPE, S_TYPE> makeTuple(const couple<F_TYPE, S_TYPE>& cp);
221
222 template<typename F_TYPE, typename S_TYPE>
223 friend tuple<F_TYPE, S_TYPE> makeTuple(couple<F_TYPE, S_TYPE>&& cp);
224
225 template<typename... L_TYPES, typename... R_TYPES>
226 friend tuple<L_TYPES..., R_TYPES...> operator+(const tuple<L_TYPES...>& lt, const tuple<R_TYPES...>& rt);
227
228 template<typename... L_TYPES, typename... R_TYPES>
229 friend tuple<L_TYPES..., R_TYPES...> operator+(tuple<L_TYPES...>&& lt, const tuple<R_TYPES...>&& rt);
230
231 template<typename... L_TYPES, typename... R_TYPES>
232 friend tuple<L_TYPES..., R_TYPES...> operator+(tuple<L_TYPES...>&& lt, const tuple<R_TYPES...>& rt);
233
234 template<typename... L_TYPES, typename... R_TYPES>
235 friend tuple<L_TYPES..., R_TYPES...> operator+(const tuple<L_TYPES...>& lt, tuple<R_TYPES...>&& rt);
236 };
237
238 template<typename F_TYPE, typename S_TYPE>
240
241 template<typename F_TYPE, typename S_TYPE>
243
244 template<typename... L_TYPES, typename... R_TYPES>
245 tuple<L_TYPES..., R_TYPES...> operator+(const tuple<L_TYPES...>& lt, const tuple<R_TYPES...>& rt);
246
247 template<typename... L_TYPES, typename... R_TYPES>
248 tuple<L_TYPES..., R_TYPES...> operator+(tuple<L_TYPES...>&& lt, const tuple<R_TYPES...>&& rt);
249
250 template<typename... L_TYPES, typename... R_TYPES>
251 tuple<L_TYPES..., R_TYPES...> operator+(tuple<L_TYPES...>&& lt, const tuple<R_TYPES...>& rt);
252
253 template<typename... L_TYPES, typename... R_TYPES>
254 tuple<L_TYPES..., R_TYPES...> operator+(const tuple<L_TYPES...>& lt, tuple<R_TYPES...>&& rt);
255}
256
257namespace std {
258
263 template<typename... TYPES>
264 struct tuple_size<original::tuple<TYPES...>> //NOLINT
265 : std::integral_constant<std::size_t, sizeof...(TYPES)> {};
266
278 template<std::size_t I, typename... TYPES>
279 struct tuple_element<I, original::tuple<TYPES...>> { //NOLINT
280 using type = std::tuple_element_t<I, std::tuple<TYPES...>>;
281 };
282
291 template<std::size_t I, typename... TYPES>
292 constexpr auto& get(original::tuple<TYPES...>& t) noexcept; //NOLINT
293
302 template<std::size_t I, typename... TYPES>
303 constexpr const auto& get(const original::tuple<TYPES...>& t) noexcept; //NOLINT
304
313 template<std::size_t I, typename... TYPES>
314 constexpr auto&& get(original::tuple<TYPES...>&& t) noexcept; //NOLINT
315}
316
317template <typename ... TYPES>
318template <original::u_integer I, typename T>
320 : cur_elem(std::forward<T>(cur)) {}
321
322template<typename... TYPES>
323template<original::u_integer I, typename T>
325 : cur_elem(std::move(other.cur_elem)) {}
326
327template<typename... TYPES>
328template<original::u_integer I, typename T>
330 : cur_elem(other.cur_elem) {}
331
332template<typename... TYPES>
333template<original::u_integer I, typename T>
334auto original::tuple<TYPES...>::tupleImpl<I, T>::operator=(tupleImpl&& other) noexcept -> tupleImpl&
335{
336 if (this == &other)
337 return *this;
338 cur_elem = std::move(other.cur_elem);
339 return *this;
340}
341
342template<typename... TYPES>
343template<original::u_integer I, typename T>
344template<original::u_integer I_DIFF>
346 staticError<outOfBoundError, (I_DIFF > 0)>::asserts();
347
348 return cur_elem;
349}
350
351template<typename... TYPES>
352template<original::u_integer I, typename T>
353template<original::u_integer I_DIFF>
355 staticError<outOfBoundError, (I_DIFF > 0)>::asserts();
356
357 return cur_elem;
358}
359
360template<typename... TYPES>
361template<original::u_integer I, typename T>
362template<original::u_integer I_DIFF, typename E>
364 staticError<outOfBoundError, (I_DIFF > 0)>::asserts();
365 staticError<valueError, !std::is_convertible_v<E, T>>::asserts();
366
367 cur_elem = static_cast<T>(e);
368}
369
370template<typename... TYPES>
371template<original::u_integer I, typename T>
372auto original::tuple<TYPES...>::tupleImpl<I, T>::compareTo(const tupleImpl& other) const -> integer
373{
374 if constexpr (Comparable<T>){
375 if (cur_elem != other.cur_elem)
376 return cur_elem < other.cur_elem ? -1 : 1;
377 }
378 return 0;
379}
380
381template<typename... TYPES>
382template<original::u_integer I, typename T>
383std::string original::tuple<TYPES...>::tupleImpl<I, T>::toString(bool enter) const {
384 std::stringstream ss;
385 if constexpr (I != 0)
386 ss << ", ";
387 ss << formatString(cur_elem);
388 return ss.str();
389}
390
391template <typename ... TYPES>
392template <original::u_integer I, typename T, typename TS>
394 : cur_elem(std::forward<T>(cur)), next(std::forward<TS>(next_elems)) {}
395
396template<typename... TYPES>
397template<original::u_integer I, typename T, typename TS>
399 : cur_elem(std::move(other.cur_elem)), next(std::move(other.next)) {}
400
401template<typename... TYPES>
402template<original::u_integer I, typename T, typename TS>
404 : cur_elem(other.cur_elem), next(other.next) {}
405
406template<typename... TYPES>
407template<original::u_integer I, typename T, typename TS>
409 tupleImpl&& other) noexcept -> tupleImpl&
410{
411 if (this == &other)
412 return *this;
413 cur_elem = std::move(other.cur_elem);
414 next = std::move(other.next);
415 return *this;
416}
417
418template<typename... TYPES>
419template<original::u_integer I, typename T, typename TS>
420template<original::u_integer I_DIFF>
422 if constexpr (I_DIFF == 0){
423 return cur_elem;
424 } else{
425 return next.template get<I_DIFF - 1>();
426 }
427}
428
429template<typename... TYPES>
430template<original::u_integer I, typename T, typename TS>
431template<original::u_integer I_DIFF>
433 if constexpr (I_DIFF == 0){
434 return cur_elem;
435 } else{
436 return next.template get<I_DIFF - 1>();
437 }
438}
439
440template<typename... TYPES>
441template<original::u_integer I, typename T, typename TS>
442template<original::u_integer I_DIFF, typename E>
444 if constexpr (I_DIFF == 0){
445 staticError<valueError, !std::is_convertible_v<E, T>>::asserts();
446
447 cur_elem = static_cast<T>(e);
448 } else{
449 next.template set<I_DIFF - 1, E>(e);
450 }
451}
452
453template<typename... TYPES>
454template<original::u_integer I, typename T, typename TS>
456 const tupleImpl& other) const -> integer
457{
458 if constexpr (Comparable<T>){
459 if (cur_elem != other.cur_elem)
460 return cur_elem < other.cur_elem ? -1 : 1;
461 }
462 return next.compareTo(other.next);
463}
464
465template<typename... TYPES>
466template<original::u_integer I, typename T, typename TS>
468 std::stringstream ss;
469 if constexpr (I != 0)
470 ss << ", ";
471 ss << formatString(cur_elem);
472 ss << formatString(next);
473 return ss.str();
474}
475
476template <typename ... TYPES>
477template <original::u_integer I, typename T, typename ... TS>
479 : cur_elem(std::forward<T>(cur)), next(std::forward<TS>(next_elems)...) {}
480
481template<typename... TYPES>
482template<original::u_integer I, typename T, typename... TS>
483original::tuple<TYPES...>::tupleImpl<I, T, TS...>::tupleImpl(const T& cur, const tupleImpl<I + 1, TS...>& nt)
484 : cur_elem(cur), next(nt) {}
485
486template<typename... TYPES>
487template<original::u_integer I, typename T, typename... TS>
489 : cur_elem(std::move(other.cur_elem)), next(std::move(other.next)) {}
490
491template<typename... TYPES>
492template<original::u_integer I, typename T, typename... TS>
494 : cur_elem(other.cur_elem), next(other.next) {}
495
496template<typename... TYPES>
497template<original::u_integer I, typename T, typename... TS>
499 tupleImpl&& other) noexcept -> tupleImpl&
500{
501 if (this == &other)
502 return *this;
503 cur_elem = std::move(other.cur_elem);
504 next = std::move(other.next);
505 return *this;
506}
507
508template<typename... TYPES>
509template<original::u_integer I, typename T, typename... TS>
510template<original::u_integer I_DIFF>
512 if constexpr (I_DIFF == 0){
513 return cur_elem;
514 } else{
515 return next.template get<I_DIFF - 1>();
516 }
517}
518
519template<typename... TYPES>
520template<original::u_integer I, typename T, typename... TS>
521template<original::u_integer I_DIFF>
523 if constexpr (I_DIFF == 0){
524 return cur_elem;
525 } else{
526 return next.template get<I_DIFF - 1>();
527 }
528}
529
530template<typename... TYPES>
531template<original::u_integer I, typename T, typename... TS>
532template<original::u_integer I_DIFF, typename E>
534 if constexpr (I_DIFF == 0){
535 staticError<valueError, !std::is_convertible_v<E, T>>::asserts();
536
537 cur_elem = static_cast<T>(e);
538 } else{
539 next.template set<I_DIFF - 1, E>(e);
540 }
541}
542
543template<typename... TYPES>
544template<original::u_integer I, typename T, typename... TS>
547 if constexpr (Comparable<T>){
548 if (cur_elem != other.cur_elem)
549 return cur_elem < other.cur_elem ? -1 : 1;
550 }
551 return next.compareTo(other.next);
552}
553
554template<typename... TYPES>
555template<original::u_integer I, typename T, typename... TS>
557 std::stringstream ss;
558 if constexpr (I != 0)
559 ss << ", ";
560 ss << formatString(cur_elem);
561 ss << formatString(next);
562 return ss.str();
563}
564
565template<typename... TYPES>
566template<original::u_integer... IDX_S, original::u_integer BEGIN_IDX>
567auto original::tuple<TYPES...>::_slice(std::integer_sequence<u_integer, IDX_S...>,
568 std::integral_constant<u_integer, BEGIN_IDX>) const {
569 return tuple<decltype(this->get<BEGIN_IDX + IDX_S>())...>(this->get<BEGIN_IDX + IDX_S>()...);
570}
571
572template<typename... TYPES>
573template<typename... O_TYPES, original::u_integer... T_SIZE, original::u_integer... O_SIZE>
574original::tuple<TYPES..., O_TYPES...>
575original::tuple<TYPES...>::_concat(const tuple<O_TYPES...> &other,
576 std::integer_sequence<u_integer, T_SIZE...>,
577 std::integer_sequence<u_integer, O_SIZE...>) const {
578 return tuple<TYPES..., O_TYPES...>{TYPES(this->get<T_SIZE>())..., O_TYPES(other.template get<O_SIZE>())...};
579}
580
581template<typename... TYPES>
582template<typename... O_TYPES, original::u_integer... T_SIZE, original::u_integer... O_SIZE>
583original::tuple<TYPES..., O_TYPES...>
584original::tuple<TYPES...>::_concat(tuple<O_TYPES...> &&other,
585 std::integer_sequence<u_integer, T_SIZE...>,
586 std::integer_sequence<u_integer, O_SIZE...>) const {
587 return tuple<TYPES..., O_TYPES...>{
588 std::forward<decltype(this->get<T_SIZE>())>(this->get<T_SIZE>())...,
589 std::forward<decltype(other.template get<O_SIZE>())>(other.template get<O_SIZE>())...
590 };
591}
592
593template <typename ... TYPES>
595 : elems(std::forward<TYPES>(e)...) {}
596
597template<typename... TYPES>
598original::tuple<TYPES...>::tuple(const tuple& other) : elems(other.elems) {}
599
600template<typename... TYPES>
601original::tuple<TYPES...>& original::tuple<TYPES...>::operator=(const tuple& other) {
602 if (this == &other) return *this;
603 this->elems = other.elems;
604 return *this;
605}
606
607template<typename... TYPES>
608original::tuple<TYPES...>::tuple(tuple&& other) noexcept
609 : elems(std::move(other.elems)) {}
610
611template<typename... TYPES>
612original::tuple<TYPES...>& original::tuple<TYPES...>::operator=(tuple&& other) noexcept {
613 if (this == &other) return *this;
614 this->elems = std::move(other.elems);
615 return *this;
616}
617
618template<typename... TYPES>
620 return SIZE;
621}
622
623template<typename... TYPES>
624template<original::u_integer IDX>
625const auto& original::tuple<TYPES...>::get() const {
626 return elems.template get<IDX>();
627}
628
629template<typename... TYPES>
630template<original::u_integer IDX>
632 return elems.template get<IDX>();
633}
634
635template<typename... TYPES>
636template<original::u_integer IDX, typename E>
637original::tuple<TYPES...>& original::tuple<TYPES...>::set(const E &e) {
638 elems.template set<IDX, E>(e);
639 return *this;
640}
641
642template<typename... TYPES>
643template<original::u_integer BEGIN_IDX, original::u_integer N_ELEMS>
645 constexpr bool out_of_bound = BEGIN_IDX >= SIZE || BEGIN_IDX + N_ELEMS > SIZE;
646 staticError<outOfBoundError, out_of_bound>::asserts();
647
648 return this->_slice(
649 std::make_integer_sequence<u_integer, N_ELEMS>{},
650 std::integral_constant<u_integer, BEGIN_IDX>{}
651 );
652}
653
654template<typename... TYPES>
656 return elems.compareTo(other.elems);
657}
658
659template<typename... TYPES>
660std::string original::tuple<TYPES...>::toString(bool enter) const {
661 std::stringstream ss;
662 ss << this->className();
663 ss << "(" << elems << ")";
664 return ss.str();
665}
666
667template<typename... TYPES>
669 return "tuple";
670}
671
672template<typename F_TYPE, typename S_TYPE>
673original::tuple<F_TYPE, S_TYPE> original::makeTuple(const couple<F_TYPE, S_TYPE> &cp) {
675 F_TYPE(cp.template get<0>()),
676 S_TYPE(cp.template get<1>())
677 };
678}
679
680template<typename... L_TYPES, typename... R_TYPES>
681original::tuple<L_TYPES..., R_TYPES...>
682original::operator+(const tuple<L_TYPES...> &lt, const tuple<R_TYPES...> &rt) {
683 return lt._concat(rt,
684 std::make_integer_sequence<u_integer, sizeof...(L_TYPES)>{},
685 std::make_integer_sequence<u_integer, sizeof...(R_TYPES)>{});
686}
687
688template<typename... L_TYPES, typename... R_TYPES>
689original::tuple<L_TYPES..., R_TYPES...>
690original::operator+(tuple<L_TYPES...>&& lt, const tuple<R_TYPES...>&& rt) {
691 return std::move(lt)._concat(std::move(rt),
692 std::make_integer_sequence<u_integer, sizeof...(L_TYPES)>{},
693 std::make_integer_sequence<u_integer, sizeof...(R_TYPES)>{});
694}
695
696template<typename... L_TYPES, typename... R_TYPES>
697original::tuple<L_TYPES..., R_TYPES...>
698original::operator+(tuple<L_TYPES...>&& lt, const tuple<R_TYPES...>& rt) {
699 return std::move(lt)._concat(std::move(rt),
700 std::make_integer_sequence<u_integer, sizeof...(L_TYPES)>{},
701 std::make_integer_sequence<u_integer, sizeof...(R_TYPES)>{});
702}
703
704template<typename... L_TYPES, typename... R_TYPES>
705original::tuple<L_TYPES..., R_TYPES...>
706original::operator+(const tuple<L_TYPES...>& lt, tuple<R_TYPES...>&& rt) {
707 return lt._concat(std::move(rt),
708 std::make_integer_sequence<u_integer, sizeof...(L_TYPES)>{},
709 std::make_integer_sequence<u_integer, sizeof...(R_TYPES)>{});
710}
711
712template <typename F_TYPE, typename S_TYPE>
713original::tuple<F_TYPE, S_TYPE> original::makeTuple(couple<F_TYPE, S_TYPE>&& cp)
714{
716 std::move(cp).template get<0>(),
717 std::move(cp).template get<1>()
718 };
719}
720
721template<std::size_t I, typename... TYPES>
722constexpr auto& std::get(original::tuple<TYPES...> &t) noexcept { //NOLINT
723 return t.template get<I>();
724}
725
726template<std::size_t I, typename... TYPES>
727constexpr const auto& std::get(const original::tuple<TYPES...> &t) noexcept { //NOLINT
728 return t.template get<I>();
729}
730
731template<std::size_t I, typename... TYPES>
732constexpr auto&& std::get(original::tuple<TYPES...> &&t) noexcept { //NOLINT
733 return std::move(t.template get<I>());
734}
735
736#endif //TUPLE_H
Base class for comparable objects.
Definition comparable.h:32
Container for two heterogeneous elements.
Definition couple.h:37
Base class providing polymorphic string conversion capabilities.
Definition printable.h:39
Abstract base class for unique element containers.
Definition set.h:44
Container for multiple heterogeneous elements.
Definition tuple.h:53
std::string toString(bool enter) const override
Generates formatted string representation.
Definition tuple.h:660
std::string className() const override
Gets the class name for type identification.
Definition tuple.h:668
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:370
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
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.
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.