Skip to content

Instantly share code, notes, and snippets.

@niha
Created May 30, 2010 16:23
Show Gist options
  • Save niha/419140 to your computer and use it in GitHub Desktop.
Save niha/419140 to your computer and use it in GitHub Desktop.
// せつめい
// C++ 0x で関数と引数を pack したタプルから関数適用を行う apply を実装した。
// apply を実装するには tuple の値を variadic arguments に変換する必要がある。
// 束縛済み引数の数で特殊化してやる。0 なら関数を呼ぶ。 1 以上の場合は値を一つずつ積んでいく。
// 返値型を求めようと auto impl(...) -> decltype(impl(...)) のようなコードを書くのは正しくない。
// impl の宣言に impl を利用することは当然できない。それが実際には異なるパラメータを持つ関数テンプレートであったとしても…
// declval を使って fun の返値を求めることで解決する。
#include <tuple>
#include <type_traits>
using namespace std;
template <unsigned int N>
struct apply_impl {
template <typename Fun, typename ...Args, typename ...BoundArgs>
static auto impl(Fun fun, tuple<Args...> t, BoundArgs... args) -> decltype(fun(declval<Args>()...)) {
return apply_impl<N-1>::impl(fun, t, std::get<N-1>(t), args...);
}
};
template <>
struct apply_impl<0> {
template <typename Fun, typename ...Args>
static auto impl(Fun fun, tuple<Args...> t, Args... args) -> decltype(fun(args...)) {
return fun(args...);
}
};
template <typename Fun, typename ...Args>
auto apply(Fun fun, tuple<Args...> t) -> decltype(fun(declval<Args>()...)) {
return apply_impl<sizeof...(Args)>::impl(fun, t);
}
/////////////////////////////////////////
#include <iostream>
#include <functional>
using namespace std::placeholders;
int f(){
return 0;
}
int g(int i){
return i;
}
int h(int i, int j){
return i + j;
}
struct F {
void operator()(const char* hello, const char* world){
cout << hello << world << endl;
}
};
int main(){
cout << apply(f, make_tuple()) << endl; // no parameter function
cout << apply(g, make_tuple(1)) << endl; // unary
cout << apply(h, make_tuple(1, 2)) << endl; // binary
apply(F(), make_tuple("hoge", "huga")); // functor
cout << apply([](int i){ return i; }, make_tuple(1)) << endl; // lambda
function<double (double, double, double)> fun = [](double x, double y, double z){ return x + y + z; };
cout << apply(fun, make_tuple(1, 2, 3)) << endl; // std::function
cout << apply(bind(h, 1, _1), make_tuple(2)) << endl; // bound functor
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment