Topic: Help on Interpreting standard with regards to Explicit User-Defined conversions


Author: "Darrin Weber" <weberdl@apci.com>
Date: 1997/03/21
Raw View
I am currently in disagreement with a (well-known) compiler vendor
regarding their stricter conformance to ANSI standards regarding explicit
type casts and constructors.  Consider the following class declarations:

 class A {
 public:
  A();
  operator B();
 }

 class B {
 public:
  B();
  const B& operator=(const B& source);
 }

Where A::operator B() is implemented as:

 A::operator B()
 {
  B bTmp;
  return(bTmp);
 }

The statement generating a compiler error message:

 B= (B) A;

My assertion is that the operator B() for class A should be called which
creates a temporary object of type B, followed by the assignment operator
within class B.

The (well-known) compiler vendor states that the statement B= (B) A is
equivalent to B= B(A) as defined by the ANSI C++ standards. Therefore, the
statement is in error because no constructor in class B accepts a class A
object.

Please help me to either understand where my reasoning is incorrect(it has
always compiled and executed correctly in the past) or help me demonstrate
its validity.

Darrin Weber
weberdl@apci.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         ]
[ 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: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/03/21
Raw View
"Darrin Weber" <weberdl@apci.com> writes:

 >I am currently in disagreement with a (well-known) compiler vendor
 >regarding their stricter conformance to ANSI standards regarding explicit
 >type casts and constructors.  Consider the following class declarations:
 >
 > class A {
 > public:
 >  A();
 >  operator B();
 > }
 >
 > class B {
 > public:
 >  B();
 >  const B& operator=(const B& source);
 > }
 >
 >Where A::operator B() is implemented as:
 >
 > A::operator B()
 > {
 >  B bTmp;
 >  return(bTmp);
 > }
 >
 >The statement generating a compiler error message:
 >
 > B= (B) A;

Well, that _should_ generate a compiler error message -- it is
a syntax error.  Perhaps you meant `B b; A a; b = (B) a;'?

--
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         ]
[ 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: "Darrin Weber" <weberdl@apci.com>
Date: 1997/03/22
Raw View
I'm sorry...I did mean:
A a;
B b;

b= (B) a;
---
[ 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: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/03/23
Raw View
"Darrin Weber" <weberdl@apci.com> writes:

>I am currently in disagreement with a (well-known) compiler vendor
>regarding their stricter conformance to ANSI standards regarding explicit
>type casts and constructors.  Consider the following class declarations:
>
> class A {
> public:
>  A();
>  operator B();
> }
>
> class B {
> public:
>  B();
>  const B& operator=(const B& source);
> }
>
>Where A::operator B() is implemented as:
>
> A::operator B()
> {
>  B bTmp;
>  return(bTmp);
> }
>
>The statement generating a compiler error message:

 A a;
 B a;
 b = (B) a;

According to 5.4[expr.cast]/5 in the current draft, the old-style cast
notation can perform static casts (as well as some other possibilities
that don't apply in this example).  According to 5.2.9[expr.static.cast],
the static cast static_cast<B>(a) is well-formed if `B t(a)' is well-formed
for some fresh variable `t' (as well as in some other cases that don't
apply in this example).  According to 8.5[dcl.init]/14, this performs
overload resolution on the constructors for `B'.

The only constructor with the right number of arguments for this case (one)
is the implicitly declared copy constructor.  Since the parameter of
the copy constructor is a (const) reference, we need to consult
13.3.3.1.4[over.ics.ref].

The only viable constructor in this case is the implicitly declared
copy constructor.  There is an implicit conversion sequence from `a',
which is an lvalue of type `A', to the argument type of the
copy-constructor, `const B &', namely the sequence

  A::operator B()
 A      ->   B -> const B &
 (a)    (t2)

So, what should happen is basically the following:  first a temporary
`t2' is created by calling `a.operator B()', then this temporary is
copy-constructed to create a temporary `t', which is the result of the
cast expression; finally this temporary `t' is assigned to the result,
`b'.

A compiler is however allowed to optimize away one of the temporaries.

>My assertion is that the operator B() for class A should be called which
>creates a temporary object of type B, followed by the assignment operator
>within class B.

Apart from underestimating the number of temporaries potentially
involved, this is correct.

>The (well-known) compiler vendor states that the statement B= (B) A is
>equivalent to B= B(A) as defined by the ANSI C++ standards. Therefore, the
>statement is in error because no constructor in class B accepts a class A
>object.

I don't think that conclusion is correct, because there is a constructor
in class B that accepts a class A object, once you take implicit conversions
into account: the copy constructor.

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