mem_fun_ref question

Started by
9 comments, last by Eriond 20 years, 1 month ago
class X
{
    //...

    bool f() const;
};

class Y
{
    //...

    bool f() const
    {
        for_each(v.begin(), v.end(), mem_fun_ref(&X::f));
    }
    vector<X> v;
};
Is there any way to check if X::f() returns false for any of the objects in v?
Advertisement
Either use std::transform and process the individual results, or write a stateful functor, something like:

template<class Functor>struct any_false_fn: std::unary_function<typename Functor::argument_type,                        typename Functor::result_type>{   Functor fn_;   bool any_false;   any_false_fn(const Functor& fn)   : fn_ (fn), any_false(false)   {}   result_type operator()(const argument_type& arg)   {      result_type result = fn_(arg);      any_false |= !result;      return result;   }};template<class Functor>any_false_fn<Functor> any_false(const Functor& fn){   return any_false_fn<Functor>(fn);}result = std::for_each( v.begin(), v.end(), any_false(mem_fun_ref(&X::f)) ).any_false;


std::for_each returns the functor object it was passed originally.

“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” — Brian W. Kernighan
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
use std::accumulate with an appropriately written functor: compose boolean_and with mem_fun_ref. Pass "true" in as the init. If the result is false, at least one element returned false.

This sort of grotesque not-quite-lambda-calculus is why I tend not to use STL algorithms much. std::accumulate is pretty cool, tho. (and quite useful, in surprising situations.)

"Sneftel is correct, if rather vulgar." --Flarelocke

[edited by - sneftel on March 20, 2004 6:09:30 PM]
good call.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Thank you both. I'll test it tomorrow, it's night here
Edit: I realized I didn't really understand your idea sneftel. I tried:
bool result = std::accumulate(v.begin(), v.end(), true, std::bind2nd(std::logical_and<bool>(), std::mem_fun_ref(&X::f)));
and that didn't compile. Errors: error C2440: 'initializing' : cannot convert from 'const std::const_mem_fun_ref_t<_Result,_Ty>' to 'std::binary_function<_Arg1,_Arg2,_Result>::second_argument_type'
with
[
_Result=bool,
_Ty=X
]
and
[
_Arg1=bool,
_Arg2=bool,
_Result=bool
]
and error C2064: term does not evaluate to a function taking 2 arguments
class does not define an 'operator()' or a user defined conversion operator to a pointer-to-function or reference-to-function that takes appropriate number of arguments
: see reference to function template instantiation '_Ty std::accumulate::const_iterator,bool,std::binder2nd<_Fn2>>(_InIt,_InIt,_Ty,std::binder2nd<_Fn2>)' being compiled
with
[
_Ty=bool,
_Fn2=std::logical_and,
_InIt=std::vector::const_iterator
]


[edited by - Eriond on March 20, 2004 6:48:46 PM]
One other idea: if you need (or don''t mind) short-circuit evaluation (which seems likely since your member function is const), then you can just use:

return (find_if(v.begin(), v.end(), std::not1(std::mem_fun_ref(&X::f))) != v.end());
quote:Original post by Eriond
Edit: I realized I didn''t really understand your idea sneftel. I tried:


I think he literally meant compose, not bind. The down side is that there is no standard compose function object. One quick hack would be to use:
struct thunk {  bool operator()(bool lhs, const X & rhs) {    return lhs && rhs.f();  }};std::accumulate(v.begin(), v.end(), true, thunk()); 
Oh, I see. I''ll use the compose functions from Josuttis'' book. And your way(find_if) is good enought for me.
Darnit, I knew I was going to run into that... when I actually used algorithms a fair amount, I used a lot of Boost stuff (including compose), and I have trouble remembering what's in std and what isn't. IIRC, compose is in there, along with quite a few other useful ones. Of course, Boost also has the lambda library, to obviate a lot of that with a minimal runtime cost.

"Sneftel is correct, if rather vulgar." --Flarelocke

[edited by - sneftel on March 20, 2004 11:50:03 PM]
Uh, boost::compose got deprecated, and so a link to just the boost website isn''t too helpful, as it got removed from the normal documentation links.

This topic is closed to new replies.

Advertisement