Topic: draft section 12.3.2, why?


Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/06/21
Raw View
clamage@Eng.Sun.COM (Steve Clamage) writes:
>haydens@wayback.atc.ll.mit.edu (Hayden Schultz x3685) writes:
>>Below is a quote from the ansi draft section 12.3.2. Since many older
>>compilers (like cfront) allowed conversion operators to base classes
>>this breaks code. Therefore, I'm guessing that there must be a reason
>>why it's worth making this rule. Anyone know what that reason is?
>
>"is never used" doesn't mean you can't write the operator. It means that
>even if it exists, it won't ordinarily be used for type conversion.

Yes.  It may still break some old cfront code of course.  But if the
committee had decided the other way, then I suspect that code written
for other compilers would break.  That's what happens when different
implementations do different things: when it comes time to standardize,
someone's code is gonna break.

--
Fergus Henderson
fjh@cs.mu.oz.au
http://www.cs.mu.oz.au/~fjh





Author: haydens@wayback.atc.ll.mit.edu (Hayden Schultz x3685 )
Date: 1995/06/21
Raw View
>>>>> "Fergus" == Fergus Henderson <fjh@munta.cs.mu.OZ.AU> writes:

Fergus> clamage@Eng.Sun.COM (Steve Clamage) writes:
>> haydens@wayback.atc.ll.mit.edu (Hayden Schultz x3685) writes:
>>> Below is a quote from the ansi draft section 12.3.2. Since many
>>> older compilers (like cfront) allowed conversion operators to base
>>> classes this breaks code. Therefore, I'm guessing that there must
>>> be a reason why it's worth making this rule. Anyone know what that
>>> reason is?
>>  "is never used" doesn't mean you can't write the operator. It
>> means that even if it exists, it won't ordinarily be used for type
>> conversion.

Fergus> Yes.  It may still break some old cfront code of course.  But
Fergus> if the committee had decided the other way, then I suspect
Fergus> that code written for other compilers would break.  That's
Fergus> what happens when different implementations do different
Fergus> things: when it comes time to standardize, someone's code is
Fergus> gonna break.

I don't think that this is really true in this case. Aside from it
being very unlikely that code would depend upon a user defined
conversion operators not being called for base classes, old pre-WP
compilers which correctly implement the ARM do allow allow this
because it was ok. This is not a case where a popular cfront bug is
now disallowed, the rules changed so that what was legal, is no longer
legal.

There's probably a good reason why this change was made-- not that I
know what that reason is...

 Hayden

--
Hayden Schultz
haydens@ll.mit.edu
MIT Lincoln Lab
Air Traffic Automation
244 Wood St.
Lexington, MA, 02173
(617) 981-3685






Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/06/05
Raw View
In article 95Jun4232533@wayback.atc.ll.mit.edu, haydens@wayback.atc.ll.mit.edu (Hayden Schultz x3685 ) writes:
>
>Below is a quote from the ansi draft section 12.3.2. Since many older
>compilers (like cfront) allowed conversion operators to base classes
>this breaks code. Therefore, I'm guessing that there must be a reason
>why it's worth making this rule. Anyone know what that reason is?
>
>
>
>  12.3.2  Conversion functions                          [class.conv.fct]
>
>1 A member function of a class X with a name of the form
>          conversion-function-id:
>                  operator conversion-type-id
>          conversion-type-id:
>                  type-specifier-seq conversion-declaratoropt
>          conversion-declarator:
>                  ptr-operator conversion-declaratoropt
>  specifies a conversion from X to the type specified by the conversion-
>  type-id.  Such  member  functions  are  called  conversion  functions.
>  Classes,  enumerations, and typedef-names shall not be declared in the
>  type-specifier-seq.  Neither parameter types nor return  type  can  be
>  specified.  A conversion operator is never used to convert a (possibly
>  qualified) object (or reference to an object) to the (possibly  quali
>  fied) same object type (or a reference to it), or to a (possibly qual
>  ified) base class of that type (or a reference to  it).72)  If  conver
>  sion-type-id  is void or cv-qualified void, the program is ill-formed.

"is never used" doesn't mean you can't write the operator. It means that
even if it exists, it won't ordinarily be used for type conversion. See
the footnote for that paragraph:

"72. Even though never directly called to perform a conversion, such
conversion operators can be declared and can potentially be reached
through a call to a virtual conversion operator in a base class."

The point here is that if you write
 class derived : public base { ... operator base(); ... };
and then
 derived d;
 ... (base)d ...
you will not get the conversion operator, but the default "slicing"
to a base object.
---
Steve Clamage, stephen.clamage@eng.sun.com







Author: haydens@wayback.atc.ll.mit.edu (Hayden Schultz x3685 )
Date: 1995/06/06
Raw View
>>>>> "Steve" == Steve Clamage <clamage@Eng.Sun.COM> writes:

Steve> In article 95Jun4232533@wayback.atc.ll.mit.edu, haydens@wayback.atc.ll.mit.edu (Hayden Schultz x3685 ) writes:

Hayden> Below is a quote from the ansi draft section 12.3.2. Since many older
Hayden> compilers (like cfront) allowed conversion operators to base classes
Hayden> this breaks code. Therefore, I'm guessing that there must be a reason
Hayden> why it's worth making this rule. Anyone know what that reason is?
Steve> "is never used" doesn't mean you can't write the operator. It means that
Steve> even if it exists, it won't ordinarily be used for type conversion. See
Steve> the footnote for that paragraph:

Steve> "72. Even though never directly called to perform a conversion, such
Steve> conversion operators can be declared and can potentially be reached
Steve> through a call to a virtual conversion operator in a base class."

Steve> The point here is that if you write
Steve> class derived : public base { ... operator base(); ... };
Steve> and then
Steve> derived d;
Steve> ... (base)d ...
Steve> you will not get the conversion operator, but the default "slicing"
Steve> to a base object.

Yes, I think I understand what it says. I had to read it 5 or 6 times
before I understood it because it reads like something written by an
IRS employee, but I think I understand it. What I don't understand is
why?

It may not have been particularly good programming practice to have a
conversion operator to a base class, but many c++ compilers (like
cfront) supported it. So this particular clause breaks existing code.

I suspect that the ansi committee had some good reason in mind when it
was decided that this rule was more important than compatability with
existing code. My question is what is the reasoning in this case?

 Thanks,

 Hayden

--
Hayden Schultz
haydens@ll.mit.edu
MIT Lincoln Lab
Air Traffic Automation
244 Wood St.
Lexington, MA, 02173
(617) 981-3685






Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/06/06
Raw View
In article 95Jun6111117@wayback.atc.ll.mit.edu, haydens@wayback.atc.ll.mit.edu (Hayden Schultz x3685 ) writes:
>
>>>>>> "Steve" == Steve Clamage <clamage@Eng.Sun.COM> writes:
>
>Steve> In article 95Jun4232533@wayback.atc.ll.mit.edu, haydens@wayback.atc.ll.mit.edu (Hayden Schultz x3685 ) writes:
>
>Hayden> Below is a quote from the ansi draft section 12.3.2. Since many older
>Hayden> compilers (like cfront) allowed conversion operators to base classes
>Hayden> this breaks code. Therefore, I'm guessing that there must be a reason
>Hayden> why it's worth making this rule. Anyone know what that reason is?
>Steve> "is never used" doesn't mean you can't write the operator. It means that
>Steve> even if it exists, it won't ordinarily be used for type conversion. See
>Steve> the footnote for that paragraph:
>
>Steve> "72. Even though never directly called to perform a conversion, such
>Steve> conversion operators can be declared and can potentially be reached
>Steve> through a call to a virtual conversion operator in a base class."
>
>Steve> The point here is that if you write
>Steve> class derived : public base { ... operator base(); ... };
>Steve> and then
>Steve> derived d;
>Steve> ... (base)d ...
>Steve> you will not get the conversion operator, but the default "slicing"
>Steve> to a base object.
>
>Yes, I think I understand what it says. I had to read it 5 or 6 times
>before I understood it because it reads like something written by an
>IRS employee, but I think I understand it. What I don't understand is
>why?
>
>It may not have been particularly good programming practice to have a
>conversion operator to a base class, but many c++ compilers (like
>cfront) supported it. So this particular clause breaks existing code.

I don't think it breaks existing code, and if it does, the code wasn't
portable anyway. Cfront historically allowed things which were always
expressly prohibited by written language specifications. These have to
be considered Cfront bugs. (I'm not necessarily throwing rocks at
Cfront -- all compilers have bugs. The problem is that some programmers
tended to view the definition of C++ as "whatever Cfront does", bugs
and all.)

Consider: the built-in conversion from derived to base is a
standard conversion. If you write a conversion function "operator
base()" it is a user-defined conversion. A standard conversion is
always selected before even checking for a user-defined conversion,
so you should not expect the operator function to be called unless
you call it explicitly.

You might make the argument that "operator base()" doesn't have to be
a user-defined conversion, but would simply replace the standard
conversion. That approach opens up a whole new can of worms.
- What about const and volatile? Do you sometimes get the built-in
  conversion and sometimes the user-defined conversion if the user
  didn't supply all four combinations of const and volatile?
- What about conversion of derived to base& -- do you take a
  reference to the result of "operator base()"? If so, then derived
  to base& has completely different semantics from &derived to base*.
  If not, then you have to decide when an lvalue is an object and
  when it is a reference -- this is not well-defined in the language.
  (You can't write a function to convert to reference-to-own-type for
  that reason.)

Finally, suppose you really need different semantics when converting
from derived to base than the standard conversion. I claim this
breaks the IS-A relationship. (That is, you can't use a derived object
any place a base is expected.) So in that case you can use private or
protected inheritance and provide a named conversion function. You then
get no automatic conversions from derived to base, but can get the
conversion by asking for it. (Golly! Maybe I've found a use for
protected inheritance. I always said it was a solution in search of
a problem.)
---
Steve Clamage, stephen.clamage@eng.sun.com







Author: haydens@wayback.atc.ll.mit.edu (Hayden Schultz x3685 )
Date: 1995/06/05
Raw View
Below is a quote from the ansi draft section 12.3.2. Since many older
compilers (like cfront) allowed conversion operators to base classes
this breaks code. Therefore, I'm guessing that there must be a reason
why it's worth making this rule. Anyone know what that reason is?

If I understand it properly, the using keyword can blast through
protection. So why get finicky about conversion operators?

 Thanks,

 Hayden


  12.3.2  Conversion functions                          [class.conv.fct]

1 A member function of a class X with a name of the form
          conversion-function-id:
                  operator conversion-type-id
          conversion-type-id:
                  type-specifier-seq conversion-declaratoropt
          conversion-declarator:
                  ptr-operator conversion-declaratoropt
  specifies a conversion from X to the type specified by the conversion-
  type-id.  Such  member  functions  are  called  conversion  functions.
  Classes,  enumerations, and typedef-names shall not be declared in the
  type-specifier-seq.  Neither parameter types nor return  type  can  be
  specified.  A conversion operator is never used to convert a (possibly
  qualified) object (or reference to an object) to the (possibly  quali
  fied) same object type (or a reference to it), or to a (possibly qual
  ified) base class of that type (or a reference to  it).2)  If  conver
  sion-type-id  is void or cv-qualified void, the program is ill-formed.

--
Hayden Schultz
haydens@ll.mit.edu
MIT Lincoln Lab
Air Traffic Automation
244 Wood St.
Lexington, MA, 02173
(617) 981-3685