Created
May 30, 2010 16:23
-
-
Save niha/419140 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// せつめい | |
// 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