あなたが望むことを直接行う方法はないと思いますが、コードのいくつかの場所で使用する C++11 の手法を次に示します。基本的な考え方は、私が呼び出したテンプレート関数を使用してcall_on_tuple
、関数の引数f
とさらに引数のタプルを取り、タプルを展開して、展開された引数のリストで関数を呼び出すことです。
template <typename Fun, typename... Args, unsigned... Is>
typename std::result_of<Fun(Args...)>::type
call_on_tuple(Fun&& f, std::tuple<Args...>&& tup, indices<Is...>)
{ return f(std::get<Is>(tup)...); }
したがって、アイデアは、呼び出す代わりに
length(arguments());
あなたは電話するでしょう
call_on_tuple(length,arguments());
これは、が変更されていることを前提としてarguments()
いるため、 a が返されますstd::tuple<int,int,int>
(これは基本的に、引用した質問からのアイデアです)。
ここで難しいのは、Is...
引数 pack を取得する方法です。これは0,1,2,...
、タプルの要素に番号を付けるために使用される整数のパックです。
0,1,2
常に 3 つの引数を使用することが確実な場合は、文字通り使用できますが、任意の n 項関数でこれを機能させることが目的である場合は、他の投稿で説明されている別のトリックが必要です。この投稿への回答。
引数の数を整数sizeof...(Args)
のリスト0,1,...,sizeof...(Args)
に変換するのはトリックです:
このトリックと の実装をcall_on_tuple
名前空間に入れdetail
ます。
namespace detail {
template <unsigned... Is>
struct indices
{ };
template <unsigned N, unsigned... Is>
struct index_maker : index_maker<N-1,N-1,Is...>
{ };
template <unsigned... Is>
struct index_maker<0,Is...>
{ typedef indices<Is...> type; };
template <typename Fun, typename... Args, unsigned... Is>
typename std::enable_if<!std::is_void<typename std::result_of<Fun(Args...)>::type>::value,
typename std::result_of<Fun(Args...)>::type>::type
call_on_tuple(Fun&& f, std::tuple<Args...>&& tup, indices<Is...>)
{ return f(std::get<Is>(tup)...); }
}
現在、実際の関数call_on_tuple
は次のようにグローバル名前空間で定義されています。
template <typename Fun, typename... Args>
typename std::enable_if<!std::is_void<typename std::result_of<Fun(Args...)>::type>::value,
typename std::result_of<Fun(Args...)>::type>::type
call_on_tuple(Fun&& f, std::tuple<Args...>&& tup)
{
using std::tuple;
using std::forward;
using detail::index_maker;
return detail::call_on_tuple
(forward<Fun>(f),forward<tuple<Args...>>(tup),typename index_maker<sizeof...(Args)>::type());
}
基本的にdetail::index_maker
、増加する整数のリストを生成するために呼び出し、それを呼び出しますdetail::call_on_tuple
。
その結果、次のことができます。
int length(int x, int y, int z)
{ return x + y + z; }
std::tuple<int,int,int> arguments()
{ return std::tuple<int,int,int> { 1 , 2 , 3 }; }
int main()
{
std::cout << call_on_tuple(length,arguments()) << std::endl;
return 0;
}
これは、必要なものに十分近いことを願っています。
ノート。また、これが実際に値を返すenable_if
関数でのみ使用されるようにするために、 も追加しました。f
を返す関数の別の実装を簡単に作成できますvoid
。
途中で質問を閉じてしまい、重ねて申し訳ありません。
PS。これをテストするには、次の include ステートメントを追加する必要があります。
#include <tuple>
#include <type_traits>
#include <iostream>