Topic: Too many conversions?


Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1996/09/03
Raw View
Tim Ottinger <tottinge@csci.csc.com> writes:

> > |> The part which bothered me even more than the two user-supplied conv.
> > |> was the fact that it used a downward cast int to char. It seems that
> > |> they used to be forbidden.  Aren't they still?
> >
> > Where did you get the idea that a downcast was forbidden?  It has never
> > been illegal to assign a char to an int.  It is, in fact, a very
> > frequent idiom in C.
>
> I thought that, in the ARM, it was clearly excluded for issues of
> disambiguation.
> I know it's okay on anything explicitely written, and usually generates
> the
> appropriate warning about slicing.  Which I didn't get on my example, by
> the way ;-)

In the ARM, all implicit type conversions are forbidden when it comes to
matching a template parameter.  Otherwise, everything involving built-in
types is straight from C.

With regards to the warning, this is a delicate issue.  Several standard
and very much approved C idioms involved assigning an int to a char,
particularly when the int was a return value from getc.  I think that at
various times in the past, certain compilers (Microsoft?) did generate
warnings in this case, and there was a big screem about it.

IMHO, they were doing the right thing.  I know that it meant adding a
cast in the specific case involving getc to inhibit the warnings, but:

1.  In general, the assignment is unsafe.  Adding the cast is a signal
to the code reviewers to pay particular attention here.

2.  Even in the particular case of a return value from getc, the
assignment was only safe *after* the code had checked for EOF.  So even
in this case, hinting to the code reviewers to pay a bit closer
attention is worthwhile.


With regards to my comments on the foolishness of using a class from the
draft standard without concerns over its stability: it is, of course,
much easier to see foolishness after the damage has been done.  Also, if
the implementation documentation simply described the classes, without
mentioning that they were based on the draft standard, and thus highly
susceptible to change, then the implementation is at least partially to
blame.

--
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle --
                            -- Beratung in industrieller Datenverarbeitung
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Tim Ottinger <tottinge@csci.csc.com>
Date: 1996/08/30
Raw View
> I'm not sure what the position was in earlier drafts of the standard.  I
> think that the string class has undergone some significant changes.  It
> is likely that any code written according to the earlier drafts may be
> broken.  On the other hand, you'ld have to be very foolish to use
> classes out of a *draft* standard in production code, unless the draft
> was based on extensive existing practice (not the case for the C++
> string class).  Even then, I would generally stick with the "existing
> practice" until the draft became moderately stable.

I'm a fool in the company of a great many fools.  Sigh.


> |> The part which bothered me even more than the two user-supplied conv.
> |> was the fact that it used a downward cast int to char. It seems that
> |> they used to be forbidden.  Aren't they still?
>
> Where did you get the idea that a downcast was forbidden?  It has never
> been illegal to assign a char to an int.  It is, in fact, a very
> frequent idiom in C.

I thought that, in the ARM, it was clearly excluded for issues of
disambiguation.
I know it's okay on anything explicitely written, and usually generates
the
appropriate warning about slicing.  Which I didn't get on my example, by
the way ;-)

Templates confuse my thinking on disambiguation. I've got to return to
the draft
and start seeking out all of the disambiguation rules again, and they
don't seem
to be entirely grouped together. Maybe I need a finer-toothed comb or an
eyeball
scan rather than a web search.

Thanks for all the help on this.
--
Tim
+----------------------------------------------------------------------------+
| Tim Ottinger, Sr Tech           tottinge@csci.csc.com |
| CSC Communications Industry Services             217-351-8508x2420 |
| TRIS Division -- Cellular Billing and Support             Fax
217-351-2640 |
+----------------------------------------------------------------------------+
| It is hard for a detective to predict accurately how long it will
take     |
| to  find out who committed a crime.  It is harder still to prevent
future  |
| crimes. And we've been trying to solve those problems for much
longer...   |
|                                  Bill Ehrich, via electronic
transmission  |
+----------------------------------------------------------------------------+
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: jpotter@falcon.lhup.edu (John E. Potter)
Date: 1996/08/24
Raw View
James Kanze US/ESC 60/3/141 #40763 (kanze@lts.sel.alcatel.de) wrote:
: In article <321B2028.1F2@csci.csc.com> Tim Ottinger
: <tottinge@csci.csc.com> writes:

: |> I've a class 'Result', which has a bool cast.  Now I know that it's
: |> dangerous
: |> when you allow explicit conversions, but I didn't think it was legal to
: |> take
: |> it this far:

: |>      string Function()
: |>      {
: |>          Result x;
: |>          return x;
: |>      }

: |> This compiles and runs without any warnings or compile/link errors.
: |> When I
: |> traced it down, this is what I found (this is duplicated in MS VC++,
: |> Borland,
: |> GNU and HP C++):

: |>     The operator bool() is called on x.
: |>     The bool() is cast (downcast where bool is an int typedef) to a
: |> char.
: |>     The string constructor is called: string::string(char c, int count =
: |> 1)

Note that the public(Apr95) DWP constructor is string(int, char) so that this
conversion could not happen.  g++2.7.2 agrees.

: |> This seems like two user-defined conversions and a downcast to satisfy a
: |> type conversion.  Is this going 'way to far?

: Yes.  The ARM definitely (and explicitly) said that at most one user
: conversion would be used.  Although the text concerning implicit
: conversions has changed a lot in the current (Jan. 96) draft, even a
: superficial reading of 13.3.3.1.2 makes it clear that this is still the
: case.

: Given the number of compilers which apparently do allow it, I thought
: I'd try those available to me.  Interestingly, g++ (version 2.7.2) does
: not allow it, although earlier versions did.  On the other hand, Sun CC
: 4.0.1 doesn't complain, although earlier versions (3.0.1) did.  (Given
: this, I'm rather surprised about the HP C++.  I have heard that it is
: Cfront based, as is Sun 3.0.1, so I would expect the behavior to be the
: same.)

Now assuming that String(char) exists, 8.5 states that the return value
initialization is copy initialization equivalent to
 String rv = x
and following on we get direct initialization via
 String rv(String(x))
 String rv(String(char(bool(x))))
There seems to be no question that
 string rv;
 rv = x;
is ill-formed; however, the same does not seem to be true above.  Could am
implementer conclude that the first conversion was explicitely required by
the DWP?  ie. String rv = x means String rv(String(x)) explicitely?  If we
return String(x), there is no complaint from g++2.7.2.  To continue, now
let's make the copy constructor for String private.  Still no complaint.
Fergus Henderson has explained that the rules for temporaries and what is
actually initialized could explain this.  Could some of these same rules
be used to remove the possibly implicit conversion above?  Is it the intent
to make the initialization via = and () different and does the DWP clearly
state the intent?

John
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Tim Ottinger <tottinge@csci.csc.com>
Date: 1996/08/26
Raw View
John E. Potter wrote:
> James Kanze US/ESC 60/3/141 #40763 (kanze@lts.sel.alcatel.de) wrote:
[I started the whole thing here - tim]

> : |>     The operator bool() is called on x.
> : |>     The bool() is cast (downcast where bool is an int typedef) to a
> : |> char.
> : |>     The string constructor is called: string::string(char c, int count =
> : |> 1)
>
> Note that the public(Apr95) DWP constructor is string(int, char) so that this
> conversion could not happen.  g++2.7.2 agrees.

So you don't have the default anymore?  That's probably a good thing
because of
the implicit conversion, but didn't that used to also support:
   string s = 'X';
Will this break code?  Much?


> : Yes.  The ARM definitely (and explicitly) said that at most one user
> : conversion would be used.  Although the text concerning implicit
> : conversions has changed a lot in the current (Jan. 96) draft, even a
> : superficial reading of 13.3.3.1.2 makes it clear that this is still the
> : case.

The part which bothered me even more than the two user-supplied conv.
was the fact that it used a downward cast int to char. It seems that
they used to be forbidden.  Aren't they still?

[much reasonable and stuff deleted]

> Fergus Henderson has explained that the rules for temporaries and what is
> actually initialized could explain this.  Could some of these same rules
> be used to remove the possibly implicit conversion above?  Is it the intent
> to make the initialization via = and () different and does the DWP clearly
> state the intent?

Ooohhh.. I'd not considered any special temporary rules on this, but it
certainly seems that all of my compilers were a bit temp-happy here at
best.  Are there rules for instantiating temporary which allow two,
three,
or more levels of instantiation?  I doubt it, considering the degree
of insight and foresight given by the committee on issues of implicit
and explicit conversions so far.

Is this thread by Fergus available anywhere?  Should I go back to the
DWP on this one?  It seems to be serious enough to warrant a few
columns in national C++ trades.

--
Tim
+----------------------------------------------------------------------------+
| Tim Ottinger, Sr Tech           tottinge@csci.csc.com |
| CSC Communications Industry Services             217-351-8508x2420 |
| TRIS Division -- Cellular Billing and Support             Fax 217-351-2640 |
+----------------------------------------------------------------------------+
|   A better metaphor [for debugging] might be crime.  It is hard for a      |
|   detective to predict accurately how long it will take to find out who    |
|   committed a crime.  It is harder still to prevent future crimes. And     |
|   we've been trying to solve those problems for much longer...             |
|                                  Bill Ehrich, via electronic transmission  |
+----------------------------------------------------------------------------+


[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1996/08/26
Raw View
jpotter@falcon.lhup.edu (John E. Potter) writes:

> Now assuming that String(char) exists, 8.5 states that the return value
> initialization is copy initialization equivalent to
>  String rv = x
> and following on we get direct initialization via
>  String rv(String(x))
>  String rv(String(char(bool(x))))
> There seems to be no question that
>  string rv;
>  rv = x;
> is ill-formed; however, the same does not seem to be true above.

In the above context,

  String rv( x ) ;

is legal, but

  String rv = x ;

is not.

> Could am
> implementer conclude that the first conversion was explicitely required by
> the DWP?  ie. String rv = x means String rv(String(x)) explicitely?  If we
> return String(x), there is no complaint from g++2.7.2.  To continue, now
> let's make the copy constructor for String private.  Still no complaint.
> Fergus Henderson has explained that the rules for temporaries and what is
> actually initialized could explain this.  Could some of these same rules
> be used to remove the possibly implicit conversion above?  Is it the intent
> to make the initialization via = and () different and does the DWP clearly
> state the intent?

I'm not sure how clear the *intent* (or the rationale) is stated, but
this is definitly what is stated with regards to the actual behavior,
both in the ARM and the DWP.  The two forms of initialziation are *NOT*
equivalent.  As far as I can tell, the distinction is intentional, and
not a side effect of some other desicion.

--
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle --
                            -- Beratung in industrieller Datenverarbeitung
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1996/08/27
Raw View
In article <3221BDB2.6B1A@csci.csc.com> Tim Ottinger
<tottinge@csci.csc.com> writes:

|> John E. Potter wrote:
|> > James Kanze US/ESC 60/3/141 #40763 (kanze@lts.sel.alcatel.de) wrote:
|> [I started the whole thing here - tim]

|> > Note that the public(Apr95) DWP constructor is string(int, char) so that this
|> > conversion could not happen.  g++2.7.2 agrees.

|> So you don't have the default anymore?  That's probably a good thing
|> because of
|> the implicit conversion, but didn't that used to also support:
|>    string s = 'X';
|> Will this break code?  Much?

In theory, the only code it could break is that which uses string as a
user variable:-).  There was no standard string class before.  Of
course, if the user symbol defined a class which is in some way similar
to the standard string class, there is a very good chance that it will
be seriously broken.  (I'm lucky here.  My own string class is called
GB_String, so I don't have to worry about naming conflicts.)

I'm not sure what the position was in earlier drafts of the standard.  I
think that the string class has undergone some significant changes.  It
is likely that any code written according to the earlier drafts may be
broken.  On the other hand, you'ld have to be very foolish to use
classes out of a *draft* standard in production code, unless the draft
was based on extensive existing practice (not the case for the C++
string class).  Even then, I would generally stick with the "existing
practice" until the draft became moderately stable.

|> > : Yes.  The ARM definitely (and explicitly) said that at most one user
|> > : conversion would be used.  Although the text concerning implicit
|> > : conversions has changed a lot in the current (Jan. 96) draft, even a
|> > : superficial reading of 13.3.3.1.2 makes it clear that this is still the
|> > : case.

|> The part which bothered me even more than the two user-supplied conv.
|> was the fact that it used a downward cast int to char. It seems that
|> they used to be forbidden.  Aren't they still?

Where did you get the idea that a downcast was forbidden?  It has never
been illegal to assign a char to an int.  It is, in fact, a very
frequent idiom in C.
--
James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils,    tudes et r   alisations en logiciel orient    objet --
                -- A la recherche d'une activit    dans une region francophone
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1996/08/21
Raw View
In article <321B2028.1F2@csci.csc.com> Tim Ottinger
<tottinge@csci.csc.com> writes:

|> I've got a problem with many compilers, and I'm not sure if it's me or
|> them
|> who's to blame.

|> I've a class 'Result', which has a bool cast.  Now I know that it's
|> dangerous
|> when you allow explicit conversions, but I didn't think it was legal to
|> take
|> it this far:

|>      string Function()
|>      {
|>          Result x;
|>          return x;
|>      }

|> Admittedly, this is wrong.  The programmer who wrote the original had a
|> normal
|> path which returned a string and an exceptional path where a result was
|> returned
|> instead (by accident).  But here's the problem:

|> This compiles and runs without any warnings or compile/link errors.
|> When I
|> traced it down, this is what I found (this is duplicated in MS VC++,
|> Borland,
|> GNU and HP C++):

|>     The operator bool() is called on x.
|>     The bool() is cast (downcast where bool is an int typedef) to a
|> char.
|>     The string constructor is called: string::string(char c, int count =
|> 1)

|> This seems like two user-defined conversions and a downcast to satisfy a
|> type conversion.  Is this going 'way to far?

Yes.  The ARM definitely (and explicitly) said that at most one user
conversion would be used.  Although the text concerning implicit
conversions has changed a lot in the current (Jan. 96) draft, even a
superficial reading of 13.3.3.1.2 makes it clear that this is still the
case.

Given the number of compilers which apparently do allow it, I thought
I'd try those available to me.  Interestingly, g++ (version 2.7.2) does
not allow it, although earlier versions did.  On the other hand, Sun CC
4.0.1 doesn't complain, although earlier versions (3.0.1) did.  (Given
this, I'm rather surprised about the HP C++.  I have heard that it is
Cfront based, as is Sun 3.0.1, so I would expect the behavior to be the
same.)
--
James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils,    tudes et r   alisations en logiciel orient    objet --
                -- A la recherche d'une activit    dans une region francophone



[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Tim Ottinger <tottinge@csci.csc.com>
Date: 1996/08/21
Raw View
I've got a problem with many compilers, and I'm not sure if it's me or
them
who's to blame.

I've a class 'Result', which has a bool cast.  Now I know that it's
dangerous
when you allow explicit conversions, but I didn't think it was legal to
take
it this far:

     string Function()
     {
         Result x;
         return x;
     }

Admittedly, this is wrong.  The programmer who wrote the original had a
normal
path which returned a string and an exceptional path where a result was
returned
instead (by accident).  But here's the problem:

This compiles and runs without any warnings or compile/link errors.
When I
traced it down, this is what I found (this is duplicated in MS VC++,
Borland,
GNU and HP C++):

    The operator bool() is called on x.
    The bool() is cast (downcast where bool is an int typedef) to a
char.
    The string constructor is called: string::string(char c, int count =
1)

This seems like two user-defined conversions and a downcast to satisfy a
type conversion.  Is this going 'way to far?

I am removing the 'bool' cast from Result anyway, but would like a
ruling.
--
+----------------------------------------------------------------------------+
| Tim Ottinger, Sr Tech           tottinge@csci.csc.com |
| CSC Communications Industry Services             217-351-8508x2420 |
| TRIS Division -- Cellular Billing and Support             Fax
217-351-2640 |
+----------------------------------------------------------------------------+
| Requirements have always been the least stable part of any project I
have  |
| worked on.                         -- Robert Martin via Usenet
12/02/95 |
+----------------------------------------------------------------------------+


[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]