我想让一些函数/函子充当复合函数/函子:
具体来说,我有函数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
}
我不知道为什么CASE 2会失败......
答案 0 :(得分:1)
我有函数
f(x, y)
和g(u, v)
,我想创建一个函数指针或仿函数h(t) = f(g(t,C1), C2)
。我必须在C ++ 03中完成。
仅使用C ++ 03标准库中提供的适配器无法编写函数。显然,没有什么能阻止你自己实现这个功能。但是,如果你想利用任何现有的库,并获得真正的单行,那么几乎没有其他选择:
libstdc ++附带the standard library extensions from 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);
在std::bind
扩展库中也可以找到C ++ 11 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);
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));
答案 1 :(得分:0)
重要的是要记住,这些库函数并不神奇,它们只是推断出相关的类型。
在您的情况下,您不需要所有这些灵活性,只是因为您知道自己需要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)); }
。