ReactivePlusPlus
ReactiveX implementation for C++20
Loading...
Searching...
No Matches
tuple.hpp
1// ReactivePlusPlus library
2//
3// Copyright Aleksey Loginov 2023 - present.
4// Distributed under the Boost Software License, Version 1.0.
5// (See accompanying file LICENSE_1_0.txt or copy at
6// https://www.boost.org/LICENSE_1_0.txt)
7//
8// Project home: https://github.com/victimsnino/ReactivePlusPlus
9//
10
11#pragma once
12
13#include <rpp/defs.hpp>
14#include <rpp/utils/constraints.hpp>
15
16#include <cstddef>
17#include <utility>
18
19namespace rpp::details
20{
21 template<size_t, typename T>
23 {
24 public:
25 tuple_leaf() = default;
26
27 tuple_leaf(const T& value)
28 : m_value{value}
29 {
30 }
31
32 tuple_leaf(T&& value)
33 : m_value{std::move(value)}
34 {
35 }
36
37 const T& get() const { return m_value; }
38
39 T& get() { return m_value; }
40
41 private:
42 RPP_NO_UNIQUE_ADDRESS T m_value{};
43 };
44
45 template<typename, typename...>
47
48 template<typename... Args, size_t... Indices>
49 class RPP_EMPTY_BASES tuple_impl<std::index_sequence<Indices...>, Args...> : private tuple_leaf<Indices, Args>...
50 {
51 public:
52 tuple_impl() = default;
53
54 template<typename... TArgs>
55 requires (!rpp::constraint::variadic_decayed_same_as<tuple_impl<std::index_sequence<Indices...>, Args...>, TArgs...>)
56 tuple_impl(TArgs&&... args)
57 : tuple_leaf<Indices, Args>{std::forward<TArgs>(args)}...
58 {
59 }
60
61 template<typename... TArgs, std::invocable<TArgs&&..., Args&...> Callable>
62 auto apply(Callable&& callable, TArgs&&... args)
63 {
64 return std::forward<Callable>(callable)(std::forward<TArgs>(args)..., static_cast<tuple_leaf<Indices, Args>*>(this)->get()...);
65 }
66
67 template<typename... TArgs, std::invocable<TArgs&&..., Args...> Callable>
68 auto apply(Callable&& callable, TArgs&&... args) const
69 {
70 return std::forward<Callable>(callable)(std::forward<TArgs>(args)..., static_cast<const tuple_leaf<Indices, Args>*>(this)->get()...);
71 }
72
73 template<size_t I>
74 requires (I < sizeof...(Args))
75 const auto& get() const
76 {
77 return static_cast<const tuple_leaf<I, type_at_index_t<I>>*>(this)->get();
78 }
79
80 template<size_t I>
81 requires (I < sizeof...(Args))
82 auto& get()
83 {
84 return static_cast<tuple_leaf<I, type_at_index_t<I>>*>(this)->get();
85 }
86
87 private:
88 template<size_t I, typename T>
89 constexpr static T type_at_index_impl(const tuple_leaf<I, T>*);
90
91 public:
92 template<size_t I>
93 constexpr static auto type_at_index() -> decltype(type_at_index_impl<I>(std::declval<tuple_impl*>()));
94
95 template<size_t I>
96 requires (I < sizeof...(Args))
97 using type_at_index_t = decltype(type_at_index<I>());
98 };
99} // namespace rpp::details
100
101namespace rpp::utils
102{
103 template<typename... Args>
104 class tuple : public rpp::details::tuple_impl<std::index_sequence_for<Args...>, Args...>
105 {
106 public:
107 using rpp::details::tuple_impl<std::index_sequence_for<Args...>, Args...>::tuple_impl;
108 };
109
110 template<typename... Args>
111 tuple(const Args&...) -> tuple<Args...>;
112} // namespace rpp::utils
Definition tuple.hpp:46
Definition tuple.hpp:23
Definition tuple.hpp:105
Definition constraints.hpp:31