I found this on the Internet:
#include <utility>
#include <type_traits>
namespace details {
template< typename F, typename Tuple, bool Done, int Total, int... N > struct call_impl {
static void call( F f, Tuple && t ) {
call_impl< F, Tuple, Total == 1 + sizeof...( N ), Total, N..., sizeof...( N ) >::call( f, std::forward< Tuple >( t ) );
}
};
template< typename F, typename Tuple, int Total, int... N > struct call_impl< F, Tuple, true, Total, N... > {
static void call( F f, Tuple && t ) {
f( std::get< N >( std::forward< Tuple >( t ) )... );
}
};
} // namespace details.
template< typename F, typename Tuple > void call( F f, Tuple &&t ) {
//typedef typename std::decay< Tuple >::type ttype;
using ttype = typename std::decay< Tuple >::type;
details::call_impl< F, Tuple, 0 == std::tuple_size< ttype >::value, std::tuple_size< ttype >::value >::call( f, std::forward< Tuple >( t ) );
}
Used to unpack a std::tuple
on the arguments of a function call.
The idea is to postpone a function call until necessary, storing the past arguments in a std::tuple
and being able to recover them at a later time.
Unfortunately, the template
works only with void
functions. I'm trying to adapt it to be able to use it in functions with any type of return, but I'm not getting it:
error: no matching function for call to 'call (int (&) (int), std :: tuple < int > &)'
...
error: invalid use of incomplete type 'class std :: result_of < int (*) (int) >'
#include <tuple>
#include <functional>
#include <type_traits>
#include <iostream>
namespace details {
template< typename RET, typename F, typename Tuple, bool Done, int Total, int... N > struct call_impl {
static RET call( F f, Tuple && t ) {
return call_impl< RET, F, Tuple, Total == 1 + sizeof...( N ), Total, N..., sizeof...( N ) >::call( f, std::forward< Tuple >( t ) );
}
};
template< typename RET, typename F, typename Tuple, int Total, int... N > struct call_impl< RET, F, Tuple, true, Total, N... > {
static RET call( F f, Tuple && t ) {
return f( std::get< N >( std::forward< Tuple >( t ) )... );
}
};
} // namespace details.
template< typename F, typename Tuple, typename RET = typename std::result_of< F >::type > RET call( F f, Tuple &&t ) {
//typedef typename std::decay< Tuple >::type ttype;
using ttype = typename std::decay< Tuple >::type;
return details::call_impl< RET, F, Tuple, 0 == std::tuple_size< ttype >::value, std::tuple_size< ttype >::value >::call( f, std::forward< Tuple >( t ) );
}
int dummy( int );
int main( ) {
auto tp = std::make_tuple( 10 );
auto ret = call( dummy, tp );
std::cout << "Retorno: " << ret << std::endl;
return 0;
}
int dummy( int v ) {
std::cout << "dummy( " << v << " )\n";
return v + 1;
}
Note: compiled with g++ -Wall -Wextra -std=c++11 -pedantic