首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >std::bind2在C++03中的复合函数

std::bind2在C++03中的复合函数
EN

Stack Overflow用户
提问于 2015-05-05 07:16:55
回答 2查看 527关注 0票数 1

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

具体来说,我有函数f(x, y)g(u, v),我希望创建一个函数指针或函子h(t) = f(g(t,C1), C2),这样就可以将函子h传递到for_each()循环中,其中C1、C2是一些常量。

或者,让我们在我的实际例子中这样做:我有一个函数double g(T1 u, T2 v),它计算一些东西。我想从向量u循环所有的vector<T1> vecInput,用固定的第二个参数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上这么做。有什么解决办法吗?而且,我希望解决方案能够更干净(如果可以在上面这样的一行中完成)。

更新

bind2nd()的相关问题:我得到了编译错误,现在我将它简化为一个更简单的代码来查看它:

代码语言:javascript
复制
#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号案子失败了..。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-05-07 12:03:32

我有函数f(x, y)__和g(u, v)__,我想创建一个函数指针或函子h(t) = f(g(t,C1), C2)__。我得用C++03来做。

不可能只使用C++03标准库中可用的适配器来组合函数。显然,没有什么能阻止您自己实现此功能。但是,如果您想要利用现有的任何库,并获得一个真正的一行程序,那么几乎没有其他选择:

选项1: SGI扩展

libstdc++随SGI的标准库扩展一起运来。它提供了几个额外的适配器和函子,即:compose1compose2constant1。它们可以通过以下方式结合起来:

代码语言:javascript
复制
#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扩展

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

代码语言:javascript
复制
#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库

Boost.Bind库可能是最可移植的解决方案:

代码语言:javascript
复制
#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绑定对象参数:

代码语言:javascript
复制
Class object;
std::bind1st(std::mem_fun(&Class::func), &object)(arg);

但是,对于引用其参数的成员函数来说,这将失败。再次,您可以使用Boost/TR1来代替:

代码语言:javascript
复制
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,这将负责为转换参数调用向量的push_back成员函数。

代码语言:javascript
复制
#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));

演示

票数 1
EN

Stack Overflow用户

发布于 2015-05-05 08:58:37

重要的是要记住,这些库函数并不神奇,它们只是推导出相当复杂的类型。

在您的情况下,您不需要所有这些灵活性,这仅仅是因为您知道您需要vector::push_back。与其推断一个相当复杂的类型,不如创建一个显式类型来捕获函数。甚至还有一种库类型可以做到这一点,std::back_insert_iterator,但是通常您可以自己做。

因此,您将得到一个模板类,它接受类型名T1和T2,存储&gT2 C2std::vector<double>&。它只是实现了void operator()(T1 t1) { v.pus_back(g(t1, C2)); }

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30046499

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档