用boost :: phoenix actor替换一元仿函数

时间:2011-08-29 18:42:57

标签: c++ boost functor boost-phoenix

我有一个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个对象?

2 个答案:

答案 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)

鉴于两个字符串lhsrhs,指定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