Topic: basic_ios:: why operator void*() instead of operator bool()
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/07/01 Raw View
Jerry Coffin wrote:
>
> In article <MPG.11e304ed5b0ca1719896c3@news.teleport.com>,
> smeyers@aristeia.com says...
>
> [ ... ]
>
> > In my mind, this leads to two questions:
> > 1. *Are* the rules as Christopher and Valentin have described them?
> > That is, is it valid to compare cin and cout if both have implicit
> > conversions to different pointer types (because both pointer types
> > can be implicitly converted to void*)?
> > 2. If so, am I the only one who feels that this is very bad?
>
> Hmm...I haven't looked things up again, but as I recall, only ONE
> implicit conversion will be done per operand in a given operation.
One implicit conversion sequence, which typically
consists of many conversions.
--
Valentin Bonnard
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: smeyers@aristeia.com (Scott Meyers)
Date: 1999/06/28 Raw View
After removing a bunch of attributions, we have:
> > > Please let me bring again that trick of Don Box: he uses a conversion
> > > to an unique incomplete type:
> > >
> > > class X
> > > {
> > > class Undefined;
> > > operator Undefined* ()
> > > { return reinterpret_cast<Undefined*>(some-condition); }
> > > };
> > >
> > > This will issue a compile-time error if cin and cout defined
> > > conversions to different types.
> >
> > I doubt so:
> >
> > Conversion from X to X::Undefined* is an user defined conversion.
> > Conversion from X::Undefined* to void* is a language defined
> > conversion. Each user defined conversion may be followed by a language
> > defined conversion in an implicit cast (this is what causes the
> > problems with bool). So cin==cout would resolve to
> > (void*)(istream::unique*)cin==(void*)(ostream::unique*)cout which is
> > clearly not a compile error.
Without even looking at the standard, I can't imagine this is supposed to
be true. Consider the following:
int *pInt;
double *pDouble;
if (pInt == pDouble) ... // error, can't compare int* and double*
Unless I'm really off in LooneyLand, this shouldn't compile, not in C, not
in C++. Certainly we don't expect both pointers to be converted to void*
for purposes of comparison.
Assuming what I just wrote is true, the same thing applies to the types
istream::unique* and ostream::unique*. They're built-in pointer types and
they're not comparable.
Right? RIGHT? Please tell me I'm right...
Scott
--
Scott Meyers, Ph.D. smeyers@aristeia.com
Software Development Consultant http://www.aristeia.com/
Visit http://meyerscd.awl.com/ to demo the Effective C++ CD
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/06/28 Raw View
Scott Meyers wrote:
> Without even looking at the standard, I can't imagine this is supposed to
> be true.
I can imagine that it is true.
> Assuming what I just wrote is true, the same thing applies to the types
> istream::unique* and ostream::unique*. They're built-in pointer types and
> they're not comparable.
>
> Right? RIGHT? Please tell me I'm right...
Sorry, no. You are considering another problem.
In this thread we want to compare cout and cin, we aren't
trying to compare values of pointer type.
--
Valentin Bonnard
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: smeyers@aristeia.com (Scott Meyers)
Date: 1999/06/30 Raw View
> In this thread we want to compare cout and cin, we aren't
> trying to compare values of pointer type.
I understand that. My argument is this: if an operation on built-in
pointer types is not valid in C, it shouldn't be valid in C++, either, not
even as part of a conversion sequence originating from a non-C construct.
In the case under discussion, it would not be legal to compare cin::inner*
and cout::inner* by themselves in C (I'm ignoring that they are nested
types -- the point is more general than that), so it should not be legal to
compare them as part of a conversion sequence that originates in an attempt
to compare cin and cout.
In my mind, this leads to two questions:
1. *Are* the rules as Christopher and Valentin have described them?
That is, is it valid to compare cin and cout if both have implicit
conversions to different pointer types (because both pointer types
can be implicitly converted to void*)?
2. If so, am I the only one who feels that this is very bad?
Scott
--
Scott Meyers, Ph.D. smeyers@aristeia.com
Software Development Consultant http://www.aristeia.com/
Visit http://meyerscd.awl.com/ to demo the Effective C++ CD
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/06/30 Raw View
Scott Meyers wrote:
>
> After removing a bunch of attributions, we have:
>
> > > > Please let me bring again that trick of Don Box: he uses a conversion
> > > > to an unique incomplete type:
> > > >
> > > > class X
> > > > {
> > > > class Undefined;
> > > > operator Undefined* ()
> > > > { return reinterpret_cast<Undefined*>(some-condition); }
> > > > };
> > > >
> > > > This will issue a compile-time error if cin and cout defined
> > > > conversions to different types.
> > >
> > > I doubt so:
> > >
> > > Conversion from X to X::Undefined* is an user defined conversion.
> > > Conversion from X::Undefined* to void* is a language defined
> > > conversion. Each user defined conversion may be followed by a language
> > > defined conversion in an implicit cast (this is what causes the
> > > problems with bool). So cin==cout would resolve to
> > > (void*)(istream::unique*)cin==(void*)(ostream::unique*)cout which is
> > > clearly not a compile error.
>
> Without even looking at the standard, I can't imagine this is supposed to
> be true. Consider the following:
>
> int *pInt;
> double *pDouble;
>
> if (pInt == pDouble) ... // error, can't compare int* and double*
>
> Unless I'm really off in LooneyLand, this shouldn't compile, not in C, not
> in C++. Certainly we don't expect both pointers to be converted to void*
> for purposes of comparison.
>
> Assuming what I just wrote is true, the same thing applies to the types
> istream::unique* and ostream::unique*. They're built-in pointer types and
> they're not comparable.
>
> Right? RIGHT? Please tell me I'm right...
The point is that we are _not_ comparing a cin::unique* with
a cout::unique* (which AFAIK would be ill-formed), but a cin
with an cout.
I don't have the standard, but:
>From CD2 (I've added analysis for the current problem with //)
13.3.1.2 Operators in expressions [over.match.oper]
1 If no operand of an operator in an expression has a type that is a
class or an enumeration, the operator is assumed to be a built-in
operator and interpreted according to clause _expr_.
// cin and cout are both class type, so this doesn't apply
[...]
2 If either operand has a type that is a class or an enumeration, a
user-defined operator function might be declared that implements this
operator or a user-defined conversion can be necessary to convert the
operand to a type that is appropriate for a built-in operator. In
this case, overload resolution is used to determine which operator
function or built-in operator is to be invoked to implement the opera-
tor. Therefore, the operator notation is first transformed to the
equivalent function-call notation as summarized in Table 1 (where @
denotes one of the operators covered in the specified subclause).
Table 1--relationship between operator and function call notation
+--------------+------------+--------------------+------------------------+
|Subclause | Expression | As member function | As non-member
function |
+--------------+------------+--------------------+------------------------+
|_over.unary_ | @a | (a).operator@ () | operator@
(a) |
|_over.binary_ | a@b | (a).operator@ (b) | operator@ (a,
b) |
|_over.ass_ | a=b | (a).operator= (b)
| |
|_over.sub_ | a[b] | (a).operator[](b)
| |
|_over.ref_ | a-> | (a).operator-> ()
| |
|_over.inc_ | a@ | (a).operator@ (0) | operator@ (a,
0) |
+--------------+------------+--------------------+------------------------+
// In this case, we get
// cin.operator==(cout)
// operator==(cin, cout)
3 For a unary operator @ with an operand of type T1 or reference to cv
T1, and for a binary operator @ with a left operand of type T1 or ref-
erence to cv T1 and a right operand of type T2 or reference to cv T2,
three sets of candidate functions, designated member candidates, non-
member candidates and built-in candidates, are constructed as follows:
--If T1 is a class type, the set of member candidates is the result of
the qualified lookup of T1::operator@ (_over.call.func_); otherwise,
the set of member candidates is empty.
// No candidate here
--The set of non-member candidates is the result of the unqualified
lookup of operator@ in the context of the expression according to
the usual rules for name lookup in unqualified function calls
(_basic.lookup.koenig_) except that all member functions are
ignored.
// No candidate here
--For the operator ,, the unary operator &, or the operator ->, the
built-in candidates set is empty. For all other operators, the
built-in candidates include all of the candidate operator functions
defined in _over.built_ that, compared to the given operator,
--have the same operator name, and
--accept the same number of operands, and
--accept operand types to which the given operand or operands can be
converted according to _over.best.ics_.
// according to 13.6, the "==" candidate functions are
// void operator==(T*, T*) for any type T
// (and non-pointer ==, which isn't interesting here)
//
// There exist conversion sequences
// istream -> istream::unique* -> void*
// and
// ostream -> ostream::unique*-> void*
// and
// (void*)cin == (void*)cout
// is a legal expression, so operator==(void*, void*) is a candidate.
// There's no other candidate.
4 For the built-in assignment operators, conversions of the left operand
are restricted as follows:
[...]
// does not apply
5 For all other operators, no such restrictions apply.
// Nothing to do ;-)
6 The set of candidate functions for overload resolution is the union of
the member candidates, the non-member candidates, and the built-in
candidates. The argument list contains all of the operands of the
operator. The best function from the set of candidate functions is
selected according to _over.match.viable_ and _over.match.best_.8)
// So if my analysis above was valid, cin==cout indeed
// should compile.
//
// Of course, this doesn't affect the (in)validity of
// (istream::unique*)cin == (ostream::unique*)cout
Of course, this analysis is according to CD2, so something
may have changed for the final standard; also I may have
made an error in the analysis; however if I didn't make
a mistake, the expression
cin == cout
would be valid even with conversions to cin::unique* and
cout::unique*.
Of course it's strange if this line compiles through
conversion operators to istream::unique* and ostream::unique*,
but only if those are invoked implicitly (or the cast to
void is done explicitly, too).
This could probably be fixed by demanding that for
builtin operator candidates, the conversion sequence
must end at the first builtin type, and a prototype is
considered for each valid combination of builtin types.
That is, the conversion would end at istream::unique*
and ostream::unique* (making cin==cout illegal), but
besides operator==(T*, T*), also operator==(void*, T*),
operator==(T*, void*), operator==(Base*, Derived*), etc.
are valid candidates, since the corresponding operations
are valid if directly using those pointers.
(The second addition would be necessary to allow things
like:)
struct X { operator Base*(); };
struct Y { operator Derived*(); };
X x;
Y y;
x==y; // would be ruled out by "stop rule" otherwise, since
// Derived* -> Base* is conversion between builtin types
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Bill Wade" <bill.wade@stoner.com>
Date: 1999/06/30 Raw View
Scott Meyers wrote in message ...
>Without even looking at the standard, I can't imagine this is supposed to
>be true. Consider the following:
>
> int *pInt;
> double *pDouble;
>
> if (pInt == pDouble) ... // error, can't compare int* and double*
>
>Unless I'm really off in LooneyLand, this shouldn't compile, not in C, not
>in C++. Certainly we don't expect both pointers to be converted to void*
>for purposes of comparison.
>
>Assuming what I just wrote is true, the same thing applies to the types
>istream::unique* and ostream::unique*. They're built-in pointer types and
>they're not comparable.
>
>Right? RIGHT? Please tell me I'm right...
For a user-defined operator== you would be wrong, but you can't write a
user-defined operator== that takes two pointer arguments (unless there is
some obscure way to do this with template magic).
So, you are right. The pointer conversion rules for built-in relational
operators, 5.9 (and the equality operator, 5.10), only allow one of the
pointers to change its underlying type (all of the const volatile stuff can
change for both pointers). 5.9 says the type that is finally compared must
be "similar (4.4)" to one of the actual operands. The definition of similar
does not allow pointer to base or pointer to void conversions.
So when comparing
cv1 void* to cv2 something*
both pointers are converted to
cv12 void*
When comparing
cv1 base* to cv2 derived*
both pointers are converted to
cv12 base*
But for
class der1: public base {};
class der2: public base {};
comparing der1* to der2* requires an explicit cast (presumably to void* or
base*) of at least one of the arguments.
You should get a compile error from the following program fragment.
struct base{};
struct d1: base {};
struct d2: base {};
d1 d_1;
d2 d_2;
&d_1 == &d_2; // Not allowed.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/06/30 Raw View
smeyers@aristeia.com (Scott Meyers) writes:
>[...] this leads to two questions:
> 1. *Are* the rules as Christopher and Valentin have described them?
> That is, is it valid to compare cin and cout if both have implicit
> conversions to different pointer types (because both pointer types
> can be implicitly converted to void*)?
Their analysis looks correct to me.
> 2. If so, am I the only one who feels that this is very bad?
It's certainly bad, IMHO. I don't think I'd go so far as to say that it is
_very_ bad, though.
Compilers are of course free to issue warnings whenever they like;
cases like this would be a good time to issue a warning.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jcoffin@taeus.com (Jerry Coffin)
Date: 1999/06/30 Raw View
In article <MPG.11e304ed5b0ca1719896c3@news.teleport.com>,
smeyers@aristeia.com says...
[ ... ]
> In my mind, this leads to two questions:
> 1. *Are* the rules as Christopher and Valentin have described them?
> That is, is it valid to compare cin and cout if both have implicit
> conversions to different pointer types (because both pointer types
> can be implicitly converted to void*)?
> 2. If so, am I the only one who feels that this is very bad?
Hmm...I haven't looked things up again, but as I recall, only ONE
implicit conversion will be done per operand in a given operation.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James.Kanze@dresdner-bank.com
Date: 1999/06/23 Raw View
In article <37676711.BFA38365@physik.tu-muenchen.de>,
Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:
> Andrei Alexandrescu wrote:
> >
> > In article <7jot7u$o3k$1@nnrp1.deja.com>,
> > James.Kanze@dresdner-bank.com wrote:
> > > No. We'd like for cin==cout to be a compile time error. The
easiest
> > > way of doing this is for cin and cout to convert to distinct
pointer
> > > types, and return unique values for each pointer. Failing that,
> > > however, I agree that the only reasonable solution is for operator
> > void*
> > > to return this.
> >
> > Please let me bring again that trick of Don Box: he uses a
conversion to
> > an unique incomplete type:
> >
> > class X
> > {
> > class Undefined;
> > operator Undefined* ()
> > { return reinterpret_cast<Undefined*>(some-condition); }
> > };
> >
> > This will issue a compile-time error if cin and cout defined
conversions
> > to different types.
>
> I doubt so:
>
> Conversion from X to X::Undefined* is an user defined conversion.
> Conversion from X::Undefined* to void* is a language defined
> conversion.
> Each user defined conversion may be followed by a language defined
> conversion in an implicit cast (this is what causes the problems
> with bool).
> So cin==cout would resolve to
> (void*)(istream::unique*)cin==(void*)(ostream::unique*)cout
> which is clearly not a compile error.
The conversions are legal, but the compiler shouldn't use them here.
Section 5.10 states: "The == (equal to) and the != (not equal to)
operators have the same semantic restrictions, conversions, and result
type as the relational operators except for their lower precedence and
truth-value result." And according to 5.9/2: "Pointer conversions and
qualification conversions are performed on pointer operands (or on a
pointer operand and a null pointer constant) to bring them to their
composite pointer type. If one operand is a null pointer constant, the
composite pointer type is the type of the other operand. Otherwise, if
one of the operands has type "pointer to cv1 void", then the other has
type "pointer to cv2 T" and the composite pointer type is "pointer to
cv12 void", where cv12 is the union of cv1 and cv2. Otherwise, the
composite pointer type is a pointer type similar to the type of one of
the operands, with a cv-qualification signature that is the union of the
cv-qualification signatures of the operand types."
There is no composite pointer type which can be applied to
istream::unique* and ostream::unique*, so the expression is illegal.
For that matter: in 5.9/1 it says: "The operands shall have arithmetic,
enumeration or pointer type." Not "must be convertible to...", but
"must have". It would seem to me that this would make cin==cout illegal
even now. But does this really mean what it says: if I have a user
defined type which converts to an int, is userDefined==0 illegal?
--
James Kanze mailto:
James.Kanze@dresdner-bank.com
Conseils en informatique orientie objet/
Beratung in objekt orientierter
Datenverarbeitung
Ziegelh|ttenweg 17a, 60598 Frankfurt, Germany Tel. +49 (069) 63 19 86
27
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/06/23 Raw View
James.Kanze@dresdner-bank.com wrote:
>
> In article <37676711.BFA38365@physik.tu-muenchen.de>,
> Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:
> > Andrei Alexandrescu wrote:
> > >
> > > In article <7jot7u$o3k$1@nnrp1.deja.com>,
> > > James.Kanze@dresdner-bank.com wrote:
> > > > No. We'd like for cin==cout to be a compile time error. The
> easiest
> > > > way of doing this is for cin and cout to convert to distinct
> pointer
> > > > types, and return unique values for each pointer. Failing that,
> > > > however, I agree that the only reasonable solution is for operator
> > > void*
> > > > to return this.
> > >
> > > Please let me bring again that trick of Don Box: he uses a
> conversion to
> > > an unique incomplete type:
> > >
> > > class X
> > > {
> > > class Undefined;
> > > operator Undefined* ()
> > > { return reinterpret_cast<Undefined*>(some-condition); }
> > > };
> > >
> > > This will issue a compile-time error if cin and cout defined
> conversions
> > > to different types.
> >
> > I doubt so:
> >
> > Conversion from X to X::Undefined* is an user defined conversion.
> > Conversion from X::Undefined* to void* is a language defined
> > conversion.
> > Each user defined conversion may be followed by a language defined
> > conversion in an implicit cast (this is what causes the problems
> > with bool).
> > So cin==cout would resolve to
> > (void*)(istream::unique*)cin==(void*)(ostream::unique*)cout
> > which is clearly not a compile error.
>
> The conversions are legal, but the compiler shouldn't use them here.
> Section 5.10 states: "The == (equal to) and the != (not equal to)
> operators have the same semantic restrictions, conversions, and result
> type as the relational operators except for their lower precedence and
> truth-value result." And according to 5.9/2: "Pointer conversions and
> qualification conversions are performed on pointer operands (or on a
> pointer operand and a null pointer constant) to bring them to their
> composite pointer type. If one operand is a null pointer constant, the
> composite pointer type is the type of the other operand. Otherwise, if
> one of the operands has type "pointer to cv1 void", then the other has
> type "pointer to cv2 T" and the composite pointer type is "pointer to
> cv12 void", where cv12 is the union of cv1 and cv2.
Up to hre, no problem; unfortunately, this is not applicable here,
so we have to look at the following:
> Otherwise, the
> composite pointer type is a pointer type similar to the type of one of
> the operands, with a cv-qualification signature that is the union of the
> cv-qualification signatures of the operand types."
What is "a pointer type similar to the type of one of the
operands"? Does the standard define similarity of pointers
somewhere?
However, I think even this is not applicable, see below.
>
> There is no composite pointer type which can be applied to
> istream::unique* and ostream::unique*, so the expression is illegal.
But the operand types are not istream::unique* and ostream::unique*,
but istream and ostream. So I'd conclude that either cin==cout
is disallowed completely (since neither cin nor cout is of a
suitable type for built-in operator new, and no suitable
user defined operator== exists), or cin==cout is allowed through
an allowed implicit conversion sequence which leads to types
that are allowed for builtin operator== (conversion to void*
for both _is_ such a sequence, as shown above; and comparing
two void* is allowed). The fact that another set of conversion
sequences exists (namely istream->istream::unique* and
ostream->ostream::unique*) where the call is illegal is IMHO
irrelevant. Otherwise, the following code shouldn't compile
either:
struct X
{
operator int();
struct foo {};
operator foo();
};
struct Y
{
operator int();
struct foo {};
operator foo();
};
X x;
Y y;
int main()
{
return x==y;
}
Here, conversions X -> X::foo() and Y -> Y::foo exist, for which
no == is defined; should this therefore fail?
However, I now can think of _one_ reason why the unique*
solution might work anyway:
(istream->istream::unique*, ostream->void*) and
(istream->void*, ostream->ostream::unique*) are both conversion
sequence pairs which result in callable operator== - maybe then
with "unique" pointers, cin==cout should fail due to ambiguity?
>
> For that matter: in 5.9/1 it says: "The operands shall have arithmetic,
> enumeration or pointer type." Not "must be convertible to...", but
> "must have". It would seem to me that this would make cin==cout illegal
> even now. But does this really mean what it says: if I have a user
> defined type which converts to an int, is userDefined==0 illegal?
Good question. I hope not...
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/06/24 Raw View
The rules for user defined types are different
from the rules for builtin types.
User defined types use overloading rules with
pseudo prototypes for built-in operators (like
bool operator== (T*, T*) for every T), while
builtin types use C-like promotion and
conversion rules.
Consider:
bool foo (T*, T*); // for every T
foo (cout, cin);
The viable calls would be:
ostream -> ostream::magic* -> void*
istream -> istream::magic* -> void*
foo (void*, void*);
ostream -> ostream::magic* -> const void*
istream -> istream::magic* -> const void*
foo (const void*, const void*);
Since ostream::magic* -> void* is better
than ostream::magic* -> const void*, the first
alternative is choosen.
Unless I have missed something, of course.
--
Valentin Bonnard
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Ed Brey" <brey@afd.mke.etn.com>
Date: 1999/06/23 Raw View
David R Tribble <dtribble@technologist.com> wrote in message
news:376EBD5F.79B4FCCC@technologist.com...
>
> AllanW wrote:
> while ( { int ch; ch = cin.get(), ch != '\n' and ch != EOF; } )
> ...
>
> Ack. On second thought, maybe not. Loop-local variables for
> anything more complex than a single array index or pointer appear
> to be a bad idea. You can always wrap the thing in another set
> of braces, after all.
Furthermore, you're encroaching on a domain that "for" already handles well:
for (int ch; ch = cin.get(), ch != '\n' && ch != EOF;)
...
To me, this fits well with the "spirit" of the for construct, since ch is
constructed initially, and then reused in subsequent passes through the
loop. It makes sense to initialize ch in the initialization section.
If there is a problem with reusing a variable between loop iterations,
existing constructs still provide clear and reasonably concise code:
for (;;)
{
int ch(cin.get());
if (ch == '\n' || ch == EOF)
break;
...
}
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/06/23 Raw View
On 16 Jun 99 17:12:22 GMT, Fergus Henderson <fjh@cs.mu.OZ.AU> wrote:
>James.Kanze@dresdner-bank.com writes:
>C and C++ already have a concise syntax for that:
>
> while ( cin >> myValue, ! cin.fail() ) ...
Frankly, I find this more intelligible
while (true) {
int myValue;
cin >> myValue;
if (cin.fail()) break;
...
}
I find concise syntax too clever and confusing.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW <allan_w@my-deja.com>
Date: 1999/06/19 Raw View
In article <7k8efs$mim$1@nnrp1.deja.com>,
James.Kanze@dresdner-bank.com wrote:
>
> The "problem" is that too many people like conditions with complicated
> side effects, like:
>
> while ( cin >> myValue ) ...
>
> Written using a (hypothetical) member function, you have:
>
> while ( (cin >> myValue).succeeded() ) ...
>
> Using existing functions, you have to write:
>
> while ( ! (cin >> myValue).fail() ) ...
>
> since `good' doesn't have the desired semantics.
>
> My own preference is for:
>
> for ( cin >> myValue ; ! cin.fail() ; cin >> myValue ) ...
>
> But many people understandably don't like the repetion in the
> initialization and the "incrementation". (I once considered
> requesting an extension to C so that a simple "-" as
> incrementation meant to reuse the initialization. In the
> end, it seemed more trouble that it was worth. The
> duplication is usually only a single function call.)
How about:
while ( (cin>>myValue) , (!cin.fail()) ) ...
> Of course, in many cases, the "duplication" is slightly different:
>
> for (int ch=cin.get(); ch!='\n' && ch!=EOF; ch=cin.get()) ...
This example isn't a case where initialization is better than
assignment. So we can do this:
for (int ch; (ch=cin.get()), (ch!='\n' && ch!=EOF); ) ...
> All of which is an argument for something, but I'm not sure what.
Perhaps some syntax which allows while() to declare a local
variable without the test being dependant on the value of that
variable?
// One possible syntax
while ( (int ch) , (ch=cin.get()), (ch!='\n' && ch!=EOF) ) ...
Note that this is not the same as
while (int ch=cin.get(), (ch!='\n' && ch!=EOF) ) // WRONG
I'm not sure if this is a syntax error. If it isn't, then
it initializes ch with a boolean expression (which is calculated
by comparing the uninitialized value of ch to two constants).
In any case, this is not equivalent to the example above.
--
Allan_W@my-dejanews.com is a "Spam Magnet," never read.
Please reply in newsgroups only, sorry.
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <dtribble@technologist.com>
Date: 1999/06/21 Raw View
AllanW wrote:
> > All of which is an argument for something, but I'm not sure what.
>
> Perhaps some syntax which allows while() to declare a local
> variable without the test being dependant on the value of that
> variable?
>
> // One possible syntax
> while ( (int ch) , (ch=cin.get()), (ch!='\n' && ch!=EOF) ) ...
>
> Note that this is not the same as
> while (int ch=cin.get(), (ch!='\n' && ch!=EOF) ) // WRONG
How about:
while ( { int ch; ch = cin.get(), ch != '\n' and ch != EOF; } )
...
Ack. On second thought, maybe not. Loop-local variables for
anything more complex than a single array index or pointer appear
to be a bad idea. You can always wrap the thing in another set
of braces, after all.
-- David R. Tribble, dtribble@technologist.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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James.Kanze@dresdner-bank.com
Date: 1999/06/16 Raw View
In article <slrn7md02f.31i.sbnaran@localhost.localdomain>,
sbnaran@uiuc.edu wrote:
> On 15 Jun 99 13:01:34 GMT, Gargantua Blargg <blargg@flash.net> wrote:
> >As it currently is, it's meaningless. Plus, it's not such a good idea
> >anyway. I think a named test function would be much clearer, and
without
> >the side-effects we get.
> We already have named test functions -- namely 'fail' and 'good'.
Attention, though. The semantics of fail and good are subtly different,
and you can have situations where both return false.
In this case, what we need is functions like: lastOperationFailed, or
nextOperationMaySucceed, so that the semantics are correct. In
practice, since nextOperationMaySucceed (good) is rather uncertain (it
may not succeed), I can't remember ever having used it.
> This
> suggests that we get rid off operator void *() const, and operator!()
> const. Alas, too many peoople depend on these functions, so we can't
> get rid of them. But in our own classes we write, named test
functions
> like 'ok' are IMO better than cute operator functions.
The "problem" is that too many people like conditions with complicated
side effects, like:
while ( cin >> myValue ) ...
Written using a (hypothetical) member function, you have:
while ( (cin >> myValue).succeeded() ) ...
Using existing functions, you have to write:
while ( ! (cin >> myValue).fail() ) ...
since `good' doesn't have the desired semantics.
My own preference is for:
for ( cin >> myValue ; ! cin.fail() ; cin >> myValue ) ...
But many people understandably don't like the repetion in the
initialization and the "incrementation". (I once considered requesting
an extension to C so that a simple "-" as incrementation meant to reuse
the initialization. In the end, it seemed more trouble that it was
worth. The duplication is usually only a single function call.)
Of course, in many cases, the "duplication" is slightly different:
for ( int ch = cin.get() ; ch != '\n' && ch != EOF ; ch = cin.get()
) ...
All of which is an argument for something, but I'm not sure what.
--
James Kanze mailto:
James.Kanze@dresdner-bank.com
Conseils en informatique orient e objet/
Beratung in objekt orientierter
Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49 (069) 63 19 86
27
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/06/16 Raw View
James.Kanze@dresdner-bank.com writes:
>My own preference is for:
>
> for ( cin >> myValue ; ! cin.fail() ; cin >> myValue ) ...
>
>But many people understandably don't like the repetion in the
>initialization and the "incrementation". (I once considered requesting
>an extension to C so that a simple "-" as incrementation meant to reuse
>the initialization. In the end, it seemed more trouble that it was
>worth. The duplication is usually only a single function call.)
C and C++ already have a concise syntax for that:
while ( cin >> myValue, ! cin.fail() ) ...
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <dtribble@technologist.com>
Date: 1999/06/17 Raw View
James.Kanze@dresdner-bank.com wrote:
> The "problem" is that too many people like conditions with
> complicated side effects, like:
> while ( cin >> myValue ) ...
>
> Written using a (hypothetical) member function, you have:
> while ( (cin >> myValue).succeeded() ) ...
>
> Using existing functions, you have to write:
> while ( ! (cin >> myValue).fail() ) ...
>
> since `good' doesn't have the desired semantics.
>
> My own preference is for:
> for ( cin >> myValue ; ! cin.fail() ; cin >> myValue ) ...
I prefer:
while (cin >> myValue, not cin.fail())
...
> All of which is an argument for something, but I'm not sure what.
Better standard member function names in place of cute member
operators, perhaps?
I don't like '!cin' because it looks too much like checking that
'cin' is not null ('cin' still reminds me of stdin, which is a
pointer). Of course, I've always hated using '!' on anything other
than bool operands anyway.
-- David R. Tribble, dtribble@technologist.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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/06/17 Raw View
Andrei Alexandrescu wrote:
>
> In article <7jot7u$o3k$1@nnrp1.deja.com>,
> James.Kanze@dresdner-bank.com wrote:
> > No. We'd like for cin==cout to be a compile time error. The easiest
> > way of doing this is for cin and cout to convert to distinct pointer
> > types, and return unique values for each pointer. Failing that,
> > however, I agree that the only reasonable solution is for operator
> void*
> > to return this.
>
> Please let me bring again that trick of Don Box: he uses a conversion to
> an unique incomplete type:
>
> class X
> {
> class Undefined;
> operator Undefined* ()
> { return reinterpret_cast<Undefined*>(some-condition); }
> };
>
> This will issue a compile-time error if cin and cout defined conversions
> to different types.
I doubt so:
Conversion from X to X::Undefined* is an user defined conversion.
Conversion from X::Undefined* to void* is a language defined
conversion.
Each user defined conversion may be followed by a language defined
conversion in an implicit cast (this is what causes the problems
with bool).
So cin==cout would resolve to
(void*)(istream::unique*)cin==(void*)(ostream::unique*)cout
which is clearly not a compile error.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: blargg@flash.net (Gargantua Blargg)
Date: 1999/06/13 Raw View
A: Combining ideas, I think a pointer to a const volatile incomplete type
is best:
struct Incomplete; // never defined
operator Incomplete const volatile* () const;
This way even functions like memcpy won't accept it accidentally. It is
rare for a function to take a pointer to a volatile const object, yet
often enough that a function takes a void const*.
B: People in the past mentioned that explicit should have been allowed on
an operator bool () for a class, so that it wouldn't have the unfortunate
effects an operator bool () would normally have:
explicit operator bool () const;
--
"I don't like my edges rounded off" - Ani DiFranco
Gargantua Blargg | blargg@flash.net | http://www.flash.net/~blargg/
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: comeau@panix.com (Greg Comeau)
Date: 1999/06/15 Raw View
In article <199906121433.JAA05389@ares.flash.net> blargg@flash.net (Gargantua Blargg) writes:
>B: People in the past mentioned that explicit should have been allowed on
>an operator bool () for a class, so that it wouldn't have the unfortunate
>effects an operator bool () would normally have:
>
> explicit operator bool () const;
Well, it was suggested for all op conversion functions at one point.
In the case of bool, probably there should be an 'explicit bool' type
too, that wouldn't need to be concerned with backwards compatibility
with "fake bools" that used to exist (still do actually) and their
assumptions about conversions.
- Greg
--
Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418-3214
Producers of Comeau C/C++ 4.2.38 -- New Release! We now do Windows too.
Email: comeau@comeaucomputing.com / Voice:718-945-0009 / Fax:718-441-2310
*** WEB: http://www.comeaucomputing.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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/06/15 Raw View
On 13 Jun 1999 05:02:39 GMT, Gargantua Blargg <blargg@flash.net> wrote:
>B: People in the past mentioned that explicit should have been allowed on
>an operator bool () for a class, so that it wouldn't have the unfortunate
>effects an operator bool () would normally have:
>
> explicit operator bool () const;
How do you call an explicit converion operator? Perhaps like this:
bool b=static_cast<bool>(cout);
Well, if you're going to do this, then you might as well make a member
function basic_ios::asBool() const. Then one writes
bool b=cout.asBool();
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: blargg@flash.net (Gargantua Blargg)
Date: 1999/06/15 Raw View
In article <slrn7m7p4p.in5.sbnaran@localhost.localdomain>,
sbnaran@uiuc.edu wrote:
> On 13 Jun 1999 05:02:39 GMT, Gargantua Blargg <blargg@flash.net> wrote:
>
> >B: People in the past mentioned that explicit should have been allowed on
> >an operator bool () for a class, so that it wouldn't have the unfortunate
> >effects an operator bool () would normally have:
> >
> > explicit operator bool () const;
>
> How do you call an explicit converion operator? Perhaps like this:
> bool b=static_cast<bool>(cout);
> Well, if you're going to do this, then you might as well make a member
> function basic_ios::asBool() const. Then one writes
> bool b=cout.asBool();
Obviously that was not the idea, because that would be stupid and
pointless, as you have shown :-)
The idea was that an explicit operator bool would act like what we are
trying to achieve, that is, ability to test in an if with
if ( obj )
and
if ( !obj )
without having the implicit conversion to int types
int i = obj; // illegal
(I'm sure you can find the threads with Deja News).
As it currently is, it's meaningless. Plus, it's not such a good idea
anyway. I think a named test function would be much clearer, and without
the side-effects we get.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/06/16 Raw View
On 15 Jun 99 13:01:34 GMT, Gargantua Blargg <blargg@flash.net> wrote:
>As it currently is, it's meaningless. Plus, it's not such a good idea
>anyway. I think a named test function would be much clearer, and without
>the side-effects we get.
We already have named test functions -- namely 'fail' and 'good'. This
suggests that we get rid off operator void *() const, and operator!()
const. Alas, too many peoople depend on these functions, so we can't
get rid of them. But in our own classes we write, named test functions
like 'ok' are IMO better than cute operator functions.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Andrei Alexandrescu <andrewalex@hotmail.com>
Date: 1999/06/12 Raw View
In article <7jot7u$o3k$1@nnrp1.deja.com>,
James.Kanze@dresdner-bank.com wrote:
> No. We'd like for cin==cout to be a compile time error. The easiest
> way of doing this is for cin and cout to convert to distinct pointer
> types, and return unique values for each pointer. Failing that,
> however, I agree that the only reasonable solution is for operator
void*
> to return this.
Please let me bring again that trick of Don Box: he uses a conversion to
an unique incomplete type:
class X
{
class Undefined;
operator Undefined* ()
{ return reinterpret_cast<Undefined*>(some-condition); }
};
This will issue a compile-time error if cin and cout defined conversions
to different types.
Andrei
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Dietmar Kuehl <dietmar.kuehl@claas-solutions.de>
Date: 1999/06/09 Raw View
Hi,
In article <slrn7lrias.ajs.sbnaran@localhost.localdomain>,
sbnaran@uiuc.edu wrote:
> Most likely we want (a==b) to be #false. Hence it seems that the
> implementation of the conversion should be my imagined implementation,
> template<class charT, class traits>
> operator void const * () const { return state& (failbit|badbit) ?
> 0:this; }
There are some other options, too. For example, the implementation might
return some other handy pointer like eg. the pointer to the xalloc
array. This is never transferred to another stream and thus unique for
a stream. However, you cannot rely at all on a behavior of '==' for
streams since the implementation is free to choose appropriate pointers
at will. I guess the major reason why the KCC implementation (it is the
one from Modena AFAIK) returns a pointer to the stream buffer rather
than some more or less arbitrary integer value (as is done by the egcs
implementation) is that this is guaranteed to be a valid non-null
pointer (this pointer can be null but in this case badbit is set).
--
<mailto:dietmar.kuehl@claas-solutions.de>
homepage: <http://www.informatik.uni-konstanz.de/~kuehl>
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James.Kanze@dresdner-bank.com
Date: 1999/06/10 Raw View
In article <FD0v6C.C3I@research.att.com>,
ark@research.att.com (Andrew Koenig) wrote:
> In article <375C4693.8D94E903@dnai.com>,
> Eric Montague <ericelm@dnai.com> wrote:
>
> > Why does basic_ios implement conversion operator
> > void*() instead of conversion operator bool()?
> > If the only reason for this conversion operator is
> > to allow
> > while( cin >> word )
> > would not a conversion to bool be more appropriate?
>
> One would think so... but take a look at this:
>
> std::cin << 1;
>
> It would be real nice if this expression would not compile
> (because I wrote << when I meant >>), but if basic_ios were
> to convert to bool, it would compile. Think about it.
You mean, of course, because you wrote cin wehn you meant cout. I
certainly hope that std::cin >> 1 won't compile (except that it probably
will in certain backwards compatibility modes).
--
James Kanze mailto:
James.Kanze@dresdner-bank.com
Conseils en informatique orient e objet/
Beratung in objekt orientierter
Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49 (069) 63 19 86
27
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James.Kanze@dresdner-bank.com
Date: 1999/06/10 Raw View
In article <slrn7lrias.ajs.sbnaran@localhost.localdomain>,
sbnaran@uiuc.edu wrote:
> On 8 Jun 1999 16:41:05 GMT, Eric Montague <ericelm@dnai.com> wrote:
>
> >Why does basic_ios implement conversion operator
> >void*() instead of conversion operator bool()?
> >If the only reason for this conversion operator is
> >to allow
> >while( cin >> word )
> >would not a conversion to bool be more appropriate?
[...]
> II.
>
> My imagined implementation of the operator conversion would return
"this"
> or null. As the operator conversion is a const function, the type of
> "this" is std::basic_ios const *, which the compiler turns into void
> const *.
>
> But the egcs implementation is as follows:
> operator void*() const { return fail() ? (void*)0 : (void*)(-1); }
> This means that the following snippet results in eq equal to #true.
> bool eq=(cin==cout);
>
> However, we'd like (cin==cout) to be #false.
No. We'd like for cin==cout to be a compile time error. The easiest
way of doing this is for cin and cout to convert to distinct pointer
types, and return unique values for each pointer. Failing that,
however, I agree that the only reasonable solution is for operator void*
to return this.
--
James Kanze mailto:
James.Kanze@dresdner-bank.com
Conseils en informatique orientie objet/
Beratung in objekt orientierter
Datenverarbeitung
Ziegelh|ttenweg 17a, 60598 Frankfurt, Germany Tel. +49 (069) 63 19 86
27
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Eric Montague <ericelm@dnai.com>
Date: 1999/06/08 Raw View
Why does basic_ios implement conversion operator
void*() instead of conversion operator bool()?
If the only reason for this conversion operator is
to allow
while( cin >> word )
would not a conversion to bool be more appropriate?
--
Eric
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: comeau@panix.com (Greg Comeau)
Date: 1999/06/09 Raw View
In article <375C4693.8D94E903@dnai.com> Eric Montague <ericelm@dnai.com> writes:
>
>Why does basic_ios implement conversion operator
>void*() instead of conversion operator bool()?
>If the only reason for this conversion operator is
>to allow
>while( cin >> word )
>would not a conversion to bool be more appropriate?
The first reason is historical: once upon a time C++ did not have a
bool data type, so op void *() and op const void *() were used.
Second: An issue which pops up with bool is that since bool is an
integral type, it will as such take place in normal conversion, promotions,
etc. This is significant here, because that also then allows nonsense
such as
int i = cin; // ok if bool, error if [const] void *
i += 90;
- Greg
--
Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418-3214
Producers of Comeau C/C++ 4.2.38 -- New Release! We now do Windows too.
Email: comeau@comeaucomputing.com / Voice:718-945-0009 / Fax:718-441-2310
*** WEB: http://www.comeaucomputing.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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/06/09 Raw View
Eric Montague <ericelm@dnai.com> writes:
>Why does basic_ios implement conversion operator
>void*() instead of conversion operator bool()?
>If the only reason for this conversion operator is
>to allow
>while( cin >> word )
>would not a conversion to bool be more appropriate?
It would, except that bool silently promotes and converts to
every arithmetic type. Simple typographical errors like
cout < 2
would compile and run, but with unintended results.
Type void* does not allow very many accidents to turn into
legal code.
--
Steve Clamage, stephen.clamage@sun.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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kuehl@horn.fmi.uni-konstanz.de (Dietmar Kuehl)
Date: 1999/06/09 Raw View
Hi,
Eric Montague (ericelm@dnai.com) wrote:
: Why does basic_ios implement conversion operator
: void*() instead of conversion operator bool()?
'void*' has the advantage over other built-in type that there is no
implicit type promotion defined for it (except to 'void const*'). This
does not hold for example for 'bool': A 'bool' is promoted to an
arbitrary 'int'. The result could be that the expression 'std::cout <<
x' would be interpreted as a conversion to 'bool' from 'std::cout' and
'x' followed by a shift operation, eg. if there is a conversion
operator defined for 'x' which converts to 'bool'. Thus, although the
program should fail to compile because there is no 'operator<<
(ostream&, T const&)' (where 'T' is the type of 'x') defined, the
program would compile fine but produce strange results.
: If the only reason for this conversion operator is
: to allow
: while( cin >> word )
: would not a conversion to bool be more appropriate?
If appears to be more reasonable but produces some problems, especially
for the stream classes. Similar problems exist for other classes, too.
Since a pointer can be used in a conditional statement as a condition
this is more appropriate.
--
<mailto:dietmar.kuehl@claas-solutions.de>
<http://www.informatik.uni-konstanz.de/~kuehl/>
I am a realistic optimist - that's why I appear to be slightly pessimistic
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/06/09 Raw View
On 8 Jun 1999 16:41:05 GMT, Eric Montague <ericelm@dnai.com> wrote:
>Why does basic_ios implement conversion operator
>void*() instead of conversion operator bool()?
>If the only reason for this conversion operator is
>to allow
>while( cin >> word )
>would not a conversion to bool be more appropriate?
I.
About the only thing you can do with a void * is compare it to null or
compare it to another pointer. But there's more you can do with a
bool -- eg. add a bool to an int*, or an int. If basic_ios::operator
returns a bool, then the following snippet would pass compilation,
cout+3; // convert 'cout' to bool, then bool to int, then add two ints
But we'd like the above snippet to be a syntax error.
Personally, I think that the operator conversion should return a void
const *. There's even less you can do with a pointer to const void!
Actually, perhaps there should not even be an operator conversion at
all. The functions fail() and good() are excellent enough, and make
the intent of the code really clear.
Now ((cin>>t).good()) is cumbersome to write. But generally I write
code like this,
while (true) {
T t;
cin >> t;
if (cin.fail()) break;
// do stuff with 't'
}
And to me, this looks just fine. There's no need for fancy operator
conversions.
II.
My imagined implementation of the operator conversion would return "this"
or null. As the operator conversion is a const function, the type of
"this" is std::basic_ios const *, which the compiler turns into void
const *.
But the egcs implementation is as follows:
operator void*() const { return fail() ? (void*)0 : (void*)(-1); }
This means that the following snippet results in eq equal to #true.
bool eq=(cin==cout);
However, we'd like (cin==cout) to be #false. For this to be so, the
operator conversion must be
operator void*() const { return fail() ? 0 : this; }
But as remarked above, the type of "this" is ::ios const *. Hence the
operator conversion is not const correct. It should be
operator void const *() const { return fail() ? 0 : this; }
The KCC implementation, ignoring mutexes, is
template<class charT, class traits>
operator void* () const { return state& (failbit|badbit) ? 0:sb; }
The variable 'sb' is the pointer to the internal streambuf, and it has
type std::basic_streambuf<CharT,traits> *. This means that the
following snippet results in eq equal to #true
std::ostream a(cout.rdbuf());
std::ostream b(cout.rdbuf());
bool eq=(a==b);
Most likely we want (a==b) to be #false. Hence it seems that the
implementation of the conversion should be my imagined implementation,
template<class charT, class traits>
operator void const * () const { return state& (failbit|badbit) ? 0:this; }
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]