├── README.md ├── demo.cpp └── tuple_utility.hpp /README.md: -------------------------------------------------------------------------------- 1 | tuple_utility 2 | ============= 3 | 4 | Utilities for C++ tuples. 5 | 6 | `tuple_map`: 7 | 8 | #include "tuple_utility.hpp" 9 | 10 | int main() 11 | { 12 | auto t = std::make_tuple(0, 1, 2, 3); 13 | 14 | auto negative_t = tuple_map([](int x) 15 | { 16 | return -x; 17 | }, t); 18 | 19 | std::cout << "negative_t: "; 20 | tuple_print(negative_t); 21 | std::cout << std::endl; 22 | 23 | // prints 0, -1, -2, -3 24 | 25 | return 0; 26 | } 27 | 28 | `std::array`s are tuples too: 29 | 30 | #include "tuple_utility.hpp" 31 | #include 32 | 33 | int main() 34 | { 35 | std::array t = {0, 1, 2, 3}; 36 | 37 | auto negative_t = tuple_map([](int x) 38 | { 39 | return -x; 40 | }, t); 41 | 42 | std::cout << "negative_t: "; 43 | tuple_print(negative_t); 44 | std::cout << std::endl; 45 | 46 | // prints 0, -1, -2, -3 47 | 48 | return 0; 49 | } 50 | 51 | As is any type which specializes `tuple_traits`: 52 | 53 | #include "tuple_utility.hpp" 54 | #include 55 | 56 | struct my_float3 57 | { 58 | float x, y, z; 59 | }; 60 | 61 | template<> 62 | struct tuple_traits 63 | { 64 | using tuple_type = my_float3; 65 | 66 | static const size_t size = 3; 67 | 68 | template 69 | using element_type = float; 70 | 71 | template 72 | static float& get(tuple_type& t) 73 | { 74 | static_assert(i < size, "i must be < size"); 75 | return &t.x + i; 76 | } 77 | 78 | template 79 | static const float& get(const tuple_type& t) 80 | { 81 | static_assert(i < size, "i must be < size"); 82 | return &t.x + i; 83 | } 84 | 85 | template 86 | static float&& get(tuple_type&& t) 87 | { 88 | static_assert(i < size, "i must be < size"); 89 | return std::move(&t.x + i); 90 | } 91 | }; 92 | 93 | int main() 94 | { 95 | my_float3 t = {0.f, 1.f, 2.f}; 96 | 97 | auto negative_t = tuple_map([](float x) 98 | { 99 | return -x; 100 | }, t); 101 | 102 | std::cout << "negative_t: "; 103 | tuple_print(negative_t); 104 | std::cout << std::endl; 105 | 106 | // prints 0, -1, -2 107 | 108 | return 0; 109 | } 110 | 111 | `tuple_map` is variadic: 112 | 113 | #include "tuple_utility.hpp" 114 | 115 | int main() 116 | { 117 | auto t = std::make_tuple(0, 1, 2, 3); 118 | 119 | auto negative_t = tuple_map([](int x) 120 | { 121 | return -x; 122 | }, t); 123 | 124 | auto zero_t = tuple_map([](int x, int y) 125 | { 126 | return x + y; 127 | }, t, negative_t); 128 | 129 | std::cout << "zero_t: "; 130 | tuple_print(zero_t); 131 | std::cout << std::endl; 132 | 133 | // prints 0, 0, 0, 0 134 | 135 | return 0; 136 | } 137 | 138 | 139 | `tuple_head` & `tuple_tail`: 140 | 141 | #include "tuple_utility.hpp" 142 | 143 | int main() 144 | { 145 | auto t = std::make_tuple(0, 1, 2, 3); 146 | 147 | std::cout << "t's head is " << tuple_head(t) << std::endl; 148 | 149 | // prints 0 150 | 151 | auto t_tail = tuple_tail(t); 152 | std::cout << "t's tail is "; 153 | tuple_print(t_tail); 154 | std::cout << std::endl; 155 | 156 | // prints 1, 2, 3 157 | 158 | return 0; 159 | } 160 | 161 | `tuple_take` & `tuple_drop`: 162 | 163 | #include "tuple_utility.hpp" 164 | 165 | int main() 166 | { 167 | auto t = std::make_tuple(0, 1, 2, 3); 168 | 169 | auto t_take_2 = tuple_take<2>(t); 170 | 171 | std::cout << "t_take_2 is "; 172 | tuple_print(t_take_2); 173 | std::cout << std::endl; 174 | 175 | // prints 0, 1 176 | 177 | auto t_drop_2 = tuple_drop<2>(t); 178 | 179 | std::cout << "t_drop_2 is "; 180 | tuple_drop<2>(t); 181 | std::cout << std::endl; 182 | 183 | // prints 2, 3 184 | 185 | return 0; 186 | } 187 | 188 | `tuple_append`: 189 | 190 | #include "tuple_utility.hpp" 191 | 192 | int main() 193 | { 194 | auto t = std::make_tuple(0, 1, 2, 3); 195 | 196 | auto t_append_4 = tuple_append(t, 4); 197 | 198 | std::cout << "t_append_4 is "; 199 | tuple_print(t_append_4); 200 | std::cout << std::endl; 201 | 202 | // prints 0, 1, 2, 3, 4 203 | 204 | return 0; 205 | } 206 | 207 | `tuple_prepend`: 208 | 209 | #include "tuple_utility.hpp" 210 | 211 | int main() 212 | { 213 | auto t = std::make_tuple(0, 1, 2, 3); 214 | 215 | auto t_prepend_neg_1 = tuple_prepend(t, -1); 216 | 217 | std::cout << "t_prepend_neg_1 is "; 218 | tuple_print(t_prepend_neg_1); 219 | std::cout << std::endl; 220 | 221 | // prints -1, 0, 1, 2, 3 222 | 223 | return 0; 224 | } 225 | 226 | `make_from_tuple`: 227 | 228 | #include "tuple_utility.hpp" 229 | #include 230 | 231 | int main() 232 | { 233 | auto t = std::make_tuple(13, 13); 234 | 235 | auto vector_of_13s = make_from_tuple>(t); 236 | 237 | // vector_of_13s is a std::vector containing 13 238 | // elements which are all equal to 13 239 | 240 | return 0; 241 | } 242 | 243 | `tuple_reduce`: 244 | 245 | #include "tuple_utility.hpp" 246 | 247 | int main() 248 | { 249 | auto t = std::make_tuple(0, 1, 2, 3); 250 | 251 | auto sum = tuple_reduce(t, 0, [](int x, int y){return x + y;}); 252 | 253 | std::cout << "sum of t's elements is " << sum << std::endl; 254 | // prints 6 255 | 256 | return 0; 257 | } 258 | 259 | `tuple_for_each`: 260 | 261 | #include "tuple_utility.hpp" 262 | 263 | int main() 264 | { 265 | auto t = std::make_tuple(0, 1, 2, 3); 266 | 267 | auto sum = tuple_for_each([](int& x){ ++x; }, t); 268 | 269 | tuple_print(t); 270 | // prints 1, 2, 3, 4 271 | 272 | return 0; 273 | } 274 | 275 | `tuple_filter`: 276 | 277 | #include "tuple_utility.hpp" 278 | #include 279 | #include 280 | 281 | int main() 282 | { 283 | auto t1 = std::make_tuple(13, 3.14159, std::string("hi there")); 284 | 285 | auto t2 = tuple_filter(t1); 286 | 287 | tuple_print(t2); 288 | std::cout << std::endl; 289 | // prints 13, 3.14159 290 | 291 | return 0; 292 | } 293 | 294 | `tuple_lexicographical_compare`: 295 | 296 | #include "tuple_utility.hpp" 297 | 298 | int main() 299 | { 300 | auto t1 = std::make_tuple(0, 1, 2); 301 | auto t2 = std::make_tuple(3, 4); 302 | 303 | std::cout << "t1 is less than t2: " << tuple_lexicographical_compare(t1, t2) << std::endl; 304 | // prints 1 305 | 306 | auto t3 = std::make_tuple(5, 6, 7); 307 | auto t4 = std::make_tuple(0, 1, 2, 3, 4); 308 | 309 | std::cout << "t3 is less than t4: " << tuple_lexicographical_compare(t3, t4) << std::endl; 310 | // prints 0 311 | 312 | return 0; 313 | } 314 | 315 | `tuple_repeat`: 316 | 317 | #include "tuple_utility.hpp" 318 | 319 | int main() 320 | { 321 | auto t1 = tuple_repeat<3>(13.0); 322 | 323 | tuple_print(t1); 324 | std::cout << std::endl; 325 | // prints 13, 13, 13 326 | 327 | return 0; 328 | } 329 | 330 | `tuple_gather`: 331 | 332 | #include "tuple_utility.hpp" 333 | 334 | int main() 335 | { 336 | auto t1 = std::make_tuple('a', 'b', 'c', 'd', 'e'); 337 | auto t2 = tuple_gather<0,2,4>(t1); 338 | 339 | tuple_print(t2); 340 | std::cout << std::endl; 341 | // prints a, c, e 342 | 343 | return 0; 344 | } 345 | 346 | -------------------------------------------------------------------------------- /demo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "tuple_utility.hpp" 6 | 7 | int main() 8 | { 9 | auto t = std::make_tuple(0, 1, 2, 3); 10 | 11 | // negate the elements of a tuple 12 | auto negative_t = tuple_map(std::negate(), t); 13 | 14 | std::cout << "negative_t: "; 15 | tuple_print(negative_t); 16 | std::cout << std::endl; 17 | 18 | // add two tuples together 19 | auto zero_t = tuple_map(std::plus(), t, negative_t); 20 | 21 | std::cout << "zero_t: "; 22 | tuple_print(zero_t); 23 | std::cout << std::endl; 24 | 25 | auto one_t = std::make_tuple(1,1,1); 26 | 27 | auto two_t = std::make_tuple(2,2,2); 28 | 29 | auto three_t = std::make_tuple(3,3,3); 30 | 31 | // add three tuples together 32 | auto six_t = tuple_map([](int x, int y, int z){return x + y + z;}, one_t, two_t, three_t); 33 | 34 | std::cout << "six_t: "; 35 | tuple_print(six_t); 36 | std::cout << std::endl; 37 | 38 | // take the first 2 elements of six_t: 39 | auto six_t_first_two = tuple_take<2>(six_t); 40 | 41 | std::cout << "six_t_first_two: "; 42 | tuple_print(six_t_first_two); 43 | std::cout << std::endl; 44 | 45 | // drop the first 2 elements of t: 46 | auto t_drop_2 = tuple_drop<2>(t); 47 | 48 | std::cout << "t_drop_2: "; 49 | tuple_print(t_drop_2); 50 | std::cout << std::endl; 51 | 52 | // make a std::vector from constructor arguments taken from a tuple 53 | auto vector_of_13s = make_from_tuple>(std::make_tuple(13,13)); 54 | 55 | // append to a tuple 56 | auto empty = std::make_tuple(); 57 | auto t10 = tuple_append(empty, 13); 58 | 59 | std::cout << "t10: "; 60 | tuple_print(t10); 61 | std::cout << std::endl; 62 | 63 | // reduce a tuple 64 | auto t11 = std::make_tuple(0, 1, 2, 3); 65 | auto reduce_t11 = tuple_reduce(t11, 0, [](int x, int y){return x + y;}); 66 | std::cout << "reduce_t11: " << reduce_t11 << std::endl; 67 | 68 | // increment each element of a tuple 69 | auto t12 = std::make_tuple(0, 1, 2, 3); 70 | tuple_for_each([](int &x){ ++x; }, t12); 71 | std::cout << "t12: "; 72 | tuple_print(t12); 73 | std::cout << std::endl; 74 | 75 | auto t13 = std::make_tuple(0, 1); 76 | auto t14 = std::make_tuple(2, 3, 4); 77 | 78 | std::cout << "t13 less than t14: " << tuple_lexicographical_compare(t13, t14) << std::endl; 79 | std::cout << "empty less than t13: " << tuple_lexicographical_compare(empty, t13) << std::endl; 80 | std::cout << "empty less empty: " << tuple_lexicographical_compare(empty, empty) << std::endl; 81 | std::cout << "t14 less than t12: " << tuple_lexicographical_compare(t14, t12) << std::endl; 82 | 83 | // zip two tuples together 84 | auto t15 = std::make_tuple(0, 1); 85 | auto t16 = std::make_tuple(2, 3); 86 | auto t17 = tuple_zip(t15,t16); 87 | static_cast(t17); 88 | 89 | // filter elements of a tuple which are not arithmetic types 90 | auto t18 = std::make_tuple(13, 3.14159265359, std::string("not arithmetic")); 91 | auto t19 = tuple_filter(t18); 92 | std::cout << "t19: "; 93 | tuple_print(t19); 94 | std::cout << std::endl; 95 | 96 | // prepend to a tuple 97 | auto t20 = tuple_prepend(empty, 7); 98 | 99 | std::cout << "t20: "; 100 | tuple_print(t20); 101 | std::cout << std::endl; 102 | 103 | // repeat a value a constant number of times 104 | auto t21 = tuple_repeat<3>(13.0); 105 | std::cout << "t21: "; 106 | tuple_print(t21); 107 | std::cout << std::endl; 108 | 109 | // gather elements from a tuple 110 | auto t22 = std::make_tuple('a', 'b', 'c', 'd', 'e'); 111 | auto t23 = tuple_gather<0,2,4>(t22); 112 | 113 | std::cout << "t23: "; 114 | tuple_print(t23); 115 | std::cout << std::endl; 116 | 117 | return 0; 118 | } 119 | 120 | -------------------------------------------------------------------------------- /tuple_utility.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions 5 | // are met: 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above copyright 9 | // notice, this list of conditions and the following disclaimer in the 10 | // documentation and/or other materials provided with the distribution. 11 | // * Neither the name of NVIDIA CORPORATION nor the names of its 12 | // contributors may be used to endorse or promote products derived 13 | // from this software without specific prior written permission. 14 | // 15 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 16 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 23 | // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | #pragma once 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | // allow the user to define an annotation to apply to these functions 35 | // by default, it attempts to be constexpr 36 | #ifndef TUPLE_UTILITY_ANNOTATION 37 | # if __cplusplus <= 201103L 38 | # define TUPLE_UTILITY_ANNOTATION 39 | # else 40 | # define TUPLE_UTILITY_ANNOTATION constexpr 41 | # endif 42 | # define TUPLE_UTILITY_ANNOTATION_NEEDS_UNDEF 43 | #endif 44 | 45 | 46 | #define TUPLE_UTILITY_REQUIRES(...) typename std::enable_if<(__VA_ARGS__)>::type* = nullptr 47 | 48 | 49 | // figure out what namespace to put everything in 50 | #if !defined(TUPLE_UTILITY_NAMESPACE) 51 | # if defined(TUPLE_UTILITY_NAMESPACE_OPEN_BRACE) or defined(TUPLE_UTILITY_NAMESPACE_CLOSE_BRACE) 52 | # error "Either all of TUPLE_UTILITY_NAMESPACE, TUPLE_UTILITY_NAMESPACE_OPEN_BRACE, and TUPLE_UTILITY_NAMESPACE_CLOSE_BRACE must be defined, or none of them." 53 | # endif 54 | 55 | // by default, there is no namespace 56 | # define TUPLE_UTILITY_NAMESPACE 57 | # define TUPLE_UTILITY_NAMESPACE_OPEN_BRACE 58 | # define TUPLE_UTILITY_NAMESPACE_CLOSE_BRACE 59 | # define TUPLE_UTILITY_NAMESPACE_NEEDS_UNDEF 60 | 61 | #elif defined(TUPLE_UTILITY_NAMESPACE) or defined(TUPLE_UTILITY_NAMESPACE_OPEN_BRACE) or defined(TUPLE_UTILITY_NAMESPACE_CLOSE_BRACE) 62 | # if !defined(TUPLE_UTILITY_NAMESPACE) or !defined(TUPLE_UTILITY_NAMESPACE_OPEN_BRACE) or !defined(TUPLE_UTILITY_NAMESPACE_CLOSE_BRACE) 63 | # error "Either all of TUPLE_UTILITY_NAMESPACE, TUPLE_UTILITY_NAMESPACE_OPEN_BRACE, and TUPLE_UTILITY_NAMESPACE_CLOSE_BRACE must be defined, or none of them." 64 | # endif 65 | #endif 66 | 67 | 68 | TUPLE_UTILITY_NAMESPACE_OPEN_BRACE 69 | 70 | 71 | namespace detail 72 | { 73 | 74 | 75 | template 76 | using decay_t = typename std::decay::type; 77 | 78 | 79 | template 80 | struct conjunction; 81 | 82 | template<> 83 | struct conjunction<> : std::true_type {}; 84 | 85 | template 86 | struct conjunction 87 | : std::integral_constant< 88 | bool, 89 | Condition::value and conjunction::value 90 | > 91 | {}; 92 | 93 | 94 | // define index sequence in case it is missing 95 | template struct index_sequence {}; 96 | 97 | template 98 | struct make_index_sequence_impl; 99 | 100 | template 101 | struct make_index_sequence_impl< 102 | Start, 103 | index_sequence, 104 | End 105 | > 106 | { 107 | typedef typename make_index_sequence_impl< 108 | Start + 1, 109 | index_sequence, 110 | End 111 | >::type type; 112 | }; 113 | 114 | template 115 | struct make_index_sequence_impl, End> 116 | { 117 | typedef index_sequence type; 118 | }; 119 | 120 | template 121 | using make_index_sequence = typename make_index_sequence_impl<0, index_sequence<>, N>::type; 122 | 123 | 124 | 125 | template 126 | struct has_get_member_function_impl 127 | { 128 | // XXX consider requiring that Result matches the expected result, 129 | // i.e. propagate_reference_t> 130 | template().template get()) 133 | > 134 | static std::true_type test(int); 135 | 136 | static std::false_type test(...); 137 | 138 | using type = decltype(test(0)); 139 | }; 140 | 141 | template 142 | using has_get_member_function = typename has_get_member_function_impl::type; 143 | 144 | 145 | template 146 | struct has_std_get_free_function_impl 147 | { 148 | // XXX consider requiring that Result matches the expected result, 149 | // i.e. propagate_reference_t> 150 | template(std::declval())) 153 | > 154 | static std::true_type test(int); 155 | 156 | static std::false_type test(...); 157 | 158 | using type = decltype(test(0)); 159 | }; 160 | 161 | template 162 | using has_std_get_free_function = typename has_std_get_free_function_impl::type; 163 | 164 | 165 | template 166 | struct has_operator_bracket_impl 167 | { 168 | // XXX consider requiring that Result matches the expected result, 169 | // i.e. propagate_reference_t> 170 | template()[0]) 172 | > 173 | static std::true_type test(int); 174 | 175 | static std::false_type test(...); 176 | 177 | using type = decltype(test(0)); 178 | }; 179 | 180 | template 181 | using has_operator_bracket = typename has_operator_bracket_impl::type; 182 | 183 | 184 | } // end detail 185 | 186 | 187 | template 188 | struct tuple_traits 189 | { 190 | using tuple_type = T; 191 | 192 | static const size_t size = std::tuple_size::value; 193 | 194 | template 195 | using element_type = typename std::tuple_element::type; 196 | 197 | // these overloads of get use member t.template get() 198 | template::value 201 | )> 202 | TUPLE_UTILITY_ANNOTATION 203 | static element_type& get(tuple_type& t) 204 | { 205 | return t.template get(); 206 | } 207 | 208 | template::value 211 | )> 212 | TUPLE_UTILITY_ANNOTATION 213 | static const element_type& get(const tuple_type& t) 214 | { 215 | return t.template get(); 216 | } 217 | 218 | template::value 221 | )> 222 | TUPLE_UTILITY_ANNOTATION 223 | static element_type&& get(tuple_type&& t) 224 | { 225 | return std::move(t).template get(); 226 | } 227 | 228 | 229 | // these overloads of get use std::get(t) 230 | template::value and 233 | detail::has_std_get_free_function::value 234 | )> 235 | TUPLE_UTILITY_ANNOTATION 236 | static element_type& get(tuple_type& t) 237 | { 238 | return std::get(t); 239 | } 240 | 241 | template::value and 244 | detail::has_std_get_free_function::value 245 | )> 246 | TUPLE_UTILITY_ANNOTATION 247 | static const element_type& get(const tuple_type& t) 248 | { 249 | return std::get(t); 250 | } 251 | 252 | template::value and 255 | detail::has_std_get_free_function::value 256 | )> 257 | TUPLE_UTILITY_ANNOTATION 258 | static element_type&& get(tuple_type&& t) 259 | { 260 | return std::get(std::move(t)); 261 | } 262 | 263 | 264 | // these overloads of get use t[i] (operator bracket) 265 | template::value and 268 | !detail::has_std_get_free_function::value and 269 | detail::has_operator_bracket::value 270 | )> 271 | TUPLE_UTILITY_ANNOTATION 272 | static element_type& get(tuple_type& t) 273 | { 274 | return t[i]; 275 | } 276 | 277 | template::value and 280 | !detail::has_std_get_free_function::value and 281 | detail::has_operator_bracket::value 282 | )> 283 | TUPLE_UTILITY_ANNOTATION 284 | static const element_type& get(const tuple_type& t) 285 | { 286 | return t[i]; 287 | } 288 | 289 | template::value and 292 | !detail::has_std_get_free_function::value and 293 | detail::has_operator_bracket::value 294 | )> 295 | TUPLE_UTILITY_ANNOTATION 296 | static element_type&& get(tuple_type&& t) 297 | { 298 | return std::move(std::move(t)[i]); 299 | } 300 | }; 301 | 302 | 303 | template 304 | struct is_tuple_like 305 | { 306 | // XXX this should also check for the existence of std::tuple_element::type 307 | // for all of T's elements 308 | template::value 310 | > 311 | static constexpr bool test(int) 312 | { 313 | return true; 314 | } 315 | 316 | template 317 | static constexpr bool test(...) 318 | { 319 | return false; 320 | } 321 | 322 | static constexpr bool value = test(0); 323 | }; 324 | 325 | 326 | static_assert(is_tuple_like>::value, "std::tuple should be tuple-like."); 327 | 328 | 329 | template 330 | struct tuple_rebind; 331 | 332 | 333 | // tuple-like templates can always be rebound 334 | template class TupleTemplate, class... OriginalTypes, class... ReboundTypes> 335 | struct tuple_rebind, ReboundTypes...> 336 | { 337 | using type = TupleTemplate; 338 | }; 339 | 340 | 341 | // array-like templates can be rebound if all of the types to use in the rebinding are the same 342 | template class ArrayTemplate, class OriginalType, std::size_t N, class ReboundType, class... ReboundTypes> 343 | struct tuple_rebind, ReboundType, ReboundTypes...> 344 | : std::conditional< 345 | detail::conjunction...>::value, // if all of the types to rebind are the same, 346 | ArrayTemplate, // then reinstantiate the ArrayTemplate using ReboundType 347 | std::enable_if // otherwise, do not define a member named type 348 | >::type 349 | {}; 350 | 351 | 352 | // pair-like templates can be rebound if we have two types to use in the rebinding 353 | template class PairTemplate, class OriginalType1, class OriginalType2, class ReboundType1, class ReboundType2> 354 | struct tuple_rebind, ReboundType1, ReboundType2> 355 | { 356 | using type = PairTemplate; 357 | }; 358 | 359 | 360 | template 361 | using tuple_rebind_t = typename tuple_rebind::type; 362 | 363 | 364 | template 365 | TUPLE_UTILITY_ANNOTATION 366 | auto get(Tuple&& t) 367 | -> decltype( 368 | tuple_traits>::template get(std::forward(t)) 369 | ) 370 | { 371 | return tuple_traits>::template get(std::forward(t)); 372 | } 373 | 374 | 375 | template 376 | TUPLE_UTILITY_ANNOTATION 377 | auto tuple_head(Tuple&& t) 378 | -> decltype( 379 | TUPLE_UTILITY_NAMESPACE::get<0>(std::forward(t)) 380 | ) 381 | { 382 | return TUPLE_UTILITY_NAMESPACE::get<0>(std::forward(t)); 383 | } 384 | 385 | 386 | namespace detail 387 | { 388 | 389 | 390 | template 391 | TUPLE_UTILITY_ANNOTATION 392 | auto tuple_tail_invoke_impl(Tuple&& t, Function f, index_sequence) 393 | -> decltype( 394 | f( 395 | TUPLE_UTILITY_NAMESPACE::get(std::forward(t))... 396 | ) 397 | ) 398 | { 399 | return f(TUPLE_UTILITY_NAMESPACE::get(std::forward(t))...); 400 | } 401 | 402 | 403 | } // end detail 404 | 405 | 406 | template 407 | TUPLE_UTILITY_ANNOTATION 408 | auto tuple_tail_invoke(Tuple&& t, Function f) 409 | -> decltype( 410 | detail::tuple_tail_invoke_impl( 411 | std::forward(t), 412 | f, 413 | detail::make_index_sequence< 414 | std::tuple_size< 415 | typename std::decay::type 416 | >::value - 1 417 | >() 418 | ) 419 | ) 420 | { 421 | return tuple_tail_invoke_impl( 422 | std::forward(t), 423 | f, 424 | detail::make_index_sequence< 425 | std::tuple_size< 426 | typename std::decay::type 427 | >::value - 1 428 | >() 429 | ); 430 | } 431 | 432 | 433 | namespace detail 434 | { 435 | 436 | 437 | template 438 | TUPLE_UTILITY_ANNOTATION 439 | auto tuple_prefix_invoke_impl(Tuple&& t, Function f, index_sequence) 440 | -> decltype( 441 | f( 442 | TUPLE_UTILITY_NAMESPACE::get(std::forward(t))... 443 | ) 444 | ) 445 | { 446 | return f(TUPLE_UTILITY_NAMESPACE::get(std::forward(t))...); 447 | } 448 | 449 | 450 | } // end detail 451 | 452 | 453 | template 454 | TUPLE_UTILITY_ANNOTATION 455 | auto tuple_prefix_invoke(Tuple&& t, Function f) 456 | -> decltype( 457 | detail::tuple_prefix_invoke_impl( 458 | std::forward(t), 459 | f, 460 | detail::make_index_sequence< 461 | std::tuple_size< 462 | typename std::decay::type 463 | >::value - 1 464 | >() 465 | ) 466 | ) 467 | { 468 | return detail::tuple_prefix_invoke_impl( 469 | std::forward(t), 470 | f, 471 | detail::make_index_sequence< 472 | std::tuple_size< 473 | typename std::decay::type 474 | >::value - 1 475 | >() 476 | ); 477 | } 478 | 479 | 480 | namespace detail 481 | { 482 | 483 | 484 | struct tuple_forwarder 485 | { 486 | template 487 | TUPLE_UTILITY_ANNOTATION 488 | auto operator()(Args&&... args) 489 | -> decltype( 490 | std::forward_as_tuple(args...) 491 | ) 492 | { 493 | return std::forward_as_tuple(args...); 494 | } 495 | }; 496 | 497 | 498 | } // end detail 499 | 500 | 501 | // forward_tuple_tail() returns t's tail as a tuple of references 502 | template 503 | TUPLE_UTILITY_ANNOTATION 504 | auto forward_tuple_tail(typename std::remove_reference::type& t) 505 | -> decltype( 506 | tuple_tail_invoke(std::forward(t), detail::tuple_forwarder{}) 507 | ) 508 | { 509 | return tuple_tail_invoke(std::forward(t), detail::tuple_forwarder{}); 510 | } 511 | 512 | 513 | namespace detail 514 | { 515 | 516 | 517 | template 518 | TUPLE_UTILITY_ANNOTATION 519 | auto tuple_tail_impl_impl(Args&&... args) 520 | -> decltype( 521 | std::make_tuple(args...) 522 | ) 523 | { 524 | return std::make_tuple(args...); 525 | } 526 | 527 | template 528 | TUPLE_UTILITY_ANNOTATION 529 | auto tuple_tail_impl(Tuple&& t, index_sequence) 530 | -> decltype( 531 | detail::tuple_tail_impl_impl(TUPLE_UTILITY_NAMESPACE::get(std::forward(t))...) 532 | ) 533 | { 534 | return detail::tuple_tail_impl_impl(TUPLE_UTILITY_NAMESPACE::get(std::forward(t))...); 535 | } 536 | 537 | 538 | } // end detail 539 | 540 | 541 | // tuple_tail() returns t's tail as a tuple of values 542 | // i.e., it makes a copy of t's tail 543 | template 544 | TUPLE_UTILITY_ANNOTATION 545 | auto tuple_tail(Tuple&& t) 546 | -> decltype( 547 | detail::tuple_tail_impl( 548 | std::forward(t), 549 | detail::make_index_sequence< 550 | std::tuple_size< 551 | typename std::decay::type 552 | >::value - 1 553 | >() 554 | ) 555 | ) 556 | { 557 | using indices = detail::make_index_sequence< 558 | std::tuple_size< 559 | typename std::decay::type 560 | >::value - 1 561 | >; 562 | return detail::tuple_tail_impl(std::forward(t), indices()); 563 | } 564 | 565 | 566 | namespace detail 567 | { 568 | 569 | 570 | template 571 | TUPLE_UTILITY_ANNOTATION 572 | auto tuple_take_invoke_impl(Tuple&& t, Function f, index_sequence) 573 | -> decltype( 574 | f( 575 | TUPLE_UTILITY_NAMESPACE::get(std::forward(t))... 576 | ) 577 | ) 578 | { 579 | return f(TUPLE_UTILITY_NAMESPACE::get(std::forward(t))...); 580 | } 581 | 582 | 583 | } // end detail 584 | 585 | 586 | template 587 | TUPLE_UTILITY_ANNOTATION 588 | auto tuple_take_invoke(Tuple&& t, Function f) 589 | -> decltype( 590 | detail::tuple_take_invoke_impl(std::forward(t), f, detail::make_index_sequence()) 591 | ) 592 | { 593 | return detail::tuple_take_invoke_impl(std::forward(t), f, detail::make_index_sequence()); 594 | } 595 | 596 | 597 | namespace detail 598 | { 599 | 600 | 601 | struct std_tuple_factory 602 | { 603 | template 604 | TUPLE_UTILITY_ANNOTATION 605 | auto operator()(T&&... args) 606 | -> decltype( 607 | std::make_tuple(std::forward(args)...) 608 | ) 609 | { 610 | return std::make_tuple(std::forward(args)...); 611 | } 612 | }; 613 | 614 | 615 | } // end detail 616 | 617 | 618 | template 619 | TUPLE_UTILITY_ANNOTATION 620 | auto tuple_take(Tuple&& t) 621 | -> decltype( 622 | tuple_take_invoke(std::forward(t), detail::std_tuple_factory()) 623 | ) 624 | { 625 | return tuple_take_invoke(std::forward(t), detail::std_tuple_factory()); 626 | } 627 | 628 | 629 | namespace detail 630 | { 631 | 632 | 633 | template 634 | TUPLE_UTILITY_ANNOTATION 635 | auto tuple_drop_invoke_impl(Tuple&& t, Function f, index_sequence) 636 | -> decltype( 637 | f(TUPLE_UTILITY_NAMESPACE::get(std::forward(t))...) 638 | ) 639 | { 640 | return f(TUPLE_UTILITY_NAMESPACE::get(std::forward(t))...); 641 | } 642 | 643 | 644 | } // end detail 645 | 646 | 647 | template 648 | TUPLE_UTILITY_ANNOTATION 649 | auto tuple_drop_invoke(Tuple&& t, Function f) 650 | -> decltype( 651 | detail::tuple_drop_invoke_impl( 652 | std::forward(t), 653 | f, 654 | detail::make_index_sequence::type>::value - N>() 655 | ) 656 | ) 657 | { 658 | return detail::tuple_drop_invoke_impl( 659 | std::forward(t), 660 | f, 661 | detail::make_index_sequence::type>::value - N>() 662 | ); 663 | } 664 | 665 | 666 | template 667 | TUPLE_UTILITY_ANNOTATION 668 | auto tuple_drop(Tuple&& t) 669 | -> decltype( 670 | tuple_drop_invoke(std::forward(t), detail::std_tuple_factory()) 671 | ) 672 | { 673 | return TUPLE_UTILITY_NAMESPACE::tuple_drop_invoke(std::forward(t), detail::std_tuple_factory()); 674 | } 675 | 676 | 677 | template 678 | TUPLE_UTILITY_ANNOTATION 679 | auto tuple_drop_back_invoke(Tuple&& t, Function f) 680 | -> decltype( 681 | tuple_take_invoke::type>::value - N>(std::forward(t), f) 682 | ) 683 | { 684 | return tuple_take_invoke::type>::value - N>(std::forward(t), f); 685 | } 686 | 687 | 688 | template 689 | TUPLE_UTILITY_ANNOTATION 690 | auto tuple_drop_back(Tuple&& t) 691 | -> decltype( 692 | tuple_drop_back_invoke(std::forward(t), detail::std_tuple_factory()) 693 | ) 694 | { 695 | return tuple_drop_back_invoke(std::forward(t), detail::std_tuple_factory()); 696 | } 697 | 698 | 699 | template 700 | TUPLE_UTILITY_ANNOTATION 701 | auto tuple_drop_last(Tuple&& t) 702 | -> decltype( 703 | TUPLE_UTILITY_NAMESPACE::tuple_drop_back<1>(std::forward(t)) 704 | ) 705 | { 706 | return TUPLE_UTILITY_NAMESPACE::tuple_drop_back<1>(std::forward(t)); 707 | } 708 | 709 | 710 | template 711 | TUPLE_UTILITY_ANNOTATION 712 | auto tuple_last(Tuple&& t) 713 | -> decltype( 714 | TUPLE_UTILITY_NAMESPACE::get< 715 | std::tuple_size< 716 | typename std::decay::type 717 | >::value - 1 718 | >(std::forward(t)) 719 | ) 720 | { 721 | const size_t i = std::tuple_size::type>::value - 1; 722 | return TUPLE_UTILITY_NAMESPACE::get(std::forward(t)); 723 | } 724 | 725 | 726 | namespace detail 727 | { 728 | 729 | 730 | template 731 | TUPLE_UTILITY_ANNOTATION 732 | auto tuple_append_invoke_impl(Tuple&& t, T&& x, Function f, index_sequence) 733 | -> decltype( 734 | f(TUPLE_UTILITY_NAMESPACE::get(std::forward(t))..., std::forward(x)) 735 | ) 736 | { 737 | return f(TUPLE_UTILITY_NAMESPACE::get(std::forward(t))..., std::forward(x)); 738 | } 739 | 740 | 741 | } // end detail 742 | 743 | 744 | template 745 | TUPLE_UTILITY_ANNOTATION 746 | auto tuple_append_invoke(Tuple&& t, T&& x, Function f) 747 | -> decltype( 748 | detail::tuple_append_invoke_impl( 749 | std::forward(t), 750 | std::forward(x), 751 | f, 752 | detail::make_index_sequence< 753 | std::tuple_size< 754 | typename std::decay::type 755 | >::value 756 | >() 757 | ) 758 | ) 759 | { 760 | using indices = detail::make_index_sequence< 761 | std::tuple_size::type>::value 762 | >; 763 | return detail::tuple_append_invoke_impl(std::forward(t), std::forward(x), f, indices()); 764 | } 765 | 766 | 767 | namespace detail 768 | { 769 | 770 | 771 | template 772 | TUPLE_UTILITY_ANNOTATION 773 | auto tuple_prepend_invoke_impl(Tuple&& t, T&& x, Function f, index_sequence) 774 | -> decltype( 775 | f(std::forward(x), TUPLE_UTILITY_NAMESPACE::get(std::forward(t))...) 776 | ) 777 | { 778 | return f(std::forward(x), TUPLE_UTILITY_NAMESPACE::get(std::forward(t))...); 779 | } 780 | 781 | 782 | } // end detail 783 | 784 | 785 | template 786 | TUPLE_UTILITY_ANNOTATION 787 | auto tuple_prepend_invoke(Tuple&& t, T&& x, Function f) 788 | -> decltype( 789 | detail::tuple_prepend_invoke_impl( 790 | std::forward(t), 791 | std::forward(x), 792 | f, 793 | detail::make_index_sequence< 794 | std::tuple_size< 795 | typename std::decay::type 796 | >::value 797 | >() 798 | ) 799 | ) 800 | { 801 | using indices = detail::make_index_sequence< 802 | std::tuple_size::type>::value 803 | >; 804 | return detail::tuple_prepend_invoke_impl(std::forward(t), std::forward(x), f, indices()); 805 | } 806 | 807 | 808 | template 809 | TUPLE_UTILITY_ANNOTATION 810 | auto tuple_append(Tuple&& t, T&& x) 811 | -> decltype( 812 | tuple_append_invoke(std::forward(t), std::forward(x), detail::std_tuple_factory()) 813 | ) 814 | { 815 | return tuple_append_invoke(std::forward(t), std::forward(x), detail::std_tuple_factory()); 816 | } 817 | 818 | 819 | template 820 | TUPLE_UTILITY_ANNOTATION 821 | auto tuple_prepend(Tuple&& t, T&& x) 822 | -> decltype( 823 | tuple_prepend_invoke(std::forward(t), std::forward(x), detail::std_tuple_factory()) 824 | ) 825 | { 826 | return tuple_prepend_invoke(std::forward(t), std::forward(x), detail::std_tuple_factory()); 827 | } 828 | 829 | 830 | namespace detail 831 | { 832 | 833 | 834 | template 835 | TUPLE_UTILITY_ANNOTATION 836 | auto tuple_map_invoke(Function f, Tuples&&... ts) 837 | -> decltype( 838 | f(TUPLE_UTILITY_NAMESPACE::get(std::forward(ts))...) 839 | ) 840 | { 841 | return f(TUPLE_UTILITY_NAMESPACE::get(std::forward(ts))...); 842 | } 843 | 844 | 845 | template 846 | TUPLE_UTILITY_ANNOTATION 847 | auto tuple_map_with_make_impl(index_sequence, Function1 f, Function2 make, Tuples&&... ts) 848 | -> decltype( 849 | make( 850 | tuple_map_invoke(f, std::forward(ts)...)... 851 | ) 852 | ) 853 | { 854 | return make( 855 | tuple_map_invoke(f, std::forward(ts)...)... 856 | ); 857 | } 858 | 859 | 860 | } // end detail 861 | 862 | 863 | template 864 | TUPLE_UTILITY_ANNOTATION 865 | auto tuple_map_with_make(Function1 f, Function2 make, Tuple&& t, Tuples&&... ts) 866 | -> decltype( 867 | detail::tuple_map_with_make_impl( 868 | detail::make_index_sequence< 869 | std::tuple_size>::value 870 | >(), 871 | f, 872 | make, 873 | std::forward(t), 874 | std::forward(ts)... 875 | ) 876 | ) 877 | { 878 | return detail::tuple_map_with_make_impl( 879 | detail::make_index_sequence< 880 | std::tuple_size>::value 881 | >(), 882 | f, 883 | make, 884 | std::forward(t), 885 | std::forward(ts)... 886 | ); 887 | } 888 | 889 | 890 | template 891 | TUPLE_UTILITY_ANNOTATION 892 | auto tuple_map(Function f, Tuple&& t, Tuples&&... ts) 893 | -> decltype( 894 | tuple_map_with_make(f, detail::std_tuple_factory(), std::forward(t), std::forward(ts)...) 895 | ) 896 | { 897 | return tuple_map_with_make(f, detail::std_tuple_factory(), std::forward(t), std::forward(ts)...); 898 | } 899 | 900 | 901 | namespace detail 902 | { 903 | 904 | 905 | template 906 | TUPLE_UTILITY_ANNOTATION 907 | T make_from_tuple_impl(const Tuple& t, index_sequence) 908 | { 909 | // use constructor syntax 910 | return T(TUPLE_UTILITY_NAMESPACE::get(t)...); 911 | } 912 | 913 | 914 | } // end detail 915 | 916 | 917 | template 918 | TUPLE_UTILITY_ANNOTATION 919 | T make_from_tuple(const Tuple& t) 920 | { 921 | return detail::make_from_tuple_impl(t, detail::make_index_sequence::value>()); 922 | } 923 | 924 | 925 | namespace detail 926 | { 927 | 928 | 929 | template 930 | struct tuple_for_each_functor 931 | { 932 | mutable Function f; 933 | 934 | template 935 | TUPLE_UTILITY_ANNOTATION 936 | int operator()(Args&&... args) const 937 | { 938 | f(std::forward(args)...); 939 | return 0; 940 | } 941 | }; 942 | 943 | 944 | template 945 | TUPLE_UTILITY_ANNOTATION 946 | int apply_row(Function f, Tuples&&... ts) 947 | { 948 | f(TUPLE_UTILITY_NAMESPACE::get(std::forward(ts))...); 949 | return 0; 950 | } 951 | 952 | 953 | template 954 | TUPLE_UTILITY_ANNOTATION 955 | void swallow(Args&&...) {} 956 | 957 | 958 | template 959 | TUPLE_UTILITY_ANNOTATION 960 | void tuple_for_each_impl(index_sequence, Function f, Tuples&&... ts) 961 | { 962 | auto g = tuple_for_each_functor{f}; 963 | 964 | // XXX swallow g to WAR nvcc 7.0 unused variable warning 965 | detail::swallow(g); 966 | 967 | // unpacking into a init lists preserves the order given by Indices 968 | using ints = int[]; 969 | (void) ints{0, ((detail::apply_row(g, std::forward(ts)...)), void(), 0)...}; 970 | } 971 | 972 | 973 | } // end detail 974 | 975 | 976 | template 977 | TUPLE_UTILITY_ANNOTATION 978 | void tuple_for_each_n(Function f, Tuple1&& t1, Tuples&&... ts) 979 | { 980 | detail::tuple_for_each_impl(detail::make_index_sequence(), f, std::forward(t1), std::forward(ts)...); 981 | } 982 | 983 | 984 | template 985 | TUPLE_UTILITY_ANNOTATION 986 | void tuple_for_each(Function f, Tuple1&& t1, Tuples&&... ts) 987 | { 988 | tuple_for_each_n>::value>(f, std::forward(t1), std::forward(ts)...); 989 | } 990 | 991 | 992 | namespace detail 993 | { 994 | 995 | 996 | template 997 | struct tuple_reduce_functor 998 | { 999 | T& init; 1000 | Function f; 1001 | 1002 | template 1003 | TUPLE_UTILITY_ANNOTATION 1004 | void operator()(Arg&& arg) 1005 | { 1006 | init = f(init, std::forward(arg)); 1007 | } 1008 | }; 1009 | 1010 | 1011 | } // end detail 1012 | 1013 | 1014 | template 1015 | TUPLE_UTILITY_ANNOTATION 1016 | T tuple_reduce(Tuple&& t, T init, Function f) 1017 | { 1018 | auto g = detail::tuple_reduce_functor{init, f}; 1019 | TUPLE_UTILITY_NAMESPACE::tuple_for_each(g, std::forward(t)); 1020 | return g.init; 1021 | } 1022 | 1023 | 1024 | namespace detail 1025 | { 1026 | 1027 | 1028 | template 1029 | struct print_element_and_delimiter 1030 | { 1031 | std::ostream &os; 1032 | const T& delimiter; 1033 | 1034 | template 1035 | void operator()(const U& arg) 1036 | { 1037 | os << arg << delimiter; 1038 | } 1039 | }; 1040 | 1041 | 1042 | template 1043 | typename std::enable_if< 1044 | (std::tuple_size< 1045 | decay_t 1046 | >::value > 0) 1047 | >::type 1048 | tuple_print_impl(const Tuple& t, std::ostream& os, const T& delimiter) 1049 | { 1050 | static const int n_ = std::tuple_size>::value - 1; 1051 | static const int n = n_ < 0 ? 0 : n_; 1052 | 1053 | tuple_for_each_n(print_element_and_delimiter{os,delimiter}, t); 1054 | 1055 | // finally print the last element sans delimiter 1056 | os << TUPLE_UTILITY_NAMESPACE::tuple_last(t); 1057 | } 1058 | 1059 | 1060 | } // end detail 1061 | 1062 | 1063 | template 1064 | void tuple_print(const Tuple& t, std::ostream& os, const T& delimiter) 1065 | { 1066 | detail::tuple_print_impl(t, os, delimiter); 1067 | } 1068 | 1069 | 1070 | template 1071 | void tuple_print(const Tuple& t, std::ostream& os = std::cout) 1072 | { 1073 | TUPLE_UTILITY_NAMESPACE::tuple_print(t, os, ", "); 1074 | } 1075 | 1076 | 1077 | namespace detail 1078 | { 1079 | 1080 | 1081 | // terminal case: Tuple1 is exhausted 1082 | // if we make it to the end of Tuple1, then the tuples are considered equal 1083 | template 1084 | TUPLE_UTILITY_ANNOTATION 1085 | typename std::enable_if< 1086 | (i == std::tuple_size::value) && (i <= std::tuple_size::value), 1087 | bool 1088 | >::type 1089 | tuple_equal_impl(const Tuple1&, const Tuple2&) 1090 | { 1091 | return true; 1092 | } 1093 | 1094 | 1095 | // terminal case: Tuple2 is exhausted but not Tuple1 1096 | // if we make it to the end of Tuple2 before Tuple1, then the tuples are considered unequal 1097 | template 1098 | TUPLE_UTILITY_ANNOTATION 1099 | typename std::enable_if< 1100 | (i < std::tuple_size::value) && (i == std::tuple_size::value), 1101 | bool 1102 | >::type 1103 | tuple_equal_impl(const Tuple1&, const Tuple2&) 1104 | { 1105 | return false; 1106 | } 1107 | 1108 | 1109 | // recursive case 1110 | template 1111 | TUPLE_UTILITY_ANNOTATION 1112 | typename std::enable_if< 1113 | (i < std::tuple_size::value) && (i < std::tuple_size::value), 1114 | bool 1115 | >::type 1116 | tuple_equal_impl(const Tuple1& t1, const Tuple2& t2) 1117 | { 1118 | return (TUPLE_UTILITY_NAMESPACE::get(t1) != TUPLE_UTILITY_NAMESPACE::get(t2)) ? false : 1119 | tuple_equal_impl(t1, t2); 1120 | } 1121 | 1122 | 1123 | } // end detail 1124 | 1125 | 1126 | template 1127 | TUPLE_UTILITY_ANNOTATION 1128 | bool tuple_equal(const Tuple1& t1, const Tuple2& t2) 1129 | { 1130 | return detail::tuple_equal_impl<0>(t1,t2); 1131 | } 1132 | 1133 | 1134 | namespace detail 1135 | { 1136 | 1137 | 1138 | template 1139 | TUPLE_UTILITY_ANNOTATION 1140 | typename std::enable_if< 1141 | std::tuple_size::value <= i, 1142 | bool 1143 | >::type 1144 | tuple_lexicographical_compare_impl(const Tuple1&, const Tuple2&) 1145 | { 1146 | return false; 1147 | } 1148 | 1149 | 1150 | template 1151 | TUPLE_UTILITY_ANNOTATION 1152 | typename std::enable_if< 1153 | (std::tuple_size::value <= i && std::tuple_size::value > i), 1154 | bool 1155 | >::type 1156 | tuple_lexicographical_compare_impl(const Tuple1&, const Tuple2&) 1157 | { 1158 | return true; 1159 | } 1160 | 1161 | 1162 | template 1163 | TUPLE_UTILITY_ANNOTATION 1164 | typename std::enable_if< 1165 | (std::tuple_size::value > i && std::tuple_size::value > i), 1166 | bool 1167 | >::type 1168 | tuple_lexicographical_compare_impl(const Tuple1& t1, const Tuple2& t2) 1169 | { 1170 | return (TUPLE_UTILITY_NAMESPACE::get(t1) < TUPLE_UTILITY_NAMESPACE::get(t2)) ? true : 1171 | (TUPLE_UTILITY_NAMESPACE::get(t2) < TUPLE_UTILITY_NAMESPACE::get(t1)) ? false : 1172 | tuple_lexicographical_compare_impl(t1,t2); 1173 | } 1174 | 1175 | 1176 | } // end detail 1177 | 1178 | 1179 | template 1180 | TUPLE_UTILITY_ANNOTATION 1181 | bool tuple_lexicographical_compare(const Tuple1& t1, const Tuple2& t2) 1182 | { 1183 | return detail::tuple_lexicographical_compare_impl<0>(t1,t2); 1184 | } 1185 | 1186 | 1187 | namespace detail 1188 | { 1189 | 1190 | 1191 | template 1192 | struct lazy_conditional 1193 | { 1194 | using type = typename True::type; 1195 | }; 1196 | 1197 | 1198 | template 1199 | struct lazy_conditional 1200 | { 1201 | using type = typename False::type; 1202 | }; 1203 | 1204 | 1205 | template 1206 | struct propagate_reference 1207 | { 1208 | using type = U; 1209 | }; 1210 | 1211 | template 1212 | struct propagate_reference 1213 | { 1214 | using type = typename std::add_lvalue_reference::type; 1215 | }; 1216 | 1217 | template 1218 | struct propagate_reference 1219 | { 1220 | using type = typename std::add_rvalue_reference::type; 1221 | }; 1222 | 1223 | 1224 | template 1225 | struct tuple_cat_element 1226 | { 1227 | static const size_t size1 = std::tuple_size::value; 1228 | 1229 | using type = typename lazy_conditional< 1230 | (I < size1), 1231 | std::tuple_element, 1232 | tuple_cat_element 1233 | >::type; 1234 | }; 1235 | 1236 | 1237 | template 1238 | struct tuple_cat_element : std::tuple_element {}; 1239 | 1240 | 1241 | template 1242 | struct propagate_reference 1243 | { 1244 | using type = const U&; 1245 | }; 1246 | 1247 | 1248 | template 1249 | struct tuple_get_result 1250 | { 1251 | using type = typename propagate_reference< 1252 | TupleReference, 1253 | typename std::tuple_element< 1254 | i, 1255 | typename std::decay::type 1256 | >::type 1257 | >::type; 1258 | }; 1259 | 1260 | 1261 | 1262 | template 1263 | struct tuple_cat_get_result 1264 | { 1265 | static_assert(std::is_reference::value, "tuple_cat_get_result's template parameters must be reference types."); 1266 | 1267 | using tuple1_type = typename std::decay::type; 1268 | static const size_t size1 = std::tuple_size::value; 1269 | 1270 | using type = typename lazy_conditional< 1271 | (I < size1), 1272 | tuple_get_result, 1273 | tuple_cat_get_result 1274 | >::type; 1275 | }; 1276 | 1277 | 1278 | template 1279 | struct tuple_cat_get_result : tuple_get_result {}; 1280 | 1281 | 1282 | template 1283 | TUPLE_UTILITY_ANNOTATION 1284 | typename tuple_cat_get_result::type 1285 | tuple_cat_get(Tuple1&& t, Tuples&&... ts); 1286 | 1287 | 1288 | template 1289 | TUPLE_UTILITY_ANNOTATION 1290 | typename tuple_cat_get_result::type 1291 | tuple_cat_get_impl(std::false_type, Tuple1&& t, Tuples&&...) 1292 | { 1293 | return TUPLE_UTILITY_NAMESPACE::get(std::forward(t)); 1294 | } 1295 | 1296 | 1297 | template 1298 | TUPLE_UTILITY_ANNOTATION 1299 | typename tuple_cat_get_result::type 1300 | tuple_cat_get_impl(std::true_type, Tuple1&&, Tuples&&... ts) 1301 | { 1302 | const size_t J = I - std::tuple_size::type>::value; 1303 | return detail::tuple_cat_get(std::forward(ts)...); 1304 | } 1305 | 1306 | 1307 | template 1308 | TUPLE_UTILITY_ANNOTATION 1309 | typename tuple_cat_get_result::type 1310 | tuple_cat_get(Tuple1&& t, Tuples&&... ts) 1311 | { 1312 | auto recurse = typename std::conditional< 1313 | I < std::tuple_size::type>::value, 1314 | std::false_type, 1315 | std::true_type 1316 | >::type(); 1317 | 1318 | return detail::tuple_cat_get_impl(recurse, std::forward(t), std::forward(ts)...); 1319 | } 1320 | 1321 | 1322 | template 1323 | TUPLE_UTILITY_ANNOTATION 1324 | auto tuple_cat_apply_impl(index_sequence, Function&& f, Tuples&&... ts) 1325 | -> decltype( 1326 | std::forward(f)(detail::tuple_cat_get(std::forward(ts)...)...) 1327 | ) 1328 | { 1329 | return std::forward(f)(detail::tuple_cat_get(std::forward(ts)...)...); 1330 | } 1331 | 1332 | 1333 | template 1334 | struct sum 1335 | : std::integral_constant< 1336 | size_t, 1337 | Size + sum::value 1338 | > 1339 | {}; 1340 | 1341 | 1342 | template struct sum : std::integral_constant {}; 1343 | 1344 | 1345 | } // end detail 1346 | 1347 | 1348 | template 1349 | TUPLE_UTILITY_ANNOTATION 1350 | auto tuple_cat_apply(Function&& f, Tuples&&... ts) 1351 | -> decltype( 1352 | detail::tuple_cat_apply_impl( 1353 | detail::make_index_sequence< 1354 | detail::sum< 1355 | 0u, 1356 | std::tuple_size::type>::value... 1357 | >::value 1358 | >(), 1359 | std::forward(f), 1360 | std::forward(ts)... 1361 | ) 1362 | ) 1363 | { 1364 | const size_t N = detail::sum<0u, std::tuple_size::type>::value...>::value; 1365 | return detail::tuple_cat_apply_impl(detail::make_index_sequence(), std::forward(f), std::forward(ts)...); 1366 | } 1367 | 1368 | 1369 | namespace detail 1370 | { 1371 | 1372 | 1373 | template 1374 | TUPLE_UTILITY_ANNOTATION 1375 | auto tuple_apply_impl(Function f, Tuple&& t, index_sequence) 1376 | -> decltype( 1377 | f(TUPLE_UTILITY_NAMESPACE::get(std::forward(t))...) 1378 | ) 1379 | { 1380 | return f(TUPLE_UTILITY_NAMESPACE::get(std::forward(t))...); 1381 | } 1382 | 1383 | 1384 | } // end detail 1385 | 1386 | 1387 | template 1388 | TUPLE_UTILITY_ANNOTATION 1389 | auto tuple_apply(Function&& f, Tuple&& t) 1390 | -> decltype( 1391 | tuple_cat_apply(std::forward(f), std::forward(t)) 1392 | ) 1393 | { 1394 | return TUPLE_UTILITY_NAMESPACE::tuple_cat_apply(std::forward(f), std::forward(t)); 1395 | } 1396 | 1397 | 1398 | template 1399 | TUPLE_UTILITY_ANNOTATION 1400 | auto tuple_zip(Tuples&&... tuples) 1401 | -> decltype( 1402 | TUPLE_UTILITY_NAMESPACE::tuple_map(detail::std_tuple_factory{}, std::forward(tuples)...) 1403 | ) 1404 | { 1405 | return TUPLE_UTILITY_NAMESPACE::tuple_map(detail::std_tuple_factory{}, std::forward(tuples)...); 1406 | } 1407 | 1408 | 1409 | namespace detail 1410 | { 1411 | 1412 | 1413 | // concatenate two index_sequences 1414 | template struct index_sequence_cat_impl; 1415 | 1416 | 1417 | template 1418 | struct index_sequence_cat_impl, index_sequence> 1419 | { 1420 | using type = index_sequence; 1421 | }; 1422 | 1423 | template 1424 | using index_sequence_cat = typename index_sequence_cat_impl::type; 1425 | 1426 | 1427 | template class MetaFunction, class Indices> 1428 | struct filter_index_sequence_impl; 1429 | 1430 | 1431 | // an empty sequence filters to the empty sequence 1432 | template class MetaFunction> 1433 | struct filter_index_sequence_impl> 1434 | { 1435 | using type = index_sequence<>; 1436 | }; 1437 | 1438 | template class MetaFunction, size_t Index0, size_t... Indices> 1439 | struct filter_index_sequence_impl> 1440 | { 1441 | // recurse and filter the rest of the indices 1442 | using rest = typename filter_index_sequence_impl>::type; 1443 | 1444 | // concatenate Index0 with rest if Index0 passes the filter 1445 | // else, just return rest 1446 | using type = typename std::conditional< 1447 | MetaFunction::value, 1448 | index_sequence_cat< 1449 | index_sequence, 1450 | rest 1451 | >, 1452 | rest 1453 | >::type; 1454 | }; 1455 | 1456 | 1457 | template class MetaFunction, class Indices> 1458 | using filter_index_sequence = typename filter_index_sequence_impl::type; 1459 | 1460 | 1461 | template class MetaFunction, class Tuple> 1462 | struct index_filter 1463 | { 1464 | using traits = tuple_traits; 1465 | 1466 | template 1467 | using filter = MetaFunction>; 1468 | }; 1469 | 1470 | 1471 | template class MetaFunction, class Tuple> 1472 | using make_filtered_indices_for_tuple = 1473 | filter_index_sequence< 1474 | index_filter::template filter, 1475 | make_index_sequence::size> 1476 | >; 1477 | 1478 | 1479 | } // end detail 1480 | 1481 | 1482 | // XXX nvcc 7.0 has trouble with this template template parameter 1483 | //template class MetaFunction, class Tuple, class Function> 1484 | //TUPLE_UTILITY_ANNOTATION 1485 | //auto tuple_filter_invoke(Tuple&& t, Function f) 1486 | // -> decltype( 1487 | // detail::tuple_apply_impl( 1488 | // f, 1489 | // std::forward(t), 1490 | // detail::make_filtered_indices_for_tuple::type>{} 1491 | // ) 1492 | // ) 1493 | //{ 1494 | // using filtered_indices = detail::make_filtered_indices_for_tuple::type>; 1495 | // 1496 | // return detail::tuple_apply_impl(f, std::forward(t), filtered_indices{}); 1497 | //} 1498 | template class MetaFunction, class Tuple, class Function, class Indices = detail::make_filtered_indices_for_tuple::type>> 1499 | TUPLE_UTILITY_ANNOTATION 1500 | auto tuple_filter_invoke(Tuple&& t, Function f) 1501 | -> decltype( 1502 | detail::tuple_apply_impl( 1503 | f, 1504 | std::forward(t), 1505 | Indices{} 1506 | ) 1507 | ) 1508 | { 1509 | return detail::tuple_apply_impl(f, std::forward(t), Indices{}); 1510 | } 1511 | 1512 | 1513 | template class MetaFunction, class Tuple> 1514 | TUPLE_UTILITY_ANNOTATION 1515 | auto tuple_filter(Tuple&& t) 1516 | -> decltype( 1517 | TUPLE_UTILITY_NAMESPACE::tuple_filter_invoke(std::forward(t), detail::std_tuple_factory{}) 1518 | ) 1519 | { 1520 | return TUPLE_UTILITY_NAMESPACE::tuple_filter_invoke(std::forward(t), detail::std_tuple_factory{}); 1521 | } 1522 | 1523 | 1524 | namespace detail 1525 | { 1526 | 1527 | 1528 | template 1529 | TUPLE_UTILITY_ANNOTATION 1530 | T&& identity(T&& x) 1531 | { 1532 | return std::forward(x); 1533 | } 1534 | 1535 | 1536 | template 1537 | TUPLE_UTILITY_ANNOTATION 1538 | auto tuple_repeat_invoke_impl(T&& x, Function f, index_sequence) 1539 | -> decltype( 1540 | f(identity(x)...) 1541 | ) 1542 | { 1543 | return f(identity(x)...); 1544 | } 1545 | 1546 | 1547 | } // end detail 1548 | 1549 | 1550 | template 1551 | TUPLE_UTILITY_ANNOTATION 1552 | auto tuple_repeat_invoke(T&& x, Function f) 1553 | -> decltype( 1554 | detail::tuple_repeat_invoke_impl(std::forward(x), f, detail::make_index_sequence()) 1555 | ) 1556 | { 1557 | return detail::tuple_repeat_invoke_impl(std::forward(x), f, detail::make_index_sequence()); 1558 | } 1559 | 1560 | 1561 | template 1562 | TUPLE_UTILITY_ANNOTATION 1563 | auto tuple_repeat(const T& x) 1564 | -> decltype( 1565 | tuple_repeat_invoke(x, detail::std_tuple_factory{}) 1566 | ) 1567 | { 1568 | return tuple_repeat_invoke(x, detail::std_tuple_factory{}); 1569 | } 1570 | 1571 | 1572 | namespace detail 1573 | { 1574 | 1575 | 1576 | template 1577 | TUPLE_UTILITY_ANNOTATION 1578 | auto tuple_gather_invoke_impl(Tuple&& t, Function f) 1579 | -> decltype( 1580 | f(TUPLE_UTILITY_NAMESPACE::get(std::forward(t))...) 1581 | ) 1582 | { 1583 | return f(TUPLE_UTILITY_NAMESPACE::get(std::forward(t))...); 1584 | } 1585 | 1586 | 1587 | } // end detail 1588 | 1589 | 1590 | template 1591 | TUPLE_UTILITY_ANNOTATION 1592 | auto tuple_gather_invoke(Tuple&& t, Function f) 1593 | -> decltype( 1594 | detail::tuple_gather_invoke_impl(std::forward(t), f) 1595 | ) 1596 | { 1597 | return detail::tuple_gather_invoke_impl(std::forward(t), f); 1598 | } 1599 | 1600 | 1601 | template 1602 | TUPLE_UTILITY_ANNOTATION 1603 | auto tuple_gather(Tuple&& t) 1604 | -> decltype( 1605 | tuple_gather_invoke(std::forward(t), detail::std_tuple_factory{}) 1606 | ) 1607 | { 1608 | return tuple_gather_invoke(std::forward(t), detail::std_tuple_factory{}); 1609 | } 1610 | 1611 | 1612 | TUPLE_UTILITY_NAMESPACE_CLOSE_BRACE 1613 | 1614 | 1615 | #ifdef TUPLE_UTILITY_ANNOTATION_NEEDS_UNDEF 1616 | #undef TUPLE_UTILITY_ANNOTATION 1617 | #undef TUPLE_UTILITY_ANNOTATION_NEEDS_UNDEF 1618 | #endif 1619 | 1620 | #ifdef TUPLE_UTILITY_NAMESPACE_NEEDS_UNDEF 1621 | #undef TUPLE_UTILITY_NAMESPACE 1622 | #undef TUPLE_UTILITY_NAMESPACE_OPEN_BRACE 1623 | #undef TUPLE_UTILITY_NAMESPACE_CLOSE_BRACE 1624 | #undef TUPLE_UTILITY_NAMESPACE_NEEDS_UNDEF 1625 | #endif 1626 | 1627 | #undef TUPLE_UTILITY_REQUIRES 1628 | 1629 | --------------------------------------------------------------------------------