Boost logo

Boost Users :

From: Daryle Walker (darylew_at_[hidden])
Date: 2008-08-21 19:51:04


On Aug 21, 2008, at 3:48 AM, Daniel Krügler wrote:
> Daryle Walker wrote:
[SNIP]
>> I don't know if what I'm going to say was what David was thinking
>> of, but...
>> If a predicate function object has several "operator ()"
>> overloads, they should be conceptually identical. Ideally, they
>> should be "const" member functions that depend only on the values
>> of the inputs and any internal state data members. Even without
>> that, your predicate class should represent ONE kind of
>> evaluation criteria to pass judgement on. Your nightmare
>> predicate would have to have all the "operator ()" inconsistent
>> with each other, i.e. differing criteria. That would make it
>> useless, considering you can't choose which overload you get in
>> normal use. You can choose a specific version with Stupid C++
>> Tricks involving casting the inputs and/or the member function,
>> but that won't help with generic (template- based) code. Testing
>> operations that aren't the same shouldn't be part of the same
>> predicate class.
>
> Thank you very much for your reply and apologies for my late
> response!
>
> My main concern was that the standard should not be too intrusive,
> but your arguments made me reflect again on this. Users should
> easily be able to separate their predicate "bundle", if their
> see strong need for such a bundle, e.g. instead of
>
> struct S {
> bool (*scmp)(const char*, const char*);
> explicit S(streq_t sc = ...) : scmp(sc) {}
> // Stateless predicate:
> bool operator()(int a, int b) const {
> return a == b;
> }
> ... // other stateless predicates
> // Statefull predicate:
> bool operator()(const char* a, const char* b) const {
> return scmp(a, b);
> }
> };
>
> they could (and probably should) write:
>
> struct SPure {
> // Stateless predicate:
> bool operator()(int a, int b) const {
> return a == b;
> }
> ... // other stateless predicates
> };
>
> struct S : SPure {
> bool (*scmp)(const char*, const char*);
> explicit S(streq_t sc = ...) : scmp(sc) {}
> // Statefull predicate(s):
> bool operator()(const char* a, const char* b) const {
> return scmp(a, b);
> }
> };
>
> Inheritance is neither required nor usually wanted, but
> if some-one *needs* this bundle (because of external
> requirements) she can realize this, if she wants that.

You may have missed something. The state-fulness or statelessness of
a predicate is _irrelevant_ to my point, which was that all the
comparison overloads should have the same effects! Having your "S"
predicate be a root class or divided with a "SPure" base class
doesn't matter. Your integer and string comparisons are probably not
testing the same concept, so they shouldn't be together, no matter
what C++ skills you use to compose them.

struct real_part_negative
{
     bool operator ()( int x ) const { return x < 0; }
     bool operator ()( unsigned x ) const { return false; }
     bool operator ()( float x ) const { return x < 0.0; }
     template < typename T >
     bool operator ()( complex<T> const &x ) const
     { return x.real < static_cast<T>(0); }
};

All these overloads represent the same concept, so it's a consistent
predicate. This is important for generic code, where you can't pick
which overload is used.

-- 
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT hotmail DOT com

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