我想得到一些函数/函子作为一个复合函数/函子:
具体来说,我有函数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()的相关问题:我得到了编译错误,现在我将它简化为一个更简单的代码来查看它:
#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号案子失败了..。
发布于 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的标准库扩展一起运来。它提供了几个额外的适配器和函子,即:compose1、compose2和constant1。它们可以通过以下方式结合起来:
#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扩展库中找到:
#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库可能是最可移植的解决方案:
#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_fun和std::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,这将负责为转换参数调用向量的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));演示
发布于 2015-05-05 08:58:37
重要的是要记住,这些库函数并不神奇,它们只是推导出相当复杂的类型。
在您的情况下,您不需要所有这些灵活性,这仅仅是因为您知道您需要vector::push_back。与其推断一个相当复杂的类型,不如创建一个显式类型来捕获函数。甚至还有一种库类型可以做到这一点,std::back_insert_iterator,但是通常您可以自己做。
因此,您将得到一个模板类,它接受类型名T1和T2,存储&g、T2 C2和std::vector<double>&。它只是实现了void operator()(T1 t1) { v.pus_back(g(t1, C2)); }。
https://stackoverflow.com/questions/30046499
复制相似问题