简化简单的C++代码——类似于Python的any

5 投票
3 回答
511 浏览
提问于 2025-04-16 02:30

现在,我有这段代码:

bool isAnyTrue() {
    for(std::list< boost::shared_ptr<Foo> >::iterator i = mylist.begin(); i != mylist.end(); ++i) {
        if( (*i)->isTrue() )
            return true;
    }

    return false;
}

我之前用过Boost库,但我记不太清楚有没有简单的方法可以像我在Python中那样写,比如:

def isAnyTrue():
    return any(o.isTrue() for o in mylist)

在STL或Boost中有没有什么结构可以写得差不多像这样?

或者有没有和这段Python代码等效的东西:

def isAnyTrue():
    return any(map(mylist, lambda o: o.isTrue()))

我主要想知道在Boost或STL中是否已经有类似于any(和all)的功能。如果没有的话,为什么没有呢?因为这看起来很有用,我在Python中经常用到。

3 个回答

4

新的C++标准里有一个叫做std::any_of的东西,比如说:

bool isAnyTrue()
{
    return std::any_of(mylist.begin(), mylist.end(), std::mem_fn(&Foo::isTrue)); // Note std::mem_fn and not std::mem_fun
}

VS2010这个版本已经实现了这个功能。

4

与其使用 find_if,我更喜欢自定义的 any。就可读性来说,我觉得它比 find_if 更好,不过这只是个人喜好。

template<class ForwardIterator, class Pred>
bool any(ForwardIterator begin, ForwardIterator end, Pred pred) {
  for( ; begin != end; ++begin)
    if(pred(*begin)) return true;

  return false;

  //or
  //return std::find_if(mylist.begin(), mylist.end(), std::mem_fun(&Foo::isTrue))
  //       != mylist.end();

}

bool isAnyTrue() {
  return any(mylist.begin(), mylist.end(), std::mem_fun(&Foo::isTrue));
}

补充:Billy ONeal 提供的用 find_if 实现的替代 any。

6

C++ 目前还没有现成的 foreach 这个功能,所以你需要自己来写。

不过,你可以用 std::find_if 这个算法来实现类似的效果:

bool isAnyTrue()
{
    return std::find_if(mylist.begin(), mylist.end(), std::mem_fun(&Foo::isTrue))
           != mylist.end();
}

另外,你可能应该使用 std::vectorstd::deque,而不是 std::list

补充说明:sth 刚刚告诉我,这段代码实际上是不能编译的,因为你的列表里存的是 shared_ptr,而不是实际的对象……因此,你需要自己写一个函数对象,或者使用 boost 库来解决这个问题:

//#include <boost/ptr_container/indirect_fun.hpp>

bool isAnyTrue()
{
    return std::find_if(mylist.begin(), mylist.end(), 
           boost::make_indirect_fun(std::mem_fun(&Foo::isTrue))) != mylist.end();
}

需要注意的是,我还没有测试这个第二个解决方案。

撰写回答