Topic: Convertible to T


Author: chris <chris@bubblescope.net>
Date: Mon, 20 Sep 2004 23:26:08 CST
Raw View
> Yes.  It allows *a to be a proxy, so a can also be an output iterator.
>
>
>>When using input iterators should I write
>>T(*a) all over the place to be sure that the object i'm using is the
>>class I expect?
>
>
> If you need to be sure, then yes.  Usually you don't need to be sure ;-)
>
> static_cast<T&>(*a) would often be more efficient and slightly safer.
>

Thank you.

However, I notice that every std library I have access to doesn't make
these kind of casts.

While I can see some arguments behind things being "convertable to T" (I
understand it is necessary for some output iterator-related business), I
don't understand why many things are allowed to be "convertable to
bool". Seeing as iterators are such a fundamental part of the standard
library, it seems strange to me that it is possible to write iterators
which are standard-complying but fail in all implementations of the
standard library, and these are simply brushed away as being "people
shouldn't write such code", where I have seen many examples of people
pushing the C++ standard to it's limits.

At the very least, I can see no reason to not replace all mentions of
"convertable to bool" to at least "one of the bool,int,char,etc.." and
list all the standard built-in types (I believe this convertable to bool
is allowed so that implementations could return say an int and avoid an
unnessary conversion. However all implementations I have seen simply
return a bool anyway.

I don't know how to remove / reduce the "convertable to T" problems. At
the least the standard could say that behaviour is undefined unless the
code acts the same if a static_cast<T&>(*a) is put around (except in
functions relating to output iterators).

Chris

---
[ 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                       ]





Author: chris <chris@bubblescope.net>
Date: Mon, 20 Sep 2004 23:28:05 CST
Raw View
David Abrahams wrote:
..
>
>>When using input iterators should I write
>>T(*a) all over the place to be sure that the object i'm using is the
>>class I expect?
>
>
> If you need to be sure, then yes.  Usually you don't need to be sure ;-)
>
> static_cast<T&>(*a) would often be more efficient and slightly safer.
>

I would have thought this, however I look through the standard library
implementations I have access to (g++, icc and STLport) and none seem to
have any static_casts in.

I have now discussed this in a few places, and would really like to see
a change to the standard with regards this.

Consider for example the following line of code, where a and b are input
iterators over int. This means that according to the standard "a!=b" is
convertable to bool and *a is convertable to int.

while(a!=b && *a!=0);

This seems a perfectly reasonable way of searching through a stream of
ints until we either reach the end or find a 0. However according to the
standard, it has (I believe) the following problems.

1) 'a!=b' only has to return a type convertable to bool. Whatever this
type is I could overload && on this operator. This would mean no matter
what the result of a!=b, *a!=0 would be executed, which could lead to
illegally derefencing an iterator (if for example b was end-of-stream).

2) While *a must be convertable to int, there is no reason I can't
define an operator!= between whatever type *a is and 0, and more
disturbingly design it in an unexpected manner.

While these are both clearly stupid things to do, they both appear
legal. Also code which makes similar assumptions to these seem to exist
in all the standard library implementations I have access to.

It appears this has been discussed previously and it was decided that
the issue would be too complicated to fix, and users should simply "not
write stupid code". However seeing as how basic iterators are to c++, it
seems suprising that such an area of strangeness exists.

While I'm not certain of how to fix this in a sensible manner, it seems
that fixing by being overly restrictive would be better than not at all,
as at least then it would be possible to write code without filling it
with casts (which I don't imagine was the intention of the writers of
the standard) or simply hoping that people only write "sensible code".

As a simple example of this occuring, the following the body of g++'s
implementation of mismatch.

while (__first1 != __last1 && *__first1 == *__first2) {..}

icc's contains for(;__first1 != __last1 && *__first1 == *__first2;) {..}

Both of these would appear to not be standards complient if I overloaded
&& in the return value of __first1!=__last1.

The main reason I bring this up is that it makes writing "torture tests"
for iterators and algorithms very difficult, as what exactly are they
allowed to do?

The obvious answer is for the standard libraries to static_cast
everywhere, but this does not seem like a pleasent fix.

Thank you for reading to the end of this message :)

Chris

---
[ 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                       ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Tue, 21 Sep 2004 13:45:32 GMT
Raw View
chris <chris@bubblescope.net> writes:

> As a simple example of this occuring, the following the body of g++'s
> implementation of mismatch.
>
> while (__first1 != __last1 && *__first1 == *__first2) {..}
>
> icc's contains for(;__first1 != __last1 && *__first1 == *__first2;) {..}
>
> Both of these would appear to not be standards complient if I
> overloaded && in the return value of __first1!=__last1.
>
> The main reason I bring this up is that it makes writing "torture
> tests" for iterators and algorithms very difficult, as what exactly
> are they allowed to do?
>
> The obvious answer is for the standard libraries to static_cast
> everywhere, but this does not seem like a pleasent fix.

I agree that in this case the implementations have a bug.  I don't
know if pleasantness is an appropriate criterion for deciding whether
to ask standard library implementors to conform to the standard, but
given that this convertiblity to bool makes it hard for _anyone_ to
write bullet-proof generic code, maybe we should reconsider the
"convertible to bool" requirement.

Matt, do you want to add this one to the issues list?

--
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                       ]





Author: ben-public-nospam@decadentplace.org.uk (Ben Hutchings)
Date: Tue, 21 Sep 2004 17:37:43 GMT
Raw View
chris wrote:
>> Yes.  It allows *a to be a proxy, so a can also be an output iterator.
>>
>>
>>>When using input iterators should I write
>>>T(*a) all over the place to be sure that the object i'm using is the
>>>class I expect?
>>
>>
>> If you need to be sure, then yes.  Usually you don't need to be sure ;-)
>>
>> static_cast<T&>(*a) would often be more efficient and slightly safer.
>>
>
> Thank you.
>
> However, I notice that every std library I have access to doesn't make
> these kind of casts.
>
> While I can see some arguments behind things being "convertable to T" (I
> understand it is necessary for some output iterator-related business), I
> don't understand why many things are allowed to be "convertable to
> bool". Seeing as iterators are such a fundamental part of the standard
> library, it seems strange to me that it is possible to write iterators
> which are standard-complying but fail in all implementations of the
> standard library, and these are simply brushed away as being "people
> shouldn't write such code", where I have seen many examples of people
> pushing the C++ standard to it's limits.
<snip>

The approach TR1 takes to making classes testable by conversion to
bool but not comparable through the bool conversion is:

- specify a conversion operator that converts to an unspecified type
  with a standard conversion to bool
- specify declaration but not definition of operator== and
  operator!= for the class

(see [tr.func.wrap.func.cap], [tr.func.wrap.func.undef]).

Perhaps we will see this careful limitation of conversions extended to
the standard library in the next version of the standard.

--
Ben Hutchings
The generation of random numbers is too important to be left to chance.

---
[ 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                       ]





Author: chris@bubblescope.net (chris)
Date: Thu, 16 Sep 2004 16:25:17 GMT
Raw View
Hello,

I have been reading the c++ standard recently, in particular the part
about input iterators. I note that given an input iterator a for type T,
then *a only has to be "convertable to T", not actually of type T.

Firstly, I can't seem to find an exact definition of "convertable to T".
While I assume it is the obvious definition (an implicit conversion), I
can't find an exact definition. Is there one?

Slightly more worryingly, there doesn't seem to be any restriction on
the this type, other than it is "convertable to T". Consider two input
iterators a and b. I would personally assume that most people would
expect *a==*b would perform T(*a)==T(*b), however it doesn't seem that
the standard requires that, and that whatever type *a is (call it U)
could have == defined on it with totally different symantics and still
be a valid inputer iterator.

Is this a correct reading? When using input iterators should I write
T(*a) all over the place to be sure that the object i'm using is the
class I expect?

Chris

---
[ 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                       ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Thu, 16 Sep 2004 23:09:53 GMT
Raw View
chris@bubblescope.net (chris) writes:

> Hello,
>
> I have been reading the c++ standard recently, in particular the part
> about input iterators. I note that given an input iterator a for type
> T, then *a only has to be "convertable to T", not actually of type T.
>
> Firstly, I can't seem to find an exact definition of "convertable to
> T". While I assume it is the obvious definition (an implicit
> conversion), I can't find an exact definition. Is there one?
>
> Slightly more worryingly, there doesn't seem to be any restriction on
> the this type, other than it is "convertable to T". Consider two input
> iterators a and b. I would personally assume that most people would
> expect *a==*b would perform T(*a)==T(*b), however it doesn't seem that
> the standard requires that, and that whatever type *a is (call it U)
> could have == defined on it with totally different symantics and still
> be a valid inputer iterator.
>
> Is this a correct reading?

Yes.  It allows *a to be a proxy, so a can also be an output iterator.

> When using input iterators should I write
> T(*a) all over the place to be sure that the object i'm using is the
> class I expect?

If you need to be sure, then yes.  Usually you don't need to be sure ;-)

static_cast<T&>(*a) would often be more efficient and slightly safer.

HTH,
--
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                       ]