c++ - simplified/alternative version of std::bind()/ tr1::bind() -
i using c++03. don't have std::bind()
. compiler ported g++, tr1::bind()
not ported.
i want bind function having 3 arguments. std::bind1st()
, std::bind2nd()
won't work. in addition, neither std::bind1st()
or std::bind2nd()
deal reference type of argument.
thus writing own version of bind1st()
follows, including sample invocation of bind1st()
:
#include <iostream> // c++03 not define nullptr #ifndef nullptr #define nullptr ((void*)0) #endif namespace mybinder { void *binder3argtobind; void *binder3functortocall; template <int uniqueid, typename user_func_type, typename bound_func_type, typename returntype, typename t1, typename t2, typename t3> class binder3 // 3 arguments binder { public: static void setparams(void **parg1, void **pfunc) { *parg1 = binder3argtobind; *pfunc = binder3functortocall; binder3argtobind = nullptr; } static returntype f_bound1st_common(t2 &arg2, t3 &arg3) { static void *arg1; static void *func; returntype ignored; if (binder3argtobind != nullptr) { setparams(&arg1, &func); return ignored; } return ((user_func_type)func)(*(t1*)arg1, arg2, arg3); } static returntype f_bound1st(t2 arg2, t3 arg3) { return f_bound1st_common(arg2, arg3); } static returntype f_bound1st(t2 &arg2, t3 arg3) { return f_bound1st_common(arg2, arg3); } static returntype f_bound1st(t2 arg2, t3 &arg3) { return f_bound1st_common(arg2, arg3); } static returntype f_bound1st(t2 &arg2, t3 &arg3) { return f_bound1st_common(arg2, arg3); } static bound_func_type bind1st(user_func_type f, t1 &arg1) { binder3functortocall = (void*)f; binder3argtobind = (void*) &arg1; (*(void (*)())f_bound1st_common)(); return f_bound1st; } }; } using namespace std; using namespace mybinder; typedef short (*func)(int const, int&); // test function short f(int &a, int const b, int &c) { int val = 100 * + 10 * b + c; a+=100; c+=10; return val; } int main(void) { int a[2] = {2, 5}; (int i=0; i<2; ++i) { // bind function f a[i] 1st argument. func ff = binder3<__counter__, short(*)(int&, int const, int&), short(*)(int const,int&), short, int, int const, int>::bind1st(f, a[i]); int k; int m; (m=0; m<2; ++m) { k = 1-m; cout << "before: a[i]=" << a[i] << endl; cout << "before: m=" << m << endl; cout << "before: k=" << k << endl; cout << ff(m, k) << endl; cout << "after: a[i]=" << a[i] << endl; cout << "after: m=" << m << endl; cout << "after: k=" << k << endl << endl; } } }
and execution results:
before: a[i]=2 before: m=0 before: k=1 201 after: a[i]=102 after: m=0 after: k=11 before: a[i]=102 before: m=1 before: k=0 10210 after: a[i]=202 after: m=1 after: k=10 before: a[i]=5 before: m=0 before: k=1 501 after: a[i]=105 after: m=0 after: k=11 before: a[i]=105 before: m=1 before: k=0 10510 after: a[i]=205 after: m=1 after: k=10
it works fine on pc, emulation. however, raises several problems in embedded compiler:
(1) embedded compiler not support __counter__
(2) invoke of bind1st()
tedious, , redundant types in template may problem, if not synchronized.
thus question:
(1) how implement __counter__
in regular g++/gcc? or, in fact, need unique number/identifier counter.
(2) there anyway can derive argument types , return types function pointer type?
(3) if question (2) can done, can derive bare types reference type? example, can derive int
int &
? please note source type can int
or int &
, , need derive resulting type int
in both cases. please note it's c++03, not c++11 or higher.
(4) other suggestions? perhaps can provide simpler or better implementation?
the goal of q.2 , q.3 make template call shorter, func ff = binder3<__counter__, short(*)(int&, int const, int&)>::bind1st(f, a[i]);
. other types can derived first function pointer type. in addition, don't have write 4 overloads.
---update---
since implementation uses pointers binding argument , function, may have potential bug/design flaw:
if caller changes value of binding variable after calls binder3<...>::bind1st()
, before use(call) of bound function, effective value value after change, not before change! can live it, careful coding. , use(call) bound function right after bind1st() (without command in-between).
ideas improve problem welcome.
--update--
currently, use of __count__
contains bug: since __count__
not globally unique (restart count 0 each compilation of .cpp file), bounding variable may overwritten, if not used promptly. if can program-wide global unique number replace __count__
, above implementation should enough (except tedious stuff).
Comments
Post a Comment