C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Type constraints on 'less' predicates

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
George van den Driessche
Guest





PostPosted: Tue Feb 24, 2004 7:29 pm    Post subject: Type constraints on 'less' predicates Reply with quote



Standard algorithms such as std::lower_bound() can take a predicate for
ordering elements (such as std::less). This question concerns the
constraints on the types that such a predicate can use.

Suppose, for example, there is some UDT:

struct BigType
{
BigType( int i );
int i;
char someArbitraryData[FAIRLY_LARGE];
};

and a container of them:

std::vector< BigType > v;

Suppose also that I know that v is populated in an order such that its
elements are sorted according to the predicate:

struct BigTypeLess
{
bool operator()( BigType const& a, BigType const& b)
{
return (a.i < b.i);
}
};

The important point here is that someArbitraryData has no significance for
the ordering of BigTypes.

Now, suppose I want to find out whether v contains a value that matches a
particular i and s. I could write:

bool vContains42 = std::binary_search( v.begin(), v.end(), BigType( 42 ),
BigTypeLess() );

But BigType's constructor initialises someArbitraryData in an expensive way
and there's no need to do that because the ordering is dependent only on i.
So I'm wonddering then if it's legal to write the following:

struct BigTypeKeyComp
{
bool operator()( BigType const& a, int b )
{
return a.i < b;
}
bool operator()( int a, BigType const& b )
{
return a < b.i;
}
};

bool vContains42 = std::binary_search( v.begin(), v.end(), 42,
BigTypeKeyComp );

To iterate: is a specific example of a general question - the query applies
equally well to std::lower_bound(), std::equal_range(), std::map and plenty
of other things that involve predicates.

The question really boils down to: can a predicate supplied in such a
situation accept arguments of different types? One upshot of accepting
different types is that (as shown above) operator()() has to be defined with
both orderings of arguments, because at least one standard library
implementation uses expressions such as

less( a, b ) || less( b, a )

in various places.

George



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Dietmar Kuehl
Guest





PostPosted: Wed Feb 25, 2004 2:58 pm    Post subject: Re: Type constraints on 'less' predicates Reply with quote



"George van den Driessche" <no-one (AT) nowhere (DOT) com> wrote:
Quote:
The question really boils down to: can a predicate supplied in such a
situation accept arguments of different types?

The standard does not really seem to specify this: the description of
'std::lower_bound' etc. requires that 'T' be "LessThanComparable" (which is
clearly wrong for the version taking a predicate anyway). The wording in the
standard can both be interpreted as allowing a heterogenous types for the
sequence elements and the search value. The requirement for LessThanComparable
seems to indicate that the types have to be homogenous.

There is a defect on this clause (see
<http://wwwold.dkuug.dk/JTC1/SC22/WG21/docs/lwg-defects.html#270>) but it
seems to address a different issue.

My personal view on this issue is that it is trivially resolved if the
standard library algorithms where specified to use property maps: the
sorting order would be defined using a specific "view", ie. a specific
property map, for the key part while the value or the combination of key and
value would be accessed using a different property map. In this case the
element and value types would be identical but this would not at all be
harmful because the property map for comparison could select just the key
part of the value.
--
<mailto:dietmar_kuehl (AT) yahoo (DOT) com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Dhruv Matani
Guest





PostPosted: Thu Feb 26, 2004 12:11 am    Post subject: Re: Type constraints on 'less' predicates Reply with quote



On Tue, 24 Feb 2004 14:29:54 -0500, George van den Driessche wrote:

Quote:
Standard algorithms such as std::lower_bound() can take a predicate for
ordering elements (such as std::less). This question concerns the
constraints on the types that such a predicate can use.

Suppose, for example, there is some UDT:

struct BigType
{
BigType( int i );
int i;
char someArbitraryData[FAIRLY_LARGE];
};

struct BigTypeKeyComp;

bool vContains42 = std::binary_search( v.begin(), v.end(), 42,
BigTypeKeyComp );

Yes. Why not? I don't see anything wrong with that? In fact, I guess that
such templated Predicate versions were provided for such purposes.



--
Regards,
-Dhruv.

Proud to be a Vegetarian.
http://www.vegetarianstarterkit.com/
http://www.vegkids.com/vegkids/index.html


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Richard Smith
Guest





PostPosted: Fri Feb 27, 2004 2:18 am    Post subject: Re: Type constraints on 'less' predicates Reply with quote

George van den Driessche wrote:
[...]
Quote:
So I'm wonddering then if it's legal to write the following:

struct BigTypeKeyComp
{
bool operator()( BigType const& a, int b )
{
return a.i < b;
}
bool operator()( int a, BigType const& b )
{
return a < b.i;
}
};

bool vContains42 = std::binary_search( v.begin(), v.end(), 42,
BigTypeKeyComp );

I think this is legal (aside from the missing paretheses after
BigTypeKeyComp). The signature of the relevant overload of
std::binary_search is give in 25.3.3.4:

template bool binary_search( ForwardIterator first, ForwardIterator last,
T const& value, Compare comp );

Paragraphs 25.3/2-5 have some general requirements for template
parameters called Compare. One of these requirement is that comp(*i,
*j) (where i and j are iterators) is well formed. This would mean you
would have to add a third operator() that took two BigTypes (though it
wouldn't surprise me if it were never called). This aside, I can see
nothing in these paragraphs to prohibit your comparator which seems to
satisfy all of these. This suggests that your code is legal.

Having said that, I've just fed a slimmed-down version of your code to
the Comeau on-line compiler which fails in some concept checking deep
in the STL. This is intriguing. It's error messages suggest that it
thinks that T and std::iterator_traits<ForwardIterator>::value_type
should be the same type and that comp( value, value ) should be a
legal expression. (I notice Comeau on-line's STL even barfs when T
and the iterator's value_type can be converted between, such as int
and short.)

Paragraph 25/8 is perhaps intended to be relevant here. (It is not
clear because the template parameter is called Compare not
BinaryPredicate.) This says:

Quote:
The BinaryPredicate parameter is used whenever an algorithm
expects a function object that when applied to the result of
dereferencing two corresponding iterators or to dereferencing
an iterator and type T when T is part of the signature
returns a value testable as true. In other words, if an
algorithm takes BinaryPredicate binary_pred as its argument
and first1 and first2 as its iterator arguments, it should
work correctly in the construct if ( binary_pred(*first1,
* first2)){...}. BinaryPredicate always takes the first
iterator type as its first argument, that is, in those cases
when T value is part of the signature, it should work
correctly in the context of if ( binary_pred(*first1, value))
{...}. binary_pred shall not apply any nonconstant function
through the dereferenced iterators.

This seems to suggest that the Standard's intention is certainly to
allow T to be different from the iterator's value_type, and probably
even to allow complicated comparators such as yours.

Quote:
One upshot of accepting
different types is that (as shown above) operator()() has to be defined with
both orderings of arguments, because at least one standard library
implementation uses expressions such

If you believe that the paragraph [25/8] I quote above is relevant
here, the sentence "BinaryPredicate always takes the first iterator
type as its first argument" suggests that you don't need both
versions.

I'd be interested to hear others' opinions on this, as to me it seems
that Comeau on-line is being too strict with its concept checking.

--
Richard Smith

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
David Abrahams
Guest





PostPosted: Sun Feb 29, 2004 5:28 pm    Post subject: Re: Type constraints on 'less' predicates Reply with quote

[email]dietmar_kuehl (AT) yahoo (DOT) com[/email] (Dietmar Kuehl) writes:

Quote:
"George van den Driessche" <no-one (AT) nowhere (DOT) com> wrote:
The question really boils down to: can a predicate supplied in such a
situation accept arguments of different types?

The standard does not really seem to specify this: the description of
'std::lower_bound' etc. requires that 'T' be "LessThanComparable" (which is
clearly wrong for the version taking a predicate anyway). The wording in the
standard can both be interpreted as allowing a heterogenous types for the
sequence elements and the search value. The requirement for LessThanComparable
seems to indicate that the types have to be homogenous.

There is a defect on this clause (see
http://wwwold.dkuug.dk/JTC1/SC22/WG21/docs/lwg-defects.html#270>) but it
seems to address a different issue.

No, it addresses that issue exactly. See
http://wwwold.dkuug.dk/JTC1/SC22/WG21/docs/papers/2001/n1313.html
from which the proposed wording for issue 270 was taken.

Quote:
My personal view on this issue is that it is trivially resolved if the
standard library algorithms where specified to use property maps: the
sorting order would be defined using a specific "view", ie. a specific
property map, for the key part while the value or the combination of key and
value would be accessed using a different property map. In this case the
element and value types would be identical but this would not at all be
harmful because the property map for comparison could select just the key
part of the value.

The problem is that property maps are a nontrivial addition to the
library and the issue is easier to solve without them.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.