1

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

我需要做什么才能使 boost:phoenix:actor 看起来像一个Foo对象?

4

2 回答 2

4

直接从 Phoenix使用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)
于 2011-08-29T22:02:43.970 回答
3

给定两个字符串lhsrhs,然后lhs == rhs指定在语义上等价于lhs.compare(rhs) == 0。换句话说,你的函子正在做的事情等价于做f.my_type != t_.

考虑到这一点,您可以用 Phoenix 表达您想要的内容:

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;

最后一行是最终的仿函数。但这并不好,因为没有可靠的方法来获取标准类型的重载成员的地址。换句话说,上面的第二行不能保证编译。

为了将来参考,我在调用重载成员时更喜欢 lambda:

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
于 2011-08-29T19:57:17.350 回答