Topic: Q: cast operator


Author: clerc@gla.ecoledoc.ibp.fr
Date: 25 Feb 1995 15:44:11 GMT
Raw View
what does the ARM/WP say about the way the
program below is supposed to behave ?

IBM says that xlC is the only one to get it 'right'.

thanks to all


#include <iostream.h>

class A {};

class B {

  public:

    operator A const&() const { cout<<"ok"; return a_; }

  private:

    A a_;
};

int main() {

  B b;
  A a;

  cout<<"1: "; a=(A&)b;        cout<<endl;
  cout<<"2: "; a=(A const&)b;  cout<<endl;
  cout<<"3: "; a=b;            cout<<endl;

  return 1;
}

#if 0


IBM xlC 2.1(.2?)
----------------

% xlC t.C
% a.out
1:
2:
3: ok


Sun CC 4.0.1
------------

% CC t.C
"t.C", line 24: Warning (Anachronism): Cannot cast from B to A.
"t.C", line 24: Note: Type "CC -migration" for more on anachronisms.
"t.C", line 24: Warning (Anachronism): Cannot cast from B to A.
2 Warning(s) detected.

% a.out
1:
2: ok
Bus error (core dumped)


HP C++3.5
---------

% CC t.C
% a.out
1:
2: ok
3: ok


Watcom C++ v10.0
----------------

C:\tmp>wcl386 /zq t.cpp

C:\tmp>t.exe
1:
2: ok
3: ok

#endif



Keywords:





Author: jason@cygnus.com (Jason Merrill)
Date: 28 Feb 1995 00:28:45 GMT
Raw View
>>>>> clerc  <clerc@gla.ecoledoc.ibp.fr> writes:

> what does the ARM/WP say about the way the
> program below is supposed to behave ?

> IBM says that xlC is the only one to get it 'right'.

...
>     operator A const&() const { cout<<"ok"; return a_; }
...
>   cout<<"1: "; a=(A&)b;        cout<<endl;
>   cout<<"2: "; a=(A const&)b;  cout<<endl;
>   cout<<"3: "; a=b;            cout<<endl;
...

The pertinent text in the WP is:

  5.2.8  Static cast                                  [expr.static.cast]

2 Any  implicit  conversion (including standard conversions and/or user-
  defined conversions; see _conv_ and _over.best.ics_) can be  performed
  explicitly  using  static_cast.  More precisely, if T t(v); is a well-
  formed declaration, for some invented temporary variable t,  then  the
  result  of  static_cast<T>(v) is defined to be the temporary t, and is
  an lvalue if T is a reference type,  and  an  rvalue  otherwise.   The
  expression v shall be an lvalue if the equivalent declaration requires
  an lvalue for v.

  5.2.9  Reinterpret cast                        [expr.reinterpret.cast]

12An lvalue expression of type T1 can be cast to the type  reference  to
  T2  if an expression of type pointer to T1 can be explicitly converted
  to the type pointer to T2 using a reinterpret_cast.  That is, a refer-
  ence  cast reinterpret_cast<T&>x has the same effect as the conversion
  *reinterpret_cast<T*>&x with the built-in  &  and  *  operators.   The
  result  is  an  lvalue  that  refers  to the same object as the source
  lvalue, but with a different type.  No temporary is created,  no  copy
  is  made,  and  constructors  (_class.ctor_)  or  conversion functions
  (_class.conv_) are not called.

  5.4  Explicit type conversion (cast notation)              [expr.cast]

4 The conversions performed by static_cast  (_expr.static.cast_),  rein-
  terpret_cast           (_expr.reinterpret.cast_),           const_cast
  (_expr.const.cast_), or any sequence thereof, can be  performed  using
  the  cast  notation  of  explicit  type conversion.  The same semantic
  restrictions and behaviors apply.  If a given conversion can  be  per-
  formed  using  either static_cast or reinterpret_cast, the static_cast
  interpretation is used.

The conversion '(A const&)b' can be interpreted as

static_cast <A const&> (b) or
reinterpret_cast <A const&> (b);

I think it is obvious from the [expr.cast] text that the former
interpretation is preferred, so xlC gets it 'wrong'.

The conversion '(A&)b' can be interpreted as

const_cast <A&> (static_cast <A const&> (b)) or
reinterpret_cast <A&> (b).

I don't think the WP is clear enough on this point to say conclusively what
the 'right' answer is.  Perhaps it should be considered ambiguous.
However, I believe that all existing compilers choose the latter option
here.

Jason