Boost函数和lambda来包装函数
boost function and lambda to wrap a function
我想转换这个简单的代码:
void setZComp(Imath::V3f& pt)
{
pt.z = 0.0;
}
int myfunc()
{
...
std::vector<Imath::V3f> vec(5,Imath::V3f(1.0,1.0,1.0));
std::for_each(vec.begin(),vec.end(),boost::bind(&setZComp,_1));
...
}
像这样,为了不让setZComp在外部声明而是内联声明
int myfunc()
{
...
boost::function<double(Imath::V3f&)> f = (boost::lambda::_1 ->* &Imath::V3f::z = 0.0) ;
std::for_each(vec.begin(),vec.end(),boost::bind(&f,_1));
...
}
我对Boost Bind和Lambda很陌生,我不知道这是否可以以某种方式完成。显然,上面的代码不起作用。
你是在用大锤砸坚果吗?有时,我认为使用普通的for循环并自己显式设置变量更简单。这使得代码更容易阅读和维护。
typedef std::vector<Imath::V3f> V3fVector;
V3fVector vec(5,Imath::V3f(1.0,1.0,1.0));
for (V3fVector::iterator i = vec.begin(), iEnd = vec.end(); iEnd != i; ++i)
i->z = 0.0;
尽管boost bind很有用,但它也是一个语法混乱,使简单的代码无法读取。
如果你不能使用c++ 11的lambda,那么你可以使用boost::lambda::bind
。
所以在你的例子中,像这样:
boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0
一个完整的例子,因为我不知道你的内部:
struct S
{
S():i(0){};
int i;
};
int main()
{
std::vector<S> vec;
vec.push_back(S());
std::for_each(vec.begin(), vec.end(), boost::lambda::bind(&S::i, boost::lambda::_1) = 5);
std::cout << vec.front().i << std::endl; // outputs 5
return 0
}
您还可以考虑看一下boost::phoenix。我认为它是一个比lambda库更完整的c++函数式编程实现。
如作为目标的成员变量一节所述:
指向成员变量的指针并不是真正的函数,但是[
boost::lambda::bind
]函数的第一个参数仍然可以是指向成员变量的指针。调用这样的绑定表达式将返回对该数据成员的引用。
要构造一个访问z
成员的lambda表达式,可以使用:
boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1)
返回的对象本身可用于其他表达式。例如,
boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0
表示"获取第一个参数(Imath::V3f&
类型)的z
成员的double
ref并赋值0.0"。
你可以在Boost中使用这个lambda。功能与std::for_each
:
boost::function<void(Imath::V3f&)> f = boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0;
std::for_each(vec.begin(), vec.end(), f);
作为参考,这里有一个完整的、可编译的示例:
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <boost/function.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
namespace Imath
{
class V3f
{
public:
double x, y, z;
V3f(double x_, double y_, double z_)
: x(x_), y(y_), z(z_)
{
}
friend std::ostream& operator<<(std::ostream& os, const V3f& pt) {
return (os << '(' << pt.x << ", " << pt.y << ", " << pt.z << ')');
}
};
}
int main()
{
std::vector<Imath::V3f> vec(5, Imath::V3f(1.0, 1.0, 1.0));
boost::function<void(Imath::V3f&)> f = boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0;
std::for_each(vec.begin(), vec.end(), f);
std::vector<Imath::V3f>::iterator it, end = vec.end();
for (it = vec.begin(); it != end; ++it) {
std::cout << *it << std::endl;
}
return EXIT_SUCCESS;
}
输出:<>之前(1,1,0)(1,1,0)(1,1,0)(1,1,0)(1,1,0)
如果您可以访问支持c++ 11或MSVC 2010的最新版本的g++
,则可以执行以下操作:
int myfunc()
{
...
std::for_each(vec.begin(),vec.end(),[](Imath::V3f& pt){ pt.z = 0.0; });
...
}
如果您想使用boost::lambda,我有时发现在包含lambda的行之前声明一个"指针到成员"变量会更简洁,这样您就可以使用->*操作符,而不是使用boost::lambda::bind。
然而,正如图灵指出的,一个简单的循环可能是最简单的解决方案。使用BOOST_FOREACH使它更简单。
下面是mkaes示例实现的修改版本,它使用操作符->*代替bind,并且还展示了如何使用BOOST_FOREACH作为替代。
#include <iostream>
#include <vector>
#include <boost/lambda/lambda.hpp>
#include <boost/foreach.hpp>
// I like to provide alternate names for the boost::lambda placeholders
boost::lambda::placeholder1_type& arg1 = boost::lambda::_1 ;
boost::lambda::placeholder2_type& arg2 = boost::lambda::_2 ;
boost::lambda::placeholder3_type& arg3 = boost::lambda::_3 ;
struct S
{
S():i(0){};
int i;
};
int main()
{
std::vector<S> vec;
vec.push_back(S());
// Define this pointer-to-member so we can
// use it in the lambda via the ->* operator
int S::* i = &S::i ;
std::for_each(vec.begin(), vec.end(), &arg1->*i = 5);
std::cout << vec.front().i << std::endl; // outputs 5
// Alternatively, just use a simple foreach loop
BOOST_FOREACH( S & s, vec )
{
s.i = 6 ;
}
std::cout << vec.front().i << std::endl; // outputs 6
return 0 ;
}
- 将 N-arg 函数包装到另一个函数中
- 将函数包装器转换为 std::function
- C++函数包装器来捕获某些信号
- 考虑引用和常量的可变参数函数包装器
- 将此私有删除器函数包装在结构中的目的是什么?
- 处理模板函数包装中的void返回
- 如何使用可变模板编写通用函数包装器
- 其他成员函数的通用"成员函数"包装器?
- 为什么将函数包装到 lambda 中可能会使程序更快?
- 创建一个允许轻松创建虚拟函数包装器函数的C++宏
- 将 c++ 函数包装为 c#,具有结构的总动态大小
- 返回对 std::函数包装的 lambda 中静态变量的引用会导致段错误
- 标准库中是否有与 std::thread 的构造函数语义匹配的类型擦除函数包装器?
- 如何编写 C++ 类成员函数包装器
- 有没有一种方法可以在基于枚举的可变参数模板函数之间进行选择,这比将函数包装在结构中更简单
- 任何返回类型的可变参数函数包装器
- 具有临时函数包装器的完美转发
- 推导成员函数包装器的返回类型时出错
- 使用可变参数模板函数包装基于省略号的函数
- 将C 模板构造函数包装在模板类中