1 // 2 // Copyright 2013 Francisco Jerez 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 // OTHER DEALINGS IN THE SOFTWARE. 21 // 22 23 #ifndef CLOVER_UTIL_TUPLE_HPP 24 #define CLOVER_UTIL_TUPLE_HPP 25 26 #include <tuple> 27 28 namespace clover { 29 namespace tuple { 30 /// 31 /// Static sequence of integers. 32 /// 33 template<int... Is> 34 struct integral_sequence; 35 36 /// 37 /// Static sequence containing all integers from 0 to N-1. 38 /// 39 template<int N, int... Is> 40 struct enumerate { 41 typedef typename enumerate<N-1, N-1, Is...>::type 42 type; 43 }; 44 45 template<int... Is> 46 struct enumerate<0, Is...> { 47 typedef integral_sequence<Is...> type; 48 }; 49 50 namespace detail { 51 template<typename F, typename T, 52 typename E = typename enumerate<std::tuple_size< 53 typename std::remove_reference<T>::type>::value 54 >::type> 55 struct _apply; 56 57 template<typename F, typename T, int... Is> 58 struct _apply<F, T, integral_sequence<Is...>> { 59 typedef typename std::remove_reference<F>::type func_type; 60 typedef decltype( 61 std::declval<func_type>()(std::get<Is>(std::declval<T &&>())...) 62 ) value_type; 63 64 static value_type evalclover::tuple::detail::_apply65 eval(F &&f, T &&t) { 66 return f(std::get<Is>(std::forward<T>(t))...); 67 } 68 }; 69 } 70 71 /// 72 /// Evaluate function \a f with the elements of tuple \a t 73 /// expanded as arguments. 74 /// 75 template<typename F, typename T> 76 typename detail::_apply<F, T>::value_type apply(F && f,T && t)77 apply(F &&f, T &&t) { 78 return detail::_apply<F, T>::eval(std::forward<F>(f), 79 std::forward<T>(t)); 80 } 81 82 namespace detail { 83 template<typename F, typename T, 84 typename E = typename enumerate<std::tuple_size< 85 typename std::remove_reference<T>::type>::value 86 >::type> 87 struct _map; 88 89 template<typename F, typename T, int... Is> 90 struct _map<F, T, integral_sequence<Is...>> { 91 typedef typename std::remove_reference<F>::type func_type; 92 typedef std::tuple< 93 decltype(std::declval<func_type>()( 94 std::get<Is>(std::declval<T &&>())))... 95 > value_type; 96 97 static value_type evalclover::tuple::detail::_map98 eval(F &&f, T &&t) { 99 return value_type(f(std::get<Is>(std::forward<T>(t)))...); 100 } 101 }; 102 } 103 104 /// 105 /// Evaluate function \a f on each element of the tuple \a t and 106 /// return the resulting values as a new tuple. 107 /// 108 template<typename F, typename T> 109 typename detail::_map<F, T>::value_type map(F && f,T && t)110 map(F &&f, T &&t) { 111 return detail::_map<F, T>::eval(std::forward<F>(f), 112 std::forward<T>(t)); 113 } 114 } 115 } 116 117 #endif 118