C 03中具有std :: bind2nd的复合函数

Composite function with std::bind2nd in C++03

本文关键字:bind2nd 复合函数 std      更新时间:2023-10-16

我想获得一些函数/函数作为复合函数/函子:

具体来说,我具有函数f(x, y)g(u, v),并且我想创建一个函数指针或函数h(t) = f(g(t,C1), C2),因此我可以将functor h传递到for_each()循环中,其中c1,c2是某些常数。

或者,让我们在我的真实示例中进行:我有一个函数 double g(T1 u, T2 v),可以计算一些东西。我想从vector vector<T1> vecInput循环循环所有u,并使用固定的第二个参数t2VConst循环。计算所有这些数字后,我想将它们保存到矢量vector<double> results中。

我想用类似的事情来做:

foreach(vecInput.begin(), vecInput.end(), std::bind2nd(&results::push_back, std::bind2nd(g, t2VConst)))

请注意,在这种情况下,f(x,y)函数实际上是成员函数vector::push_back。(看来push_back只有一个参数。但是,作为成员函数,它具有额外的参数,这是对象本身。)

为了使情况变得更糟,我确实必须在C 03,而不是C 11中这样做。有解决方案吗?此外,我希望该解决方案可以更干净(如果可以在上面的一行中完成)。

update

bind2nd()的相关问题:我有编译错误,现在将其简化为更简单的代码以查看它:

#include <functional>
#include <algorithm>
#define CASE2   // choose define of CASE1 to CASE3
#ifdef CASE1
double g(double x, double y)   // 1. OK
#endif
#ifdef CASE2
double g(double &x, double y)  // 2. overload error
#endif
#ifdef CASE3
double g(double *x, double y)  // 3. OK
#endif
{
#ifdef CASE2
    x  = 5.0;
#endif
#ifdef CASE3
    *x = 5.0;
#endif
    // Note: no case1, since in case 1, x is a local variable, 
    // no meaning to assign value to it.
    return 3.0;
}
int main(int argc, char *argv[])
{
    double t = 2.0;
    double u;
#if defined(CASE1) || defined(CASE2)
    u = std::bind2nd(std::ptr_fun(&g), 3.0)(t);
#endif
#ifdef CASE3
    u = std::bind2nd(std::ptr_fun(&g), 3.0)(&t);
#endif
}

我不知道为什么情况2失败...

我有函数f(x, y)g(u, v),我想创建一个函数指针或函数h(t) = f(g(t,C1), C2)。我必须在C 03中进行此操作。

不可能仅使用C 03的标准库中可用的适配器构成功能。显然,没有什么可以阻止您自己实施此功能。但是,如果您想利用任何现有库并获得真正的单线库,则几乎没有其他选择:

选项#1:SGI扩展

libstdc 已通过SGI的标准库扩展名运输。它提供了几个其他适配器和函子,即:compose1compose2constant1。它们可以通过以下方式组合:

#include <functional>
#include <ext/functional>
int f(int x, int y);
int g(int u, int v);
const int arg = 1;
const int C1 = 2;
const int C2 = 3;
__gnu_cxx::compose2(std::ptr_fun(&f)
                  , std::bind2nd(std::ptr_fun(&g), C1)
                  , __gnu_cxx::constant1<int>(C2)
                 )(arg);

选项#2:TR1扩展

tr1扩展库中也可以找到C 11的std::bind的初始实现:

#include <tr1/functional>
int f(int x, int y);
int g(int u, int v);
const int arg = 1;
const int C1 = 2;
const int C2 = 3;
std::tr1::bind(&f
             , std::tr1::bind(&g
                            , std::tr1::placeholders::_1
                            , C1)
             , C2
            )(arg);

选项#3:Boost Library

boost.bind库可能是最便携的解决方案:

#include <boost/bind.hpp>
int f(int x, int y);
int g(int u, int v);
const int arg = 1;
const int C1 = 2;
const int C2 = 3;
boost::bind(&f, boost::bind(&g, _1, C1), C2)(arg);

f(x,y)功能实际上是成员函数vector::push_back

在绑定C 03中的成员函数时,通常将std::mem_funstd::bind1st一起使用来绑定对象参数:

Class object;
std::bind1st(std::mem_fun(&Class::func), &object)(arg);

但是,这将使成员函数通过参考失败。再次,您可以改用Boost/TR1:

boost::bind(&std::vector<double>::push_back
          , &results
          , boost::bind(&g, _1, C1)
          )(arg);

请注意,切换到C 11时,您需要手动解析过载的std::vector<double>::push_back

,但幸运的是,您的用例有资格用std::transform算法替换为std::back_inserter,它将负责调用vector的push_back成员功能以进行转换的参数。

#include <algorithm>
#include <functional>
#include <iterator>
int g(int u, int v);
const int C1 = 2;
std::vector<int> input, output;
std::transform(input.begin(), input.end()
             , std::back_inserter(output)
             , std::bind2nd(std::ptr_fun(&g), C1));

demo

重要的是要记住,这些库的功能不是魔术,而只是推断出相当涉及的类型。

在您的情况下,您不需要所有这些灵活性,只是因为您知道您需要vector::push_back。而不是推论相当涉及的类型,只需明确创建一个类型即可捕获该功能。std::back_insert_iterator甚至还有一个库类型,但通常您可以自己做。

因此,您最终将获得一个模板类,该类别将TYPENAMES T1和T2,存储&gT2 C2std::vector<double>&存储。它只是实现void operator()(T1 t1) { v.pus_back(g(t1, C2)); }