我正在使用C ++ 03。因此我没有std::bind()
。我的编译器是从g ++移植的,但tr1::bind()
没有被移植。
我想绑定一个有3个参数的函数。因此std::bind1st()
和std::bind2nd()
无效。此外,std::bind1st()
或std::bind2nd()
都不处理参数类型的参数。
因此,我正在编写自己的bind1st()
版本,如下所示,包括我bind1st()
的示例调用:
#include <iostream>
// c++03 does 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 * a + 10 * b + c;
a+=100;
c+=10;
return val;
}
int main(void)
{
int a[2] = {2, 5};
for (int i=0; i<2; ++i) {
// bind function f with a[i] as its 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;
for (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;
}
}
}
执行结果:
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
它可以在我的电脑上正常工作,作为仿真。但是,它在我的嵌入式编译器中引发了几个问题:
(1)嵌入式编译器不支持__COUNTER__
(2)调用bind1st()
是单调乏味的,如果模板中的那些冗余类型不同步,则可能会出现问题。
因此我的问题是:
(1)如何在常规g ++ / gcc中实现__COUNTER__
?或者,事实上,我只需要一个唯一的数字/标识符而非计数器。
(2)无论如何我可以从函数指针类型派生参数类型和返回类型吗?
(3)即使问题(2)可以完成,我可以从参考类型中导出裸类型吗?例如,我可以从int
派生int &
吗?请注意,源类型可以是int
或int &
,我需要在两种情况下派生结果类型int
。请注意,它是C ++ 03,而不是C ++ 11或更高版本。
(4)还有其他建议吗?也许有人可以提供更简单或更好的实现?
Q.2和Q.3的目标是缩短模板调用,例如FUNC ff = binder3<__COUNTER__, short(*)(int&, int const, int&)>::bind1st(f, a[i]);
。所有其他类型都可以从第一个函数指针类型派生。另外,我不必写4个重载。
--- --- UPDATE
由于实现使用指针来获取绑定参数和函数,因此它可能存在潜在的错误/设计缺陷:
如果调用者在调用binder3<...>::bind1st()
之后但在绑定函数的使用(调用)之前更改了绑定变量的值,则有效值是AFTER更改后的值,而不是更改之前的值!
目前,我可以通过仔细编码来使用它。通常我在bind1st()之后立即使用(调用)绑定函数(中间没有任何命令)。
欢迎改善这个问题的想法。
- UPDATE -
目前,使用__COUNT__
包含一个错误:由于__COUNT__
不是全局唯一的(对于.cpp文件的每个编译,重启计数从零开始),如果它们是,则可能会覆盖边界变量没有及时使用。如果我可以获得一个程序范围的全局唯一编号来替换__COUNT__
,那么上面的实现应该足够好了(除了那些乏味的东西)。