std :: bind()/ tr1 :: bind()

时间:2015-06-04 10:08:04

标签: c++ templates c++03

我正在使用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 &吗?请注意,源类型可以是intint &,我需要在两种情况下派生结果类型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__,那么上面的实现应该足够好了(除了那些乏味的东西)。

0 个答案:

没有答案