[bind] Surprising behavior
Hi there, I'm sure it's not a bug in bind but I have found a
surprising behavior when using it. In my project I have to use some
old school c++ classes that use character arrays instead of
std::string. The following code displays a difference when using two
ways of printing those character arrays.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include
Christian Henning wrote:
for_each( as.begin() , as.end() , bind( &print , bind( &std::string::c_str , bind( &A::name, _1 ))));
The problem here is that A::name returns a temporary std::string; the code is similar to char const * s = it->name().c_str(); print( s ); Since the temporary std::string is destroyed, s remains dangling. One way of avoiding the problem is to make print() take a std::string instead of a char*.
Thanks Peter, this makes sense. But just image I cannot change the
print function's interface. For example I have to interface with MFC's
CComboBox::AddString( LPCTSTR lpszString ) . Do you think there is
still a way to have just one for_each() loop? My guts tell me no.
Thanks again,
Christian
On 4/16/07, Peter Dimov
Christian Henning wrote:
for_each( as.begin() , as.end() , bind( &print , bind( &std::string::c_str , bind( &A::name, _1 ))));
The problem here is that A::name returns a temporary std::string; the code is similar to
char const * s = it->name().c_str(); print( s );
Since the temporary std::string is destroyed, s remains dangling. One way of avoiding the problem is to make print() take a std::string instead of a char*.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Christian Henning wrote:
Thanks Peter, this makes sense. But just image I cannot change the print function's interface. For example I have to interface with MFC's CComboBox::AddString( LPCTSTR lpszString ) . Do you think there is still a way to have just one for_each() loop? My guts tell me no.
Not without writing your own wrapper function void print2( std::string const & s ) { print( s.c_str() ); } and binding that instead of 'print'.
boost-users-bounces@lists.boost.org, le :
Thanks Peter, this makes sense. But just image I cannot change the print function's interface. For example I have to interface with MFC's CComboBox::AddString( LPCTSTR lpszString ) . Do you think there is still a way to have just one for_each() loop? My guts tell me no.
A while ago, I posted a very similar question, which was not answered: http://groups.google.ca/group/boost-list/browse_thread/thread/c24afb8e21 26fc88/b372145c0385d381?lnk=st&q=emalenfant+boost&rnum=1&hl=fr#b372145c0 385d381. In there, I was asking for comments about 2 workarounds which, adapted to your case would be: 1) var_typestd::string::type temp(var(std::string())); std::for_each( begin, end, ( temp = bind(&A::name, _1), bind(Print, bind(&std::string::c_str, temp)) ) ); 2) var_typestd::string::type temp(var(std::string())); std::for_each( begin, end, bind(Print, bind(&std::string::c_str, (temp = bind(&A::name, _1)) ) ) ); Note that this is more "for fun" than, anything. None of these is very elegant, or efficient...
Eric MALENFANT wrote:
2) var_typestd::string::type temp(var(std::string()));
std::for_each( begin, end, bind(Print, bind(&std::string::c_str, (temp = bind(&A::name, _1)) ) ) );
Note that this is more "for fun" than, anything.
In the "for fun" spirit, here's the boost::bind equivalent: string& (string::*assign)( string const & ) = &string::operator=; std::for_each( begin, end, bind( Print, bind( &std::string::c_str, bind( assign, string(), bind( &A::name, _1 ) ) ) ) );
participants (3)
-
Christian Henning
-
Eric MALENFANT
-
Peter Dimov