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(const T& cur = T{});
79 tupleImpl(tupleImpl&& other) noexcept;
80 tupleImpl(const tupleImpl& other);
81 tupleImpl& operator=(tupleImpl&& other) noexcept;
82
83 template<u_integer I_DIFF>
84 const auto& get() const;
85
86 template<u_integer I_DIFF>
87 auto& get();
88
89 template<u_integer I_DIFF, typename E>
90 void set(const E& e);
91
92 integer compareTo(const tupleImpl& other) const override;
93 std::string toString(bool enter) const override;
94
95 friend class tuple;
96 };
97
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
106 public:
107 explicit tupleImpl(const T& cur = T{}, const TS& next_elems = TS{});
108 tupleImpl(tupleImpl&& other) noexcept;
109 tupleImpl(const tupleImpl& other);
110 tupleImpl& operator=(tupleImpl&& other) noexcept;
111
112 template<u_integer I_DIFF>
113 const auto& get() const;
114
115 template<u_integer I_DIFF>
116 auto& get();
117
118 template<u_integer I_DIFF, typename E>
119 void set(const E& e);
120
121 integer compareTo(const tupleImpl& other) const override;
122 std::string toString(bool enter) const override;
123
124 friend class tuple;
125 };
126
130 template<u_integer I, typename T, typename... TS>
131 class tupleImpl<I, T, TS...> : public printable, public comparable<tupleImpl<I, T, TS...>> {
132 T cur_elem;
133 tupleImpl<I + 1, TS...> next;
134
135 public:
136 explicit tupleImpl(const T& cur, const TS&... next_elems);
137 explicit tupleImpl(const T& cur = T{}, const tupleImpl<I + 1, TS...>& nt = tupleImpl<I + 1, TS...>{});
138 tupleImpl(tupleImpl&& other) noexcept;
139 tupleImpl(const tupleImpl& other);
140 tupleImpl& operator=(tupleImpl&& other) noexcept;
141
142 template<u_integer I_DIFF>
143 const auto& get() const;
144
145 template<u_integer I_DIFF>
146 auto& get();
147
148 template<u_integer I_DIFF, typename E>
149 void set(const E& e);
150
151 integer compareTo(const tupleImpl& other) const override;
152 std::string toString(bool enter) const override;
153
154 friend class tuple;
155 };
156
157 tupleImpl<0, TYPES...> elems;
158
165 template<u_integer... IDX_S, u_integer BEGIN_IDX>
166 auto _slice(std::integer_sequence<u_integer, IDX_S...> indexes,
167 std::integral_constant<u_integer, BEGIN_IDX> begin) const;
168
179 template<typename... O_TYPES, u_integer... T_SIZE, u_integer... O_SIZE>
180 tuple<TYPES..., O_TYPES...> _concat(const tuple<O_TYPES...>& other,
181 std::integer_sequence<u_integer, T_SIZE...> ts,
182 std::integer_sequence<u_integer, O_SIZE...> os) const;
183
184 public:
185 explicit tuple();
186 explicit tuple(const TYPES&... e);
187 tuple(const tuple& other);
188 tuple& operator=(const tuple& other);
189 tuple(tuple&& other) noexcept;
190 tuple& operator=(tuple&& other) noexcept;
191
192 static consteval u_integer size() noexcept;
193
194 template<u_integer IDX>
195 const auto& get() const;
196
197 template<u_integer IDX>
198 auto& get();
199
200 template<u_integer IDX, typename E>
201 tuple& set(const E& e);
202
203 template<u_integer BEGIN_IDX, u_integer N_ELEMS>
204 auto slice() const;
205
206 integer compareTo(const tuple& other) const override;
207 std::string toString(bool enter) const override;
208 std::string className() const override;
209
210 ~tuple() override = default;
211
212 template<typename F_TYPE, typename S_TYPE>
213 friend tuple<F_TYPE, S_TYPE> makeTuple(const couple<F_TYPE, S_TYPE>& cp);
214
215 template<typename... L_TYPES, typename... R_TYPES>
216 friend tuple<L_TYPES..., R_TYPES...> operator+(const tuple<L_TYPES...>& lt, const tuple<R_TYPES...>& rt);
217 };
218
219 template<typename F_TYPE, typename S_TYPE>
221
222 template<typename... L_TYPES, typename... R_TYPES>
223 tuple<L_TYPES..., R_TYPES...> operator+(const tuple<L_TYPES...>& lt, const tuple<R_TYPES...>& rt);
224}
225
226namespace std {
227
232 template<typename... TYPES>
233 struct tuple_size<original::tuple<TYPES...>> //NOLINT
234 : std::integral_constant<std::size_t, sizeof...(TYPES)> {};
235
247 template<std::size_t I, typename... TYPES>
248 struct tuple_element<I, original::tuple<TYPES...>> { //NOLINT
249 using type = std::tuple_element_t<I, std::tuple<TYPES...>>;
250 };
251
260 template<std::size_t I, typename... TYPES>
261 constexpr auto& get(original::tuple<TYPES...>& t) noexcept; //NOLINT
262
271 template<std::size_t I, typename... TYPES>
272 constexpr const auto& get(const original::tuple<TYPES...>& t) noexcept; //NOLINT
273
282 template<std::size_t I, typename... TYPES>
283 constexpr auto&& get(original::tuple<TYPES...>&& t) noexcept; //NOLINT
284}
285
286template<typename... TYPES>
287template<original::u_integer I, typename T>
289 : cur_elem(cur) {}
290
291template<typename... TYPES>
292template<original::u_integer I, typename T>
294 : cur_elem(std::move(other.cur_elem)) {}
295
296template<typename... TYPES>
297template<original::u_integer I, typename T>
299 : cur_elem(other.cur_elem) {}
300
301template<typename... TYPES>
302template<original::u_integer I, typename T>
303auto original::tuple<TYPES...>::tupleImpl<I, T>::operator=(tupleImpl&& other) noexcept -> tupleImpl&
304{
305 if (this == &other)
306 return *this;
307 cur_elem = std::move(other.cur_elem);
308 return *this;
309}
310
311template<typename... TYPES>
312template<original::u_integer I, typename T>
313template<original::u_integer I_DIFF>
315 staticError<outOfBoundError, (I_DIFF > 0)>::asserts();
316
317 return cur_elem;
318}
319
320template<typename... TYPES>
321template<original::u_integer I, typename T>
322template<original::u_integer I_DIFF>
324 staticError<outOfBoundError, (I_DIFF > 0)>::asserts();
325
326 return cur_elem;
327}
328
329template<typename... TYPES>
330template<original::u_integer I, typename T>
331template<original::u_integer I_DIFF, typename E>
333 staticError<outOfBoundError, (I_DIFF > 0)>::asserts();
334 staticError<valueError, !std::is_convertible_v<E, T>>::asserts();
335
336 cur_elem = static_cast<T>(e);
337}
338
339template<typename... TYPES>
340template<original::u_integer I, typename T>
341auto original::tuple<TYPES...>::tupleImpl<I, T>::compareTo(const tupleImpl& other) const -> integer
342{
343 if constexpr (Comparable<T>){
344 if (cur_elem != other.cur_elem)
345 return cur_elem < other.cur_elem ? -1 : 1;
346 }
347 return 0;
348}
349
350template<typename... TYPES>
351template<original::u_integer I, typename T>
352std::string original::tuple<TYPES...>::tupleImpl<I, T>::toString(bool enter) const {
353 std::stringstream ss;
354 if constexpr (I != 0)
355 ss << ", ";
356 ss << formatString(cur_elem);
357 return ss.str();
358}
359
360template<typename... TYPES>
361template<original::u_integer I, typename T, typename TS>
362original::tuple<TYPES...>::tupleImpl<I, T, TS>::tupleImpl(const T& cur, const TS& next_elems)
363 : cur_elem(cur), next(next_elems) {}
364
365template<typename... TYPES>
366template<original::u_integer I, typename T, typename TS>
368 : cur_elem(std::move(other.cur_elem)), next(std::move(other.next)) {}
369
370template<typename... TYPES>
371template<original::u_integer I, typename T, typename TS>
373 : cur_elem(other.cur_elem), next(other.next) {}
374
375template<typename... TYPES>
376template<original::u_integer I, typename T, typename TS>
378 tupleImpl&& other) noexcept -> tupleImpl&
379{
380 if (this == &other)
381 return *this;
382 cur_elem = std::move(other.cur_elem);
383 next = std::move(other.next);
384 return *this;
385}
386
387template<typename... TYPES>
388template<original::u_integer I, typename T, typename TS>
389template<original::u_integer I_DIFF>
391 if constexpr (I_DIFF == 0){
392 return cur_elem;
393 } else{
394 return next.template get<I_DIFF - 1>();
395 }
396}
397
398template<typename... TYPES>
399template<original::u_integer I, typename T, typename TS>
400template<original::u_integer I_DIFF>
402 if constexpr (I_DIFF == 0){
403 return cur_elem;
404 } else{
405 return next.template get<I_DIFF - 1>();
406 }
407}
408
409template<typename... TYPES>
410template<original::u_integer I, typename T, typename TS>
411template<original::u_integer I_DIFF, typename E>
413 if constexpr (I_DIFF == 0){
414 staticError<valueError, !std::is_convertible_v<E, T>>::asserts();
415
416 cur_elem = static_cast<T>(e);
417 } else{
418 next.template set<I_DIFF - 1, E>(e);
419 }
420}
421
422template<typename... TYPES>
423template<original::u_integer I, typename T, typename TS>
425 const tupleImpl& other) const -> integer
426{
427 if constexpr (Comparable<T>){
428 if (cur_elem != other.cur_elem)
429 return cur_elem < other.cur_elem ? -1 : 1;
430 }
431 return next.compareTo(other.next);
432}
433
434template<typename... TYPES>
435template<original::u_integer I, typename T, typename TS>
437 std::stringstream ss;
438 if constexpr (I != 0)
439 ss << ", ";
440 ss << formatString(cur_elem);
441 ss << formatString(next);
442 return ss.str();
443}
444
445template<typename... TYPES>
446template<original::u_integer I, typename T, typename... TS>
447original::tuple<TYPES...>::tupleImpl<I, T, TS...>::tupleImpl(const T& cur, const TS&... next_elems)
448 : cur_elem(cur), next(next_elems...) {}
449
450template<typename... TYPES>
451template<original::u_integer I, typename T, typename... TS>
452original::tuple<TYPES...>::tupleImpl<I, T, TS...>::tupleImpl(const T& cur, const tupleImpl<I + 1, TS...>& nt)
453 : cur_elem(cur), next(nt) {}
454
455template<typename... TYPES>
456template<original::u_integer I, typename T, typename... TS>
458 : cur_elem(std::move(other.cur_elem)), next(std::move(other.next)) {}
459
460template<typename... TYPES>
461template<original::u_integer I, typename T, typename... TS>
463 : cur_elem(other.cur_elem), next(other.next) {}
464
465template<typename... TYPES>
466template<original::u_integer I, typename T, typename... TS>
468 tupleImpl&& other) noexcept -> tupleImpl&
469{
470 if (this == &other)
471 return *this;
472 cur_elem = std::move(other.cur_elem);
473 next = std::move(other.next);
474 return *this;
475}
476
477template<typename... TYPES>
478template<original::u_integer I, typename T, typename... TS>
479template<original::u_integer I_DIFF>
481 if constexpr (I_DIFF == 0){
482 return cur_elem;
483 } else{
484 return next.template get<I_DIFF - 1>();
485 }
486}
487
488template<typename... TYPES>
489template<original::u_integer I, typename T, typename... TS>
490template<original::u_integer I_DIFF>
492 if constexpr (I_DIFF == 0){
493 return cur_elem;
494 } else{
495 return next.template get<I_DIFF - 1>();
496 }
497}
498
499template<typename... TYPES>
500template<original::u_integer I, typename T, typename... TS>
501template<original::u_integer I_DIFF, typename E>
503 if constexpr (I_DIFF == 0){
504 staticError<valueError, !std::is_convertible_v<E, T>>::asserts();
505
506 cur_elem = static_cast<T>(e);
507 } else{
508 next.template set<I_DIFF - 1, E>(e);
509 }
510}
511
512template<typename... TYPES>
513template<original::u_integer I, typename T, typename... TS>
516 if constexpr (Comparable<T>){
517 if (cur_elem != other.cur_elem)
518 return cur_elem < other.cur_elem ? -1 : 1;
519 }
520 return next.compareTo(other.next);
521}
522
523template<typename... TYPES>
524template<original::u_integer I, typename T, typename... TS>
526 std::stringstream ss;
527 if constexpr (I != 0)
528 ss << ", ";
529 ss << formatString(cur_elem);
530 ss << formatString(next);
531 return ss.str();
532}
533
534template<typename... TYPES>
535template<original::u_integer... IDX_S, original::u_integer BEGIN_IDX>
536auto original::tuple<TYPES...>::_slice(std::integer_sequence<u_integer, IDX_S...>,
537 std::integral_constant<u_integer, BEGIN_IDX>) const {
538 return tuple<decltype(this->get<BEGIN_IDX + IDX_S>())...>(this->get<BEGIN_IDX + IDX_S>()...);
539}
540
541template<typename... TYPES>
542template<typename... O_TYPES, original::u_integer... T_SIZE, original::u_integer... O_SIZE>
543original::tuple<TYPES..., O_TYPES...>
544original::tuple<TYPES...>::_concat(const tuple<O_TYPES...> &other,
545 std::integer_sequence<u_integer, T_SIZE...>,
546 std::integer_sequence<u_integer, O_SIZE...>) const {
547 return tuple<TYPES..., O_TYPES...>{this->get<T_SIZE>()..., other.template get<O_SIZE>()...};
548}
549
550template<typename... TYPES>
552
553template<typename... TYPES>
554original::tuple<TYPES...>::tuple(const TYPES&... e) : elems(e...) {}
555
556template<typename... TYPES>
557original::tuple<TYPES...>::tuple(const tuple& other) : elems(other.elems) {}
558
559template<typename... TYPES>
560original::tuple<TYPES...>& original::tuple<TYPES...>::operator=(const tuple& other) {
561 if (this == &other) return *this;
562 this->elems = other.elems;
563 return *this;
564}
565
566template<typename... TYPES>
567original::tuple<TYPES...>::tuple(tuple&& other) noexcept
568 : elems(std::move(other.elems)) {}
569
570template<typename... TYPES>
571original::tuple<TYPES...>& original::tuple<TYPES...>::operator=(tuple&& other) noexcept {
572 if (this == &other) return *this;
573 this->elems = std::move(other.elems);
574 return *this;
575}
576
577template<typename... TYPES>
579 return SIZE;
580}
581
582template<typename... TYPES>
583template<original::u_integer IDX>
584const auto& original::tuple<TYPES...>::get() const {
585 return elems.template get<IDX>();
586}
587
588template<typename... TYPES>
589template<original::u_integer IDX>
591 return elems.template get<IDX>();
592}
593
594template<typename... TYPES>
595template<original::u_integer IDX, typename E>
596original::tuple<TYPES...>& original::tuple<TYPES...>::set(const E &e) {
597 elems.template set<IDX, E>(e);
598 return *this;
599}
600
601template<typename... TYPES>
602template<original::u_integer BEGIN_IDX, original::u_integer N_ELEMS>
604 constexpr bool out_of_bound = BEGIN_IDX >= SIZE || BEGIN_IDX + N_ELEMS > SIZE;
605 staticError<outOfBoundError, out_of_bound>::asserts();
606
607 return this->_slice(
608 std::make_integer_sequence<u_integer, N_ELEMS>{},
609 std::integral_constant<u_integer, BEGIN_IDX>{}
610 );
611}
612
613template<typename... TYPES>
615 return elems.compareTo(other.elems);
616}
617
618template<typename... TYPES>
619std::string original::tuple<TYPES...>::toString(bool enter) const {
620 std::stringstream ss;
621 ss << this->className();
622 ss << "(" << elems << ")";
623 return ss.str();
624}
625
626template<typename... TYPES>
628 return "tuple";
629}
630
631template<typename F_TYPE, typename S_TYPE>
632original::tuple<F_TYPE, S_TYPE> original::makeTuple(const couple<F_TYPE, S_TYPE> &cp) {
633 return original::tuple<F_TYPE, S_TYPE>{cp.template get<0>(), cp.template get<1>()};
634}
635
636template<typename... L_TYPES, typename... R_TYPES>
637original::tuple<L_TYPES..., R_TYPES...>
638original::operator+(const tuple<L_TYPES...> &lt, const tuple<R_TYPES...> &rt) {
639 return lt._concat(rt,
640 std::make_integer_sequence<u_integer, sizeof...(L_TYPES)>{},
641 std::make_integer_sequence<u_integer, sizeof...(R_TYPES)>{});
642}
643
644template<std::size_t I, typename... TYPES>
645constexpr auto& std::get(original::tuple<TYPES...> &t) noexcept { //NOLINT
646 return t.template get<I>();
647}
648
649template<std::size_t I, typename... TYPES>
650constexpr const auto& std::get(const original::tuple<TYPES...> &t) noexcept { //NOLINT
651 return t.template get<I>();
652}
653
654template<std::size_t I, typename... TYPES>
655constexpr auto&& std::get(original::tuple<TYPES...> &&t) noexcept { //NOLINT
656 return std::move(t.template get<I>());
657}
658
659#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: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:619
std::string className() const override
Gets the class name for type identification.
Definition tuple.h:627
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
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.