Loading...
Searching...
No Matches
tuple.h
Go to the documentation of this file.
1#ifndef _BBM_TUPLE_H_
2#define _BBM_TUPLE_H_
3
4#include <tuple>
5#include <ostream>
6
7#include "util/constfor.h"
8#include "util/type_traits.h"
9
10/************************************************************************/
11/*! \file tuple.h
12 \brief Extensions for the STL tuple class
13*************************************************************************/
14
15namespace bbm {
16
17 /*********************************************************************/
18 /*! \brief Create a tuple from any other type that supports std::get
19 *********************************************************************/
20 template<typename T> requires concepts::gettable<T>
21 inline auto to_tuple(T&& t)
22 {
23 auto convert = [&]<size_t... IDX>(std::index_sequence<IDX...>)
24 {
25 return std::make_tuple( std::get<IDX>(std::forward<T>(t))... );
26 };
27
28 return convert(std::make_index_sequence<std::tuple_size_v<std::decay_t<T>>>{});
29 }
30
31 /**********************************************************************/
32 /*! \brief type of converting a type that supports std::get to a tuple
33 **********************************************************************/
34 template<typename T> requires concepts::gettable<T>
35 using to_tuple_t = decltype( to_tuple(std::declval<T>()) );
36
37
38 /*********************************************************************/
39 /*! \brief Make a tuple of references.
40
41 Returns std::tuple<ARGS...>, and therefore this method differs from:
42 + std::make_tuple which returns a std::tuple<std::decay_t<ARGS>...>
43 + std::forward_as_tuple which returns a std::tuple<ARGS&&...>
44 *********************************************************************/
45 template<typename... ARGS>
46 inline constexpr auto make_ref_tuple(ARGS&&... args)
47 {
48 return std::tuple< ARGS... >( std::forward<ARGS>(args)... );
49 }
50
51 /**********************************************************************/
52 /*! \brief Value-copy a tuple.
53
54 \param tup = tuple, possibly with references
55 \returns a copy of the tuple without references.
56
57 For example std::tuple<int&, int> will be converted to std::tuple<int, int>
58
59 ***********************************************************************/
60 template<typename... ARGS>
61 inline constexpr auto value_copy_tuple(const std::tuple<ARGS...>& tup)
62 {
63 auto deref = [&]<size_t... IDX>(std::index_sequence<IDX...>)
64 {
65 return std::make_tuple( std::remove_cvref_t<ARGS>( std::get<IDX>(tup) )... );
66 };
67
68 return deref(std::make_index_sequence<sizeof...(ARGS)>{});
69 }
70
71 //! \brief value-copy type of a tuple.
72 template<typename T> requires is_tuple_v<T>
73 using value_copy_tuple_t = decltype( value_copy_tuple( std::declval<std::decay_t<T>>() ) );
74
75 /**********************************************************************/
76 /*! \brief tuple_cat_t
77
78 Returns the type of std::tuple_cat
79 ***********************************************************************/
80 template<typename... Ts>
81 using tuple_cat_t = decltype( std::tuple_cat( std::declval<Ts>()... ) );
82
83
84 /**********************************************************************/
85 /*! \brief subtuple
86
87 \tparam START = start index of elements to include in the new tuple
88 \tparam COUNT = number of elements to include
89 ***********************************************************************/
90 template<size_t START, size_t COUNT, typename TUP> requires is_tuple_v<TUP> && ((START+COUNT) <= std::tuple_size_v<std::decay_t<TUP>>)
91 inline constexpr auto subtuple(TUP&& tup)
92 {
93 // if zero length => return empty
94 if constexpr (COUNT == 0) return std::tuple<>{};
95
96 // select subset
97 else
98 {
99 // helper lambda to extract the elements
100 auto extract = [&]<size_t... IDX>(std::index_sequence<IDX...>)
101 {
102 return std::tuple<std::tuple_element_t<START+IDX, std::decay_t<TUP>>...>(std::get<START+IDX>(std::forward<TUP>(tup))...);
103 };
104
105 return extract(std::make_index_sequence<COUNT>{});
106 }
107 }
108
109 /**********************************************************************/
110 /*! \brief subtuple type
111 **********************************************************************/
112 template<size_t START, size_t COUNT, typename TUP> requires is_tuple_v<TUP> && ((START+COUNT) <= std::tuple_size_v<std::decay_t<TUP>>)
113 using subtuple_t = decltype( subtuple<START,COUNT>(std::declval<TUP>()) );
114
115
116 /**********************************************************************/
117 /*! \brief Recursively flatten a tuple
118
119 The resulting tuple is the concatenation of all elements of child tuples.
120 ***********************************************************************/
121 template<typename T>
122 inline constexpr auto tuple_flatten(T&& t)
123 {
124 // base case: not a tuple
125 if constexpr (!is_tuple_v<std::decay_t<T>>) { return std::forward_as_tuple(t); }
126
127 // recursion: cat elements
128 else
129 {
130 auto flatten = [&]<size_t... IDX>(std::index_sequence<IDX...>)
131 {
132 return std::tuple_cat( (tuple_flatten( std::get<IDX>(std::forward<T>(t)) ))... );
133 };
134
135 return flatten(std::make_index_sequence<std::tuple_size_v<std::decay_t<T>>>{});
136 }
137
138 // Done.
139 }
140
141 //! \brief flattened tuple type
142 template<typename T>
143 using tuple_flatten_t = decltype( tuple_flatten( std::declval<std::decay_t<T>>() ) );
144
145
146 /**********************************************************************/
147 /*! \brief tuple_add_const to each element
148 **********************************************************************/
149 template<typename T>
150 inline constexpr auto tuple_add_const(T&& t)
151 {
152 auto add_const = [&]<size_t... IDX>(std::index_sequence<IDX...>)
153 {
154 return std::tuple< bbm::add_const_t<std::tuple_element_t<IDX, std::decay_t<T>>>... >( std::get<IDX>(std::forward<T>(t))... );
155 };
156
157 return add_const(std::make_index_sequence<std::tuple_size_v<std::decay_t<T>>>{});
158 }
159
160 //! \brief tuple_add_const type
161 template<typename T>
162 using tuple_add_const_t = decltype( tuple_add_const( std::declval<std::decay_t<T>>() ) );
163
164 /**********************************************************************/
165 /*! \brief tuple_remove_const from each element
166 **********************************************************************/
167 template<typename T>
168 inline constexpr auto tuple_remove_const(T&& t)
169 {
170 auto cast = []<typename V>(V&& val) -> decltype(auto)
171 {
172 if constexpr (std::is_pointer_v<V> || std::is_reference_v<V>) return const_cast<bbm::remove_const_t<V>>(std::forward<V>(val));
173 else return std::forward<V>(val);
174 };
175
176 auto remove_const = [&]<size_t... IDX>(std::index_sequence<IDX...>)
177 {
178 return std::tuple< bbm::remove_const_t<std::tuple_element_t<IDX, std::decay_t<T>>>... >( cast(std::get<IDX>(std::forward<T>(t)))... );
179 };
180
181 return remove_const(std::make_index_sequence<std::tuple_size_v<std::decay_t<T>>>{});
182 }
183
184 //! \brief tuple_remove_const type
185 template<typename T>
186 using tuple_remove_const_t = decltype( tuple_remove_const( std::declval<std::decay_t<T>>() ) );
187
188
189} // end bbm namespace
190
191
192namespace std {
193 /**********************************************************************/
194 /*! \brief print a tuple
195
196 The tuple elements are surrounded by '(' and ')'. Each tuple element is
197 converted to a string with bbm::toString. String types are additionally
198 surrounded by ""
199 ***********************************************************************/
200 template<typename... Ts>
201 std::ostream& operator<<(std::ostream& s, const std::tuple<Ts...>& tup)
202 {
203 s << "(";
204 CONSTFOR(idx, sizeof...(Ts),
205 {
206 if constexpr (idx != 0) s << ", ";
207
208 // add "" if a string type
209 if constexpr (bbm::is_string_type_v< std::tuple_element_t<idx, std::tuple<Ts...>> >) s << std::string("\"") + std::get<idx>(tup) + std::string("\"");
210
211 // otherwise, just print value
212 else s << std::get<idx>(tup);
213 });
214 s << ")";
215
216 return s;
217 }
218
219} // end std namespace
220
221#endif /* _BBM_TUPLE_H_ */
Complile-time for loop.
#define CONSTFOR(IDX, NUMITR,...)
HELPER MACRO.
Definition: constfor.h:63
Definition: aggregatebsdf.h:29
constexpr auto tuple_remove_const(T &&t)
tuple_remove_const from each element
Definition: tuple.h:168
decltype(subtuple< START, COUNT >(std::declval< TUP >())) subtuple_t
subtuple type
Definition: tuple.h:113
decltype(tuple_add_const(std::declval< std::decay_t< T > >())) tuple_add_const_t
tuple_add_const type
Definition: tuple.h:162
constexpr auto tuple_flatten(T &&t)
Recursively flatten a tuple.
Definition: tuple.h:122
constexpr auto make_ref_tuple(ARGS &&... args)
Make a tuple of references.
Definition: tuple.h:46
decltype(tuple_remove_const(std::declval< std::decay_t< T > >())) tuple_remove_const_t
tuple_remove_const type
Definition: tuple.h:186
typename remove_const< T >::type remove_const_t
Definition: type_traits.h:60
decltype(value_copy_tuple(std::declval< std::decay_t< T > >())) value_copy_tuple_t
value-copy type of a tuple.
Definition: tuple.h:73
constexpr auto tuple_add_const(T &&t)
tuple_add_const to each element
Definition: tuple.h:150
constexpr bool is_string_type_v
Definition: type_traits.h:105
constexpr auto subtuple(TUP &&tup)
subtuple
Definition: tuple.h:91
decltype(to_tuple(std::declval< T >())) to_tuple_t
type of converting a type that supports std::get to a tuple
Definition: tuple.h:35
auto to_tuple(T &&t)
Create a tuple from any other type that supports std::get.
Definition: tuple.h:21
constexpr auto value_copy_tuple(const std::tuple< ARGS... > &tup)
Value-copy a tuple.
Definition: tuple.h:61
decltype(std::tuple_cat(std::declval< Ts >()...)) tuple_cat_t
tuple_cat_t
Definition: tuple.h:81
decltype(tuple_flatten(std::declval< std::decay_t< T > >())) tuple_flatten_t
flattened tuple type
Definition: tuple.h:143
Definition: type_traits.h:30
Definition: type_traits.h:48
Definition: named.h:325
std::ostream & operator<<(std::ostream &s, const std::tuple< Ts... > &tup)
print a tuple
Definition: tuple.h:201
Forward declaration.
Definition: args.h:248