tags:

views:

204

answers:

3

Hi,

Right now, I have this code:

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

    return false;
}

I have used Boost here and then but I couldn't really remember any simple way to write it somewhat like I would maybe write it in Python, e.g.:

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

Is there any construct in STL/Boost to write it more or less like this?

Or maybe an equivalent to this Python Code:

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

Mostly I am wondering if there is any existing any (and all) equivalent in Boost / STL yet. Or why there is not (because it seems quite useful and I use it quite often in Python).

+5  A: 

C++ does not (yet) have a foreach construct. You have to write that yourself/

That said, you can use the std::find_if algorithm here:

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

Also, you should probably be using std::vector or std::deque rather than std::list.

EDIT: sth has just informed me that this won't actually compile because your list contains shared_ptr instead of the actual objects... because of that, you're going to need to write your own functor, or rely on 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();
}

Note, I haven't tested this second solution.

Billy ONeal
@sth: How is this solution?
Billy ONeal
Boost has a foreach (`BOOST_FOREACH`).
Albert
@Albert: Yes, it does. But even in that case, you should prefer algorithm calls to explicit loops.
Billy ONeal
A queue is not possible because it doesn't allow iteration through its elements. And why vector instead of a list? I need very fast insertion time (should be constant) and don't care about random access at all.
Albert
OP is already using boost. `boost::mem_fn` should be more flexible than `std::mem_fun` (or else use `boost::bind`)
UncleBens
Albert
@Albert: Bind cannot insert a second indirection. You'd still need to use some form of indirect_fun with bind. @UncleBens: The only benefit boost::mem_fn provides is that it automatically selects the correct type -- mem_fun or mem_fun_ref.
Billy ONeal
In any case it seems that just `boost::mem_fn` compiles and works. From the C++0x description of how `std::mem_fn` should invoke the function, it also seems that these binders are supposed to distinguish between object/reference and anything else, i.e these adaptors shouldn't care if they receive a plain pointer or a smart pointer - dereferencing it looks all the same.
UncleBens
@UncleBens: That's because `mem_fun` and `mem_fun_ref` work with smart pointers as well. The only difference is that `mem_fun` provides a level of indirection, while `mem_fun_ref` does not. We need two levels of indirection here though...
Billy ONeal
I'm not entirely sure where the second level of indirection comes from. The calls look quite the same to me: `X* ptr; ((*ptr).*member_fun)();` and `shared_ptr<X> ptr; ((*ptr).*member_fun)();`. Smart pointers exactly mimic the pointer interface.
UncleBens
+4  A: 

Instead of find_if I'd go with a custom any. I like it better in terms of readability over find_if but that's a matter of taste.

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));
}

Edit: Alternative any with find_if by Billy ONeal.

pmr
Nothing wrong with a custom any, but why not implement it in terms of `find_if`?
Billy ONeal
Ok, well, I wondered mostly why there is no such `any` (or something similar) in Boost yet. This is mostly like I have done it already (not in my question but in my real code), with a custom own `any` function.
Albert
@Albert - The cool thing about this version of any() is that it uses templates, and works with (no pun intended) any type. It's something you can stuff in your programming toolkit and use anywhere.
sheepsimulator
+2  A: 

The new C++ standard has std::any_of, e.g.

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 has this implemented.

ronag
g++ 4.4 implements this also.
rafak
Matt Joiner
First result in google. http://msdn.microsoft.com/en-us/library/ee396393.aspx
ronag