$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
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