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 

Requirements for a binary predicate

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards
View previous topic :: View next topic  
Author Message
Stefan Heinzmann
Guest





PostPosted: Mon May 17, 2004 3:01 am    Post subject: Requirements for a binary predicate Reply with quote



Hi all,

I am unsure what the requirements for a predicate are which is supposed
to be used with std::equal_range, std::lower_bound and similar
algorithms. I am of course talking about the "long" form of the
algorithm which takes the predicate as an explicit argument.

I've got a case where the element in the collection is actually a
key/value pair, but the predicate is supposed to compare the key only.
Now I could in theory do this:

template<typename Key, typename Val>
struct Element {
Key key;
Val val;
};

template<typename Key, typename Val>
struct Predicate {
typedef const Element<Key,Val> Elem;
bool operator()(Elem &e, const Key &k) const { return e.key < k; }
bool operator()(const Key &k, Elem &e) const { return k < e.key; }
};

// pseudo code, somewhere in the application code...
Key k = ...;
std::lower_bound(from_iter, to_iter, key, Predicate<...>());


In other words, the predicate is not comparing equal types. This would
allow me to avoid constructing an element just to pass it to
lower_bound, which would in any case make use of the key only.

GCC 3.3 and VC++ 7.1 accept this, but the Comeau compiler bombs out
because a concept check fails. Is Comeau overly restrictive?

--
Cheers
Stefan

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]

Back to top
James Kuyper
Guest





PostPosted: Tue May 18, 2004 4:42 am    Post subject: Re: Requirements for a binary predicate Reply with quote



[email]stefan_heinzmann (AT) yahoo (DOT) com[/email] (Stefan Heinzmann) wrote in message news:<c88nii$bjb$00$1 (AT) news (DOT) t-online.com>...
Quote:
Hi all,

I am unsure what the requirements for a predicate are which is supposed
to be used with std::equal_range, std::lower_bound and similar
algorithms. I am of course talking about the "long" form of the
algorithm which takes the predicate as an explicit argument.

I've got a case where the element in the collection is actually a
key/value pair, but the predicate is supposed to compare the key only.
Now I could in theory do this:

template<typename Key, typename Val
struct Element {
Key key;
Val val;
};

template struct Predicate {
typedef const Element bool operator()(Elem &e, const Key &k) const { return e.key < k; }
bool operator()(const Key &k, Elem &e) const { return k < e.key; }
};

// pseudo code, somewhere in the application code...
Key k = ...;
std::lower_bound(from_iter, to_iter, key, Predicate<...>());


In other words, the predicate is not comparing equal types. This would
allow me to avoid constructing an element just to pass it to
lower_bound, which would in any case make use of the key only.

GCC 3.3 and VC++ 7.1 accept this, but the Comeau compiler bombs out
because a concept check fails. Is Comeau overly restrictive?

The standard doesn't directly require that the ForwardIterator type
have a value type of T, though it might be argued that this is implied
by the name "ForwardIterator". The standard defines the behavior of
the algorithm in terms of pred(*k,value), which must therefore be a
valid expression, where 'k' is an instance of ForwardIterator, and
value is an instance of T. Your use of the algorithm does conform to
that requirement.

However, it's also required (25.3p3) that 'pred' induce a strict weak
ordering on the values. If *k and value are allowed to be different
types, it's not clear from the description which of the two types it
must induce that ordering on; probably both. Your Predicate class
can't do that for either type, because it doesn't have an operator()
overload that works on two arguments of the same type.

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
Carl Barron
Guest





PostPosted: Tue May 18, 2004 6:30 am    Post subject: Re: Requirements for a binary predicate Reply with quote



In article <c88nii$bjb$00$1 (AT) news (DOT) t-online.com>, Stefan Heinzmann
<stefan_heinzmann (AT) yahoo (DOT) com> wrote:

Quote:
In other words, the predicate is not comparing equal types. This would
allow me to avoid constructing an element just to pass it to
lower_bound, which would in any case make use of the key only.

GCC 3.3 and VC++ 7.1 accept this, but the Comeau compiler bombs out
because a concept check fails. Is Comeau overly restrictive?
[25.3] states that the predicate called comp in this section is a

strict weak ordering. The strict means that !comp(x,x) is all ways
true. This means comp must have two arguments of the same type.

All is not lost if you write an iterator that iterates over your
sequence of your class but points to the key values.

boist::transform_iterator does this but it is not in the standard or
tr1 therefore I skip the details here, but using it or a specialize
hand written iterator over pairs, but 'pointing to' only the
first_type.

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
Stefan Heinzmann
Guest





PostPosted: Tue May 18, 2004 4:57 pm    Post subject: Re: Requirements for a binary predicate Reply with quote

James Kuyper schrieb:
Quote:
stefan_heinzmann (AT) yahoo (DOT) com (Stefan Heinzmann) wrote in message news:<c88nii$bjb$00$1 (AT) news (DOT) t-online.com>...
[...]
template<typename Key, typename Val
struct Element {
Key key;
Val val;
};

template struct Predicate {
typedef const Element bool operator()(Elem &e, const Key &k) const { return e.key < k; }
bool operator()(const Key &k, Elem &e) const { return k < e.key; }
};

// pseudo code, somewhere in the application code...
Key k = ...;
std::lower_bound(from_iter, to_iter, key, Predicate<...>());
[...]
The standard doesn't directly require that the ForwardIterator type
have a value type of T, though it might be argued that this is implied
by the name "ForwardIterator". The standard defines the behavior of
the algorithm in terms of pred(*k,value), which must therefore be a
valid expression, where 'k' is an instance of ForwardIterator, and
value is an instance of T. Your use of the algorithm does conform to
that requirement.

However, it's also required (25.3p3) that 'pred' induce a strict weak
ordering on the values. If *k and value are allowed to be different
types, it's not clear from the description which of the two types it
must induce that ordering on; probably both. Your Predicate class
can't do that for either type, because it doesn't have an operator()
overload that works on two arguments of the same type.

Would that requirement be met if I added a third overload to the
predicate like this?

bool operator()(Elem &a, Elem &b) const { return a.key < b.key; }

I would still pass the key instead of a complete element to the
lower_bound function.

--
Cheers
Stefan

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
John Potter
Guest





PostPosted: Tue May 18, 2004 4:57 pm    Post subject: Re: Requirements for a binary predicate Reply with quote

On Tue, 18 May 2004 04:42:53 +0000 (UTC), [email]kuyper (AT) wizard (DOT) net[/email] (James
Kuyper) wrote:

Quote:
stefan_heinzmann (AT) yahoo (DOT) com (Stefan Heinzmann) wrote in message news:<c88nii$bjb$00$1 (AT) news (DOT) t-online.com>...

I am unsure what the requirements for a predicate are which is supposed
to be used with std::equal_range, std::lower_bound and similar
algorithms. I am of course talking about the "long" form of the
algorithm which takes the predicate as an explicit argument.

I've got a case where the element in the collection is actually a
key/value pair, but the predicate is supposed to compare the key only.
Now I could in theory do this:

template<typename Key, typename Val
struct Element {
Key key;
Val val;
};

template struct Predicate {
typedef const Element bool operator()(Elem &e, const Key &k) const { return e.key < k; }
bool operator()(const Key &k, Elem &e) const { return k < e.key; }
};

// pseudo code, somewhere in the application code...
Key k = ...;
std::lower_bound(from_iter, to_iter, key, Predicate<...>());

In other words, the predicate is not comparing equal types. This would
allow me to avoid constructing an element just to pass it to
lower_bound, which would in any case make use of the key only.

GCC 3.3 and VC++ 7.1 accept this, but the Comeau compiler bombs out
because a concept check fails. Is Comeau overly restrictive?

The standard doesn't directly require that the ForwardIterator type
have a value type of T, though it might be argued that this is implied
by the name "ForwardIterator". The standard defines the behavior of
the algorithm in terms of pred(*k,value), which must therefore be a
valid expression, where 'k' is an instance of ForwardIterator, and
value is an instance of T. Your use of the algorithm does conform to
that requirement.

However, it's also required (25.3p3) that 'pred' induce a strict weak
ordering on the values. If *k and value are allowed to be different
types, it's not clear from the description which of the two types it
must induce that ordering on; probably both. Your Predicate class
can't do that for either type, because it doesn't have an operator()
overload that works on two arguments of the same type.

One of the errors generated involves using the pred for the values.
Adding the compare for two ints clears that error. Adding the compare
for two iterator::value_types does nothing. It is now a strict weak
order for either.

The remaining error is iterator::value_type is not the same type as
value type. Nothing will remove that. Where is that requirement?

John

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
James Kuyper
Guest





PostPosted: Wed May 19, 2004 2:42 pm    Post subject: Re: Requirements for a binary predicate Reply with quote

[email]jpotter (AT) falcon (DOT) lhup.edu[/email] (John Potter) wrote in message news:<AMmqc.20053$KE6.15110 (AT) newsread3 (DOT) news.atl.earthlink.net>...
Quote:
On Tue, 18 May 2004 04:42:53 +0000 (UTC), [email]kuyper (AT) wizard (DOT) net[/email] (James
Kuyper) wrote:
...
The standard doesn't directly require that the ForwardIterator type
have a value type of T, though it might be argued that this is implied
by the name "ForwardIterator". The standard defines the behavior of
...
The remaining error is iterator::value_type is not the same type as
value type. Nothing will remove that. Where is that requirement?

It's not explicitly required; I'm not sure whether we're supposed to
infer such a requirement from the type names. The standard does
specify that we are supposed to infer some requirements from those
names: ForwardIterator is definitely required to be a forward
iterator.

This requirement can be met: create a special iterator that iterates
through Elements, but which has an operator*() which returns a
reference to the Key that is contained in the Element that it points
at.

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
James Kuyper
Guest





PostPosted: Wed May 19, 2004 5:15 pm    Post subject: Re: Requirements for a binary predicate Reply with quote

[email]stefan_heinzmann (AT) yahoo (DOT) com[/email] (Stefan Heinzmann) wrote in message news:<c8cg27$p5$00$1 (AT) news (DOT) t-online.com>...
Quote:
James Kuyper schrieb:
...
However, it's also required (25.3p3) that 'pred' induce a strict weak
ordering on the values. If *k and value are allowed to be different
types, it's not clear from the description which of the two types it
must induce that ordering on; probably both. Your Predicate class
can't do that for either type, because it doesn't have an operator()
overload that works on two arguments of the same type.

Would that requirement be met if I added a third overload to the
predicate like this?

bool operator()(Elem &a, Elem &b) const { return a.key < b.key; }

I would still pass the key instead of a complete element to the
lower_bound function.

I think so. To be safe, add an overload for two Keys, as well.

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
John Potter
Guest





PostPosted: Wed May 19, 2004 5:48 pm    Post subject: Re: Requirements for a binary predicate Reply with quote

On Wed, 19 May 2004 14:42:46 +0000 (UTC), [email]kuyper (AT) wizard (DOT) net[/email] (James
Kuyper) wrote:

Quote:
jpotter (AT) falcon (DOT) lhup.edu (John Potter) wrote in message news:<AMmqc.20053$KE6.15110 (AT) newsread3 (DOT) news.atl.earthlink.net>...

On Tue, 18 May 2004 04:42:53 +0000 (UTC), [email]kuyper (AT) wizard (DOT) net[/email] (James
Kuyper) wrote:

The standard doesn't directly require that the ForwardIterator type
have a value type of T, though it might be argued that this is implied
by the name "ForwardIterator". The standard defines the behavior of

The remaining error is iterator::value_type is not the same type as
value type. Nothing will remove that. Where is that requirement?

It's not explicitly required; I'm not sure whether we're supposed to
infer such a requirement from the type names. The standard does
specify that we are supposed to infer some requirements from those
names: ForwardIterator is definitely required to be a forward
iterator.

This requirement can be met: create a special iterator that iterates
through Elements, but which has an operator*() which returns a
reference to the Key that is contained in the Element that it points
at.

Yes. Either transform (value) or projection (reference) iterator from
boost will do the job.

However, the question in csc++ is whether the library is conformant in
producing concept checks which reject the original code. IMO, concept
checks which reject working code is about as useful as compilers which
run nethack for undefined behavior. There is a difference between
might not work and malicious breakage.

John

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
James Kuyper
Guest





PostPosted: Thu May 20, 2004 6:45 pm    Post subject: Re: Requirements for a binary predicate Reply with quote

[email]jpotter (AT) falcon (DOT) lhup.edu[/email] (John Potter) wrote in message news:<VsMqc.21467$KE6.17835 (AT) newsread3 (DOT) news.atl.earthlink.net>...
Quote:
On Wed, 19 May 2004 14:42:46 +0000 (UTC), [email]kuyper (AT) wizard (DOT) net[/email] (James
Kuyper) wrote:

[email]jpotter (AT) falcon (DOT) lhup.edu[/email] (John Potter) wrote in message news:<AMmqc.20053$KE6.15110 (AT) newsread3 (DOT) news.atl.earthlink.net>...

On Tue, 18 May 2004 04:42:53 +0000 (UTC), [email]kuyper (AT) wizard (DOT) net[/email] (James
Kuyper) wrote:

The standard doesn't directly require that the ForwardIterator type
have a value type of T, though it might be argued that this is implied
by the name "ForwardIterator". The standard defines the behavior of

The remaining error is iterator::value_type is not the same type as
value type. Nothing will remove that. Where is that requirement?

It's not explicitly required; I'm not sure whether we're supposed to
infer such a requirement from the type names. The standard does
specify that we are supposed to infer some requirements from those
names: ForwardIterator is definitely required to be a forward
iterator.
...
However, the question in csc++ is whether the library is conformant in
producing concept checks which reject the original code. IMO, concept
checks which reject working code is about as useful as compilers which
run nethack for undefined behavior. There is a difference between
might not work and malicious breakage.

Agreed. However, since I can see a way to read the standard as
imposing that requirement, I'm willing to give them the benefit of the
doubt and say that it's not malicious. They might even be correct, in
which case it doesn't even count as breakeage.

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
John Potter
Guest





PostPosted: Fri May 21, 2004 3:10 am    Post subject: Re: Requirements for a binary predicate Reply with quote

On Thu, 20 May 2004 18:45:06 +0000 (UTC), [email]kuyper (AT) wizard (DOT) net[/email] (James
Kuyper) wrote:

Quote:
Agreed. However, since I can see a way to read the standard as
imposing that requirement, I'm willing to give them the benefit of the
doubt and say that it's not malicious.

Sorry for forgetting the history of this. See lwg issue 270. Who knows
what is allowed today, but the WP says the original code will be valid
in the future.

Here is another interesting, not malicious, version.

struct P { int x, y; };
bool operator< (int lhs, P const& rhs) { return lhs < rhs.x; }
bool operator< (P const& lhs, int rhs) { return lhs.x < rhs; }
void f (vector
I know that there exists an STL implementation which will not
accept this code. It is good programming practice not any attempt
to enforce maybe rules. The same implementation will accept the
code using a function object. It seems that issue 270 will make
the operator< version non-conforming.

John

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
David Abrahams
Guest





PostPosted: Wed May 26, 2004 6:00 pm    Post subject: Re: Requirements for a binary predicate Reply with quote

[email]stefan_heinzmann (AT) yahoo (DOT) com[/email] (Stefan Heinzmann) writes:

Quote:
Hi all,

I am unsure what the requirements for a predicate are which is
supposed to be used with std::equal_range, std::lower_bound and
similar algorithms. I am of course talking about the "long" form of
the algorithm which takes the predicate as an explicit argument.

I've got a case where the element in the collection is actually a
key/value pair, but the predicate is supposed to compare the key
only. Now I could in theory do this:

template<typename Key, typename Val
struct Element {
Key key;
Val val;
};

template struct Predicate {
typedef const Element bool operator()(Elem &e, const Key &k) const { return e.key < k; }
bool operator()(const Key &k, Elem &e) const { return k < e.key; }
};

// pseudo code, somewhere in the application code...
Key k = ...;
std::lower_bound(from_iter, to_iter, key, Predicate<...>());


In other words, the predicate is not comparing equal types. This would
allow me to avoid constructing an element just to pass it to
lower_bound, which would in any case make use of the key only.

GCC 3.3 and VC++ 7.1 accept this, but the Comeau compiler bombs out
because a concept check fails. Is Comeau overly restrictive?

I think
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2001/n1313.html
addresses your question. The proposed wording from this paper (with
minor changes) is current for
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#270 which
has WP status.

--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards 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.