问题的起因很简单,我实验一个简单的程序不过。这个程序的本意是想检验一下 boost.bind 在 1.33 中新加入的比较运算符,我以为这一点也不难,然而程序的运行结果大出我的意料:
#include
#include
#include
#include
//#include
//#include
#include
//using namespace boost::lambda;
using namespace boost;
class Person
{
public:
Person(){}
Person(const std::string& name) : name_(name){}
std::string& Name()
{ return name_; }
private:
std::string name_;
};
int main()
{
std::map persons;
persons[123] = Person("Amy");
persons[234] = Person("Ralph");
persons[345] = Person("Simon");
persons[456] = Person("Maggie");
std::cout << "Ralph's Id is: " <<
std::find_if( persons.begin(), persons.end(),
bind(&Person::Name,
bind(&std::map::value_type::second, _1)) ==
"Ralph" )->first;
}
它的输出竟然是
Ralph's Id is: 0
不过,如果把程序中的 bind 库换成 boost.lambda (uncomment 掉前面的 include 和 using 即可),输出就是
Ralph's Id is: 234
这才是我想要的,我在新闻组提了这个问题,Peter Dimov 给我的答复可能是对我们每个使用 boost.bind 的人的忠告:
I get an error C2439 on this example; the problem is that the inner
bind returns a temporary Person by value, but Person::Name returns a
reference to its member std::string.
区别在于 bind 这一部分,现在我们将不得不显式的指出我们绑定到一个 data member 的目的是取得它的 reference 而不是一份拷贝。在修改这个问题之前,一定要小心处理这个问题,否则就会跟我一样目瞪口呆。
#include
#include
#include
#include
//#include
//#include
#include
//using namespace boost::lambda;
using namespace boost;
class Person
{
public:
Person(){}
Person(const std::string& name) : name_(name){}
std::string& Name()
{ return name_; }
private:
std::string name_;
};
int main()
{
std::map persons;
persons[123] = Person("Amy");
persons[234] = Person("Ralph");
persons[345] = Person("Simon");
persons[456] = Person("Maggie");
std::cout << "Ralph's Id is: " <<
std::find_if( persons.begin(), persons.end(),
bind(&Person::Name,
bind(&std::map::value_type::second, _1)) ==
"Ralph" )->first;
}
它的输出竟然是
Ralph's Id is: 0
不过,如果把程序中的 bind 库换成 boost.lambda (uncomment 掉前面的 include 和 using 即可),输出就是
Ralph's Id is: 234
这才是我想要的,我在新闻组提了这个问题,Peter Dimov 给我的答复可能是对我们每个使用 boost.bind 的人的忠告:
I get an error C2439 on this example; the problem is that the inner
bind returns a temporary Person by value, but Person::Name returns a
reference to its member std::string.
bind on a data member was changed to return a value and not a reference
because of similar reference to temporary issues, but it seems clear
now that this change has caused more problems than it solved.
I'll try to fix it for the next release (1.33.1 if there is one, or
1.34), but in the meantime you need to use
bind(&std::map::value_type::second, _1)
区别在于 bind 这一部分,现在我们将不得不显式的指出我们绑定到一个 data member 的目的是取得它的 reference 而不是一份拷贝。在修改这个问题之前,一定要小心处理这个问题,否则就会跟我一样目瞪口呆。
本文探讨了一个关于Boost.Bind在处理临时对象时遇到的问题。在使用Boost.Bind进行成员函数和数据成员绑定时,若返回引用至临时对象,则会导致程序错误。通过对比Boost.Bind和Boost.Lambda的不同行为,指出了在1.33版本中引入的新特性可能导致的问题,并给出了临时解决方案。
4681

被折叠的 条评论
为什么被折叠?



