|
Boost Users : |
From: Michael Fawcett (michael.fawcett_at_[hidden])
Date: 2008-02-15 11:24:26
On Fri, Feb 15, 2008 at 10:19 AM, dizzy <dizzy_at_[hidden]> wrote:
>
> On Friday 15 February 2008 17:07:21 Michael Fawcett wrote:
> > On Fri, Feb 15, 2008 at 3:14 AM, Jean-Pierre Bergamin <james_at_[hidden]>
> wrote:
> > > Could there be a way to provide a function object safe_logical_and that
> > > only evaluates the second argument if the first one is true?
> >
> > I've written something like that before as:
<snip code with typos>
> > but if you needed function arguments that weren't available to be
> > bound at and_ construction time you'd have to do some more trickery.
> > This would also scale well using variadic templates.
>
> I don't understand how this code does not evaluate the second argument if the
> first one isn't true (the previous poster explicitely requested that). When
> you construct the above functor evaluation of the expression given for "f1"
> argument will happen which may run into UB, ie the classical "if (p &&
> p->flag)" idiom is broken (and you seem to recognize that... no idea then
> what you ment with the code).
I might be showing my misunderstanding of all the intricacies at work here...
Maybe I am not understanding his intents, or maybe we are talking to
two different points? I have pasted below his original code, modified
to use something like what I posted (and also to have a result when &&
is used).
Are you saying that short-circuit evaluation doesn't happen here, i.e.
the second(t) call happens no matter what?
I thought it was understood that overloading && would have that
effect, and the OP understood that too, which is why he suggested a
safe_logical_and. That means overloading && is out of the question,
which we all seem to agree on, but I am feeling a little silly trying
to figure out why the below code is rubbish.
#include "boost/bind.hpp"
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
using namespace boost;
struct employee {
employee(int id, const string &name) :
id(id), name(name) {}
int id;
string name;
};
ostream &operator<<(ostream &o, const employee &e) {
o << e.id << " - " << e.name << endl;
return o;
}
template <typename F0, typename F1>
struct and_ {
F0 first;
F1 second;
and_(F0 f0, F1 f1) : first(f0), second(f1) { }
template <typename T>
bool operator()(const T &t) const {
return first(t) && second(t);
}
};
template <typename F0, typename F1>
struct or_ {
F0 first;
F1 second;
or_(F0 f0, F1 f1) : first(f0), second(f1) { }
template <typename T>
bool operator()(const T &t) const {
return first(t) || second(t);
}
};
template <typename F0, typename F1>
and_<F0, F1> safe_logical_and(F0 f0, F1 f1) {
return and_<F0, F1>(f0, f1);
}
template <typename F0, typename F1>
or_<F0, F1> safe_logical_or(F0 f0, F1 f1) {
return or_<F0, F1>(f0, f1);
}
int main() {
typedef vector<employee> emp_container;
emp_container staff;
staff.reserve(4);
staff.push_back(employee(1, "John"));
staff.push_back(employee(2, "Paula"));
staff.push_back(employee(3, "Sara"));
staff.push_back(employee(4, "Geroge"));
emp_container::const_iterator e = find_if(staff.begin(), staff.end(),
safe_logical_and(safe_logical_or(bind(&employee::name, _1) ==
"Paula", bind(&employee::name, _1) == "John"),
bind(&employee::id, _1) <= 4));
if (e != staff.end()) {
cout << "Found: " << *e << endl;
}
}
--Michael Fawcett
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net