keyongtech


  keyongtech > cpp > 03/2009

 #1  
03-12-09, 09:05 AM
metarox
Hello,

I'd like to know what is the way to unpack a tuple into function call
arguments. I've seen in an old article for the standard that a
function called std::apply( Func, tuple ) did that, but it is nowhere
to be found in the gcc 4.3.2 C++0x implementation that I currently
experiment with.

void func( int a, int b, int c)
{

}


std::tuple <int, int, int> myargs(1, 2, 3);

would call something like this unwrapping the tuple into each of the
individual function arguments. I could write this wrapper myself, but
maybe it already exists in some form.

func( get<0>(myargs), get<1>(myargs), get<2>(myargs) );

I'm looking for the generic solution using variadic templates and
tuple manipulation if someone knows.

Thanks
 #2  
03-12-09, 02:06 PM
Anthony Williams
metarox <legault.david> writes:

[..]
> std::tuple <int, int, int> myargs(1, 2, 3);
>
> would call something like this unwrapping the tuple into each of the
> individual function arguments. I could write this wrapper myself, but
> maybe it already exists in some form.
>
> func( get<0>(myargs), get<1>(myargs), get<2>(myargs) );
>
> I'm looking for the generic solution using variadic templates and
> tuple manipulation if someone knows.


I am not aware of an easy technique other than to write your own apply
function, which isn't easy --- you have to recursively unpack the tuple
until you have unpacked all the elements into separate arguments, which
you can pass to your target function.

Anthony
 #3  
03-12-09, 06:07 PM
ymett
On Mar 12, 11:46 am, metarox <legaultda> wrote:
> Hello,
>
> I'd like to know what is the way to unpack a tuple into function call
> arguments.


Try the following:

template<bool enable, class T> struct enable_if {};
template<class T> struct enable_if<true, T> { typedef T type; };

template<size_t argIndex, size_t argSize, class... Args, class...
Unpacked, class F>
inline typename enable_if<(argIndex == argSize),
void>::type apply_args_impl(const std::tuple<Args...>&& t, F f,
Unpacked&&... u)
{
f(u...); // I think this should be f(std::forward<Unpacked>
(u)...);
}
template<size_t argIndex, size_t argSize, class... Args, class...
Unpacked, class F>
inline typename enable_if<(argIndex < argSize),
void>::type apply_args_impl(const std::tuple<Args...>&& t, F f,
Unpacked&&... u)
{
apply_args_impl<argIndex + 1, argSize>(t, f, u...,
std::get<argIndex>(t));
}

template<class... Args, class F>
inline void apply_args(const std::tuple<Args...>&& t, F f)
{
apply_args_impl<0, sizeof...(Args)>(t, f);
}


There are other possibilities, such as creating a list of indices.

Yechezkel Mett
 #4  
03-12-09, 06:07 PM
Matti Rintala
Anthony Williams wrote:
> metarox <legault.david> writes:
>> I'd like to know what is the way to unpack a tuple into function call
>> arguments. I've seen in an old article for the standard that a
>> function called std::apply( Func, tuple ) did that, but it is nowhere
>> to be found in the gcc 4.3.2 C++0x implementation that I currently
>> experiment with.
>>
>> I'm looking for the generic solution using variadic templates and
>> tuple manipulation if someone knows.

>
> I am not aware of an easy technique other than to write your own apply
> function, which isn't easy --- you have to recursively unpack the tuple
> until you have unpacked all the elements into separate arguments, which
> you can pass to your target function.


Here's one I managed to write using variadic templates in C++0x. This
compiles and works in gcc 4.3.2. It doesn't even require that function's
parameter types and tuple's types are exactly the same:



#include <tuple>

// Recursive case, unpack Nth argument
template<unsigned int N>
struct Apply_aux
{
template<typename... ArgsF, typename... ArgsT, typename... Args>
static void apply(void (*f)(ArgsF...), std::tuple<ArgsT...> const& t,
Args... args)
{
Apply_aux<N-1>::apply(f, t, std::get<N-1>(t), args...);
}
};

// Terminal case, call the function with unpacked arguments
template<>
struct Apply_aux<0>
{
template<typename... ArgsF, typename... ArgsT, typename... Args>
static void apply(void (*f)(ArgsF...), std::tuple<ArgsT...> const&,
Args... args)
{
f(args...);
}
};

// Actual apply function
template<typename... ArgsF, typename... ArgsT>
void apply(void (*f)(ArgsF...), std::tuple<ArgsT...> const& t)
{
Apply_aux<sizeof...(ArgsT)>::apply(f, t);
}

// Testing
#include <string>
#include <iostream>

void f(int p1, double p2, std::string p3)
{
std::cout << "int=" << p1 << ", double=" << p2 << ", string=" << p3
<< std::endl;
}

void g(int p1, std::string p2)
{
std::cout << "int=" << p1 << ", string=" << p2 << std::endl;
}

int main()
{
std::tuple<int, double, char const*> tup(1, 2.0, "xxx");
apply(&f, tup);
apply(&g, std::make_tuple(4, "yyy"));
}



> g++ -std=c++0x tupleunpack.cc
> ./a.out

int=1, double=2, string=xxx
int=4, string=yyy
 #5  
03-12-09, 07:06 PM
Boris Rasin
On Mar 12, 11:46 am, metarox <legaultda> wrote:

[..]
> std::tuple <int, int, int> myargs(1, 2, 3);
>
> would call something like this unwrapping the tuple into each of the
> individual function arguments. I could write this wrapper myself, but
> maybe it already exists in some form.
>
> func( get<0>(myargs), get<1>(myargs), get<2>(myargs) );
>
> I'm looking for the generic solution using variadic templates and
> tuple manipulation if someone knows.


Here is the code posted previously in this group.
One has to marvel at unsurpassed clarity :-)

#include <cstddef>
#include <tuple>
#include <utility>

template<std::size_t...> struct index_tuple{};

template<std::size_t I, typename IndexTuple, typename... Types>
struct make_indices_impl;

template<std::size_t I, std::size_t... Indices, typename T,
typename... Types>
struct make_indices_impl<I, index_tuple<Indices...>, T, Types...>
{
typedef typename make_indices_impl<I + 1, index_tuple<Indices...,
I>, Types...>::type type;
};

template<std::size_t I, std::size_t... Indices>
struct make_indices_impl<I, index_tuple<Indices...> >
{
typedef index_tuple<Indices...> type;
};

template<typename... Types>
struct make_indices : make_indices_impl<0, index_tuple<>, Types...>
{};

template <class... Args>
void some_func(Args&&...){}

template <class... Args>
class store
{
public:
store(Args... args) : members(args...) {}
void forward()
{
typedef typename make_indices<Args...>::type Indices;
return forward0(Indices(), members);
}
private:
template <std::size_t... Indices>
static void forward0(index_tuple<Indices...>,
std::tuple<Args...>&&args)
{
some_func(std::forward<Args>(std::get<Indices>(arg s))...);
}
std::tuple<Args...> members;
};

int main()
{
store<int, bool, double>(42, true, 1.2).forward();
}
 #6  
03-12-09, 09:00 PM
metarox
Thanks to all of you

Hopefully they add it in the <utility> header or somewhere so we don't
have to ask too often!
Similar Threads
Cython + tuple unpacking

Hello, The following code will crash with a segfault when compiled using cython (v0.11) def func(): for (a, b) ,c ,d in zip(zip(range(3), range(3)), range(3),...

Passing a tuple to a function as multiple arguments

Hello, Let's say I have a function with a variable number of arguments(please ignore syntax errors): def myfunc(a,b,c,d,...): and I have a tuple whose contents I want to...

Unpacking sequences and keywords in one function call

Stupid question #983098403: I can't seem to pass an unpacked sequence and keyword arguments to a function at the same time. What am I doing wrong? def f(*args, **kw): for a...

problems when unpacking tuple ...

Dear all, Maybe I stared on the monitor for too long, because I cannot find the bug ... My script "transition_filter.py" starts with the following lines: import sys for...

Tuple Unpacking in raise

Hello All, Is this a bug? Why is this tuple getting unpacked by raise? Am I missing some subtle logic? Why does print not work the same way as raise? Both are statements....


All times are GMT. The time now is 01:48 PM. | Privacy Policy