 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
George van den Driessche Guest
|
Posted: Tue Feb 24, 2004 7:29 pm Post subject: Type constraints on 'less' predicates |
|
|
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
|
Posted: Wed Feb 25, 2004 2:58 pm Post subject: Re: Type constraints on 'less' predicates |
|
|
"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
|
Posted: Thu Feb 26, 2004 12:11 am Post subject: Re: Type constraints on 'less' predicates |
|
|
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
|
Posted: Fri Feb 27, 2004 2:18 am Post subject: Re: Type constraints on 'less' predicates |
|
|
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
|
Posted: Sun Feb 29, 2004 5:28 pm Post subject: Re: Type constraints on 'less' predicates |
|
|
[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 |
|
 |
|
|
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
|
|