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