我有一个Visual Studio 2008 C ++应用程序,我想用boost :: phoenix lambda表达式替换一元仿函数。
就我而言,我有包含字符串的对象列表。我想删除所有与指定的字符串不匹配的对象。所以,我使用这样的算法:
struct Foo
{
std::string my_type;
};
struct NotMatchType
{
NotMatchType( const std::string& t ) : t_( t ) { };
bool operator()( const Foo& f ) const
{
return f.my_type.compare( t_ ) != 0;
};
std::string t_;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::vector< Foo > list_of_foo;
/*populate with objects*/
std::string some_type = "some type";
list_of_foo.erase(
std::remove_if( list_of_foo.begin(),
list_of_foo.end(),
NotMatchType( some_type ) ),
list_of_foo.end() );
return 0;
}
这很好用。但是,我想稍微清理我的代码并摆脱NotMatchType
仿函数并用一个简单的lambda表达式替换它:
using boost::phoenix::arg_names::arg1;
list_of_foo.erase(
std::remove_if( list_of_foo.begin(),
list_of_foo.end(),
arg1.my_type.compare( some_type ) != 0 ),
list_of_foo.end() );
显然,这不起作用。
我也尝试过:( arg1->*&Foo::my_type ).compare( some_type ) != 0
我需要做些什么来提升:phoenix:actor看起来像Foo
个对象?
答案 0 :(得分:4)
直接在凤凰城使用std::string::compare()
非常难看,因为它已经超载,我们需要获取其地址:
phx::bind(
static_cast<int (std::string::*)(std::string const&) const>(
&std::string::compare
),
phx::cref(some_type),
phx::bind(&Foo::my_type, arg1)
) != 0
但是,如果我们按照Luc的提示并简单地比较对象的相同性,那么它就变得更容易管理了:
phx::cref(some_type) != phx::bind(&Foo::my_type, arg1)
答案 1 :(得分:3)
鉴于两个字符串lhs
和rhs
,指定lhs == rhs
在语义上等同于lhs.compare(rhs) == 0
。换句话说,你的仿函数正在做的就是做f.my_type != t_
。
考虑到这一点,你可以用凤凰表达你想要的东西:
bind(&Foo::my_type, arg1) =! ref(some_type)
为了记录,您在凤凰演员身上呼叫成员compare
。既然该成员属于std::string
,那不是你想要的。我可以得到以下工作:
typedef int (std::string::*compare_type)(std::string const&) const;
compare_type compare = &std::string::compare;
bind(compare, bind(&Foo::my_type, arg1), "") != 0;
最后一行是最后一个算符。但这并不好,因为没有可靠的方法来获取标准类型的重载成员的地址。换句话说,上面的第二行不能保证编译。
为了将来参考,我在调用重载成员时更喜欢lambdas:
auto compare = [](std::string const& lhs, std::string const& rhs)
{ return lhs.compare(rhs); };
// bind that functor and use it as a Phoenix actor etc