C++03 中带 std::bind2nd 的复合函数
Composite function with std::bind2nd in C++03
我想得到一些 function/functor 作为复合 function/functor:
具体来说,我有函数f(x, y)
和g(u, v)
,我想创建一个函数指针或仿函数h(t) = f(g(t,C1), C2)
,这样我就可以传递仿函数h
进入 for_each() 循环,其中 C1、C2 是一些常数。
或者,让我们在我的真实示例中这样做:
我有一个函数 double g(T1 u, T2 v)
可以计算一些东西。我想从向量 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。有什么解决办法吗?此外,我希望解决方案可以更简洁(如果可以像上面那样在一行中完成的话)。
更新
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 失败了...
重要的是要记住,这些库函数并不神奇,它们只是推导相当复杂的类型。
在您的情况下,您不需要所有这些灵活性,只是因为您知道自己需要 vector::push_back
。与其推导一个相当复杂的类型,不如显式创建一个类型来捕获函数。甚至还有一种库类型可以执行此操作,std::back_insert_iterator
,但通常您可以自己完成。
因此,您最终会得到一个模板 class,它采用类型名称 T1 和 T2,存储 &g
、T2 C2
和 std::vector<double>&
。它只是实现 void operator()(T1 t1) { v.pus_back(g(t1, C2)); }
.
I have functions f(x, y)
, and g(u, v)
, and I want to create a function pointer or functor h(t) = f(g(t,C1), C2)
. I have to do it in C++03.
不可能仅使用 C++03 标准库中可用的适配器来组合函数。显然,没有什么能阻止您自己实现此功能。但是,如果您想利用任何现有的库,并获得真正的单行代码,则几乎没有其他选择:
选项 #1:SGI 扩展
libstdc++ 随 the standard library extensions from SGI. It provides several additional adapters and functors, namely: compose1
, compose2
and 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);
The f(x,y)
function is really a member function vector::push_back
在 C++03 中绑定成员函数时,您通常会使用 std::mem_fun
together with 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
algorithm with 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));
我想得到一些 function/functor 作为复合 function/functor:
具体来说,我有函数f(x, y)
和g(u, v)
,我想创建一个函数指针或仿函数h(t) = f(g(t,C1), C2)
,这样我就可以传递仿函数h
进入 for_each() 循环,其中 C1、C2 是一些常数。
或者,让我们在我的真实示例中这样做:
我有一个函数 double g(T1 u, T2 v)
可以计算一些东西。我想从向量 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。有什么解决办法吗?此外,我希望解决方案可以更简洁(如果可以像上面那样在一行中完成的话)。
更新
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 失败了...
重要的是要记住,这些库函数并不神奇,它们只是推导相当复杂的类型。
在您的情况下,您不需要所有这些灵活性,只是因为您知道自己需要 vector::push_back
。与其推导一个相当复杂的类型,不如显式创建一个类型来捕获函数。甚至还有一种库类型可以执行此操作,std::back_insert_iterator
,但通常您可以自己完成。
因此,您最终会得到一个模板 class,它采用类型名称 T1 和 T2,存储 &g
、T2 C2
和 std::vector<double>&
。它只是实现 void operator()(T1 t1) { v.pus_back(g(t1, C2)); }
.
I have functions
f(x, y)
, andg(u, v)
, and I want to create a function pointer or functorh(t) = f(g(t,C1), C2)
. I have to do it in C++03.
不可能仅使用 C++03 标准库中可用的适配器来组合函数。显然,没有什么能阻止您自己实现此功能。但是,如果您想利用任何现有的库,并获得真正的单行代码,则几乎没有其他选择:
选项 #1:SGI 扩展
libstdc++ 随 the standard library extensions from SGI. It provides several additional adapters and functors, namely: compose1
, compose2
and 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);
The
f(x,y)
function is really a member functionvector::push_back
在 C++03 中绑定成员函数时,您通常会使用 std::mem_fun
together with 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
algorithm with 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));