Introduction
Let's say we have a list of string
s:
std::vector< std::string > list;
list.push_back( "duck" );
list.push_back( "duck" );
list.push_back( "goose" );
std::string value = "goose";
We'd like to filter the string
"goose
" from this list. Using the typical erase-remove idiom, we could do something like this:
bool IsGoose( const std::string& s )
{
return s == "goose";
}
list.erase( std::remove_if( list.begin(), list.end(), IsGoose ), list.end() );
Translating this to a lambda function using boost.bind
, we get:
list.erase(
std::remove_if(
list.begin(),
list.end(),
boost::bind(
static_cast< bool( * )( const std::string&,
const std::string& ) >(
&std::operator==<char, std::string::traits_type, std::string::allocator_type> ),
_1,
boost::cref( value ) ) ),
list.end() );
Because the std::operator==
is overloaded, we have a very messy looking cast in there to ensure the correct version of the function is selected. Using boost.phoenix[^], we can clean that up a bit:
namespace phx = boost::phoenix;
using phx::placeholders::arg1;
using phx::placeholders::arg2;
list.erase( std::remove_if( list.begin(),
list.end(),
arg1 == phx::cref( value ) ),
list.end() );
We can even shrink things slightly further by switching to the boost.phoenix remove_if
wrapper so that we no longer need to include the iterator range:
list.erase( phx::remove_if( arg1, arg2 )( list, arg1 == phx::cref( value ) ),
list.end() );
And that, ladies and gentlemen, is how boost.phoenix
can make a complicated and messy lambda expression much simpler.