질문에 영감을 받아 필자는 자신 만의 프리 바인딩을 처음부터 작성했습니다. 그것은 다른 모든 사람들과 꽤 비슷하게 보였지만, 원래는 약속합니다 :) - 수렴 진화라고 부릅니다.
그러나 약간 다른 풍미가 있습니다. 한 가지 방법은 생성자에게 전달하지만, std::decay
을 사용하는 것을 선호 할 수 있습니다 (어떤면에서는 더 의미가 있지만 어디서나 std::ref
을 쓰는 것을 좋아하지 않습니다). 다른 하나는 중첩 된 prebinds에 대한 지원을 추가 했으므로 prebind(foo, prebind(GetRandomNumber))()
은 prebind(foo)(GetRandomNumber())
과 같습니다.
#include <tuple>
#include <type_traits>
using namespace std;
struct pb_tag {}; //use inheritance to mark prebinder structs
//result_of_t will be defined by default in c++1y
template<typename T > using result_of_t = typename result_of<T>::type;
template<typename T> using is_prebinder = is_base_of<pb_tag, typename remove_reference<T>::type >;
//ugly sequence generators for something different
template<int N, int ...S> struct seq : seq<N-1, N, S...> {};
template<int ...S> struct seq<0, S...> {typedef seq type;};
//these three functions are only for nested prebind. they map
//T t -> T t and Prebind<f, T...> -> f(T...)
template<typename T>
auto dispatchee(T&& t, false_type) -> decltype(forward<T>(t)){
return forward<T>(t);
}
template<typename T>
auto dispatchee(T&& t, true_type) -> decltype(t())
{
return t();
}
template<typename T>
auto expand(T&& t) -> decltype(dispatchee(forward<T>(t), is_prebinder<T>()))
{
return dispatchee(forward<T>(t), is_prebinder<T>());
}
template<typename T> using expand_type = decltype(expand(declval<T>()));
//the functor which holds the closure in a tuple
template<typename f, typename ...ltypes>
struct prebinder : public pb_tag
{
tuple<f, ltypes...> closure;
typedef typename seq<sizeof...(ltypes)>::type sequence;
prebinder(f F, ltypes... largs) : closure(F, largs...) {}
template<int ...S, typename ...rtypes>
result_of_t<f(expand_type<ltypes>..., rtypes...)>
apply(seq<0, S...>, rtypes&& ... rargs){
return (get<0>(closure))(expand(get<S>(closure))... , forward<rtypes>(rargs)...);
}
template<typename ...rtypes>
result_of_t<f(expand_type<ltypes>..., rtypes...)>
operator() (rtypes&& ... rargs){
return apply(sequence(), forward<rtypes>(rargs)...);
}
};
template<typename f, typename ...ltypes>
prebinder<f, ltypes...> prebind(f&& F, ltypes&&... largs)
{
return prebinder<f, ltypes...>(forward<f>(F), forward<ltypes>(largs)...);
}
쉽게 이전 바인딩으로 변경할 수 있습니다.
사용 보인다 같은 :
int g(int a){ return 1 + a; }
int h(){ return 1; }
int i(int a, int b, int c, int d){
return 1 + a + b + c + d;
}
int main()
{
//completely bound
auto a = prebind(g, 1);
cout << a() << endl;
//nested bind by reference
auto b = prebind(g, a);
cout << b() << endl;
get<1>(a.closure) = 2;
cout << b() << endl;
//bind to prebinder
auto c = prebind(b);
cout << c() << endl;
//nested bind of temp to temp
auto d = prebind(prebind(g), prebind(h));
cout << d() << endl;
//and the one you wanted orginally
auto e = prebind(i, 1, 1, 1);
cout << e(1) << endl;
return 0;
}
거기에'표준 : bind1st'는하지만 추천하지 않습니다. – Gasim
구현할 수 없다는 두려움이 있습니다. – Paranaix
이것은 실제로 작성하기가 쉽지 않습니다. 바운드 인수를'튜플 (tuple) '에 저장하고, 가변 수의 매개 변수를'operator()'에 받아들이고, 인덱스를 통해 튜플을 압축 해제 한 다음 실제 인수를 추가하면됩니다. – Xeo