使用boost::lambda时最容易犯的一个错误就是就是将需要的表达式直白的表达出来。
比如想从一个Foo的容器中找到值为3的那个元素,可能你会写出这样的式子。
struct Foo
{
int val;
};
typedef std::vector<Foo> FooVec_t;
FooVec_t foo_vec;
.....
FooVec_t::const_iterator p = std::find_if(foo_vec.begin(), foo_vec.end(), _1.val == 3);
....
这是我实际编程中犯过的一个错误,上面的代码根本无法编译通过,我来分析下:
_1的类型是:boost::lambda::placeholder1_type,这个类型根本就没有一个叫val的成员,所以编译不通过了。
在撰写lambda表达式时,要记住的是一定要写成有效的lambda表达式!什么是有效的lambda表达式呢?比如上面的
这个问题,应该这样解决:
std::find_if(foo_vec.begin(), foo_vec.end(), bind(&Foo::val, _1) == 3);
也就是说:_1只是placeholder1_type类型,是个占位符,要获得这个占位符所代表的那个类型的某个成员值或者成员函数时,一定要用bind的方式来操作。
而对于构造函数,boost::lambda又有不一样的处理了。
关于构造函数,贴下我以前在csdn论坛上询问的一个帖子:
---------------------------------------------------------------------------------------------------------------
问题:
我想根据一个int容器的内容以及一个double容器的内容构造一个Foo容器,于是我使用了如下的代码:但是编译8通过,哪里弄错了?
struct Foo
{
Foo(int i, double d)
{
}
};
int _tmain(int argc, _TCHAR* argv[])
{
using namespace boost::lambda;
std::vector<int> int_vec;
int_vec.push_back(1);
int_vec.push_back(2);
std::vector<double> db_vec;
db_vec.push_back(1.2);
db_vec.push_back(2.3);
std::vector<Foo> foo_vec;
std::transform(int_vec.begin(), int_vec.end(), db_vec.begin(), std::back_inserter(foo_vec), Foo(_1, _2));
return 0;
-------------------------------------------------------------------------------------------
答案:
谢谢哦,今天看了一晚上的lambda的资料,终于会使用这玩意儿了。呵呵。
我的那个问题的正确解法应该是:
std::transform(int_vec.begin(), int_vec.end(), db_vec.begin(), std::back_inserter(foo_vec), bind(constructor<Foo>(), _1, _2));
而我原来的错误写法中,Foo(_1, _2)。因为_1是boost::lambda::placeholder1_type,而Foo构造函数要求的第一个参数是int型,所以编译器不让通过了。这让我明白了在使用boost::lambda的时候,经常会有将lambda表达式直白地表达出来的错误。因此很多地方需要var, constant,constant_ref的帮助,让代码成为一个lambda结构,从而成为一个functor,从而能够编译。
最后惊叹一下boost::lambda,仿照课本上的代码,写了一下:
using namespace boost::lambda;
typedef boost::shared_ptr<base> ptr_type;
typedef std::map<std::string, ptr_type> map_type;
map_type m;
m["An Object"] = ptr_type(new base);
m["Another object"] = ptr_type();
m["Yet Another object"] = ptr_type(new base);
std::for_each
(
m.begin(),
m.end(),
if_then_else
(
!bind(&ptr_type::get, bind(&map_type::value_type::second, _1)),
(
bind(&map_type::value_type::second, _1) = bind(constructor<ptr_type>(), bind(new_ptr<derived>())),
var(std::cout) << "created a new derived for /"" << bind(&map_type::value_type::first, _1) << "/"./n"
),
var(std::cout) << bind(&map_type::value_type::first, _1) << " already has a valid pointer./n"
)
);
窒息中~
比如想从一个Foo的容器中找到值为3的那个元素,可能你会写出这样的式子。
struct Foo
{
int val;
};
typedef std::vector<Foo> FooVec_t;
FooVec_t foo_vec;
.....
FooVec_t::const_iterator p = std::find_if(foo_vec.begin(), foo_vec.end(), _1.val == 3);
....
这是我实际编程中犯过的一个错误,上面的代码根本无法编译通过,我来分析下:
_1的类型是:boost::lambda::placeholder1_type,这个类型根本就没有一个叫val的成员,所以编译不通过了。
在撰写lambda表达式时,要记住的是一定要写成有效的lambda表达式!什么是有效的lambda表达式呢?比如上面的
这个问题,应该这样解决:
std::find_if(foo_vec.begin(), foo_vec.end(), bind(&Foo::val, _1) == 3);
也就是说:_1只是placeholder1_type类型,是个占位符,要获得这个占位符所代表的那个类型的某个成员值或者成员函数时,一定要用bind的方式来操作。
而对于构造函数,boost::lambda又有不一样的处理了。
关于构造函数,贴下我以前在csdn论坛上询问的一个帖子:
---------------------------------------------------------------------------------------------------------------
问题:
我想根据一个int容器的内容以及一个double容器的内容构造一个Foo容器,于是我使用了如下的代码:但是编译8通过,哪里弄错了?
struct Foo
{
Foo(int i, double d)
{
}
};
int _tmain(int argc, _TCHAR* argv[])
{
using namespace boost::lambda;
std::vector<int> int_vec;
int_vec.push_back(1);
int_vec.push_back(2);
std::vector<double> db_vec;
db_vec.push_back(1.2);
db_vec.push_back(2.3);
std::vector<Foo> foo_vec;
std::transform(int_vec.begin(), int_vec.end(), db_vec.begin(), std::back_inserter(foo_vec), Foo(_1, _2));
return 0;
-------------------------------------------------------------------------------------------
答案:
谢谢哦,今天看了一晚上的lambda的资料,终于会使用这玩意儿了。呵呵。
我的那个问题的正确解法应该是:
std::transform(int_vec.begin(), int_vec.end(), db_vec.begin(), std::back_inserter(foo_vec), bind(constructor<Foo>(), _1, _2));
而我原来的错误写法中,Foo(_1, _2)。因为_1是boost::lambda::placeholder1_type,而Foo构造函数要求的第一个参数是int型,所以编译器不让通过了。这让我明白了在使用boost::lambda的时候,经常会有将lambda表达式直白地表达出来的错误。因此很多地方需要var, constant,constant_ref的帮助,让代码成为一个lambda结构,从而成为一个functor,从而能够编译。
最后惊叹一下boost::lambda,仿照课本上的代码,写了一下:
using namespace boost::lambda;
typedef boost::shared_ptr<base> ptr_type;
typedef std::map<std::string, ptr_type> map_type;
map_type m;
m["An Object"] = ptr_type(new base);
m["Another object"] = ptr_type();
m["Yet Another object"] = ptr_type(new base);
std::for_each
(
m.begin(),
m.end(),
if_then_else
(
!bind(&ptr_type::get, bind(&map_type::value_type::second, _1)),
(
bind(&map_type::value_type::second, _1) = bind(constructor<ptr_type>(), bind(new_ptr<derived>())),
var(std::cout) << "created a new derived for /"" << bind(&map_type::value_type::first, _1) << "/"./n"
),
var(std::cout) << bind(&map_type::value_type::first, _1) << " already has a valid pointer./n"
)
);
窒息中~