Archived

This topic is now archived and is closed to further replies.

mem_fun_ref question

This topic is 5019 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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());

Share this post


Link to post
Share on other sites
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());

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites