Topic: static_cast


Author: gi2nospam@mariani.ws (Gianni Mariani)
Date: Sat, 21 Aug 2004 19:46:36 GMT
Raw View
Richard Hayden wrote:
..
> Am I correct in saying that g++ version 3.3.1 does not obey the standard
> in this case and thus that static_cast when implemented correctly can
> cast between types where there are two levels of user-defined
> conversions required? If so, I ask why 2 as opposed to 1? Have I missed
> something?

FYI - gcc 3.2.2 and gcc 3.4.0 accepts your code.

.. slightly modified below.

/**************************/

class C1 {};

class C2 {
     public:
         C2(C1) {}
};

class C3 {
     public:
         C3(C2) {}
};

/**************************/


int main()
{

     C1 c1obj;
     C3 c3obj(c1obj);


     c3obj = static_cast<C3>(c1obj);
}

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rah03@doc.ic.ac.uk (Richard Hayden)
Date: Sat, 21 Aug 2004 22:19:19 GMT
Raw View
Gianni Mariani wrote:
> Richard Hayden wrote:
> ..
>
>> Am I correct in saying that g++ version 3.3.1 does not obey the
>> standard in this case and thus that static_cast when implemented
>> correctly can cast between types where there are two levels of
>> user-defined conversions required? If so, I ask why 2 as opposed to 1?
>> Have I missed something?
>
>
> FYI - gcc 3.2.2 and gcc 3.4.0 accepts your code.
>
> .. slightly modified below.
>
> /**************************/
>
> class C1 {};
>
> class C2 {
>     public:
>         C2(C1) {}
> };
>
> class C3 {
>     public:
>         C3(C2) {}
> };
>
> /**************************/
>
>
> int main()
> {
>
>     C1 c1obj;
>     C3 c3obj(c1obj);
>
>
>     c3obj = static_cast<C3>(c1obj);
> }
>
> ---
> [ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]
>

OK, I've verified that the exact code you've supplied above returns the
following error in g++ 3.3.1:

error: invalid static_cast from type `C1' to type `C3'

So I assume this an error on the part of g++?

Furthermore, why does static_cast allow conversions which require two
consecutive user-defined conversions? This just doesn't seem right to me
since all of the overloading documentation discusses implicit conversion
sequences as consisting of a standard conversion followed by one user
defined conversion followed by a standard conversion. It seems strange
that static_cast should be any different?

Thanks,

Richard Hayden.

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rah03@doc.ic.ac.uk (Richard Hayden)
Date: Sat, 21 Aug 2004 18:19:26 GMT
Raw View
Hi,

Given the following code:

/**************************/

class C1 {};

class C2 {
public:
     C2(C1) {}
};

class C3 {
public:
     C3(C2) {}
};

/**************************/

This (assuming everything is in scope etc.):

C1 c1obj;
C3 c3obj(c1obj);

works fine in g++ version 3.3.1 (as you would imagine).

However this:

C1 c1obj;
static_cast<C3>(c1obj);

doesn't (as I expected since it requires two user-defined conversions to
convert from C1 to C3). g++ says 'invalid static_cast from C1 to C3'.
But this is in contradiction to the standard, which says:

5.2.9/2:

"An expression e can be explicitly converted to a type T using a
static_cast of the form static_cast<T>(e) if the declaration  T t(e); is
wellformed, for some invented temporary variable t (8.5). The effect of
such an explicit conversion is the same as performing the declaration
and initialization and then using the temporary variable as the result
of the conversion. The result is an lvalue if T is a reference type
(8.3.2), and an rvalue otherwise. The expression e is used as an lvalue
if and only if the initialization uses it as an lvalue."

Am I correct in saying that g++ version 3.3.1 does not obey the standard
in this case and thus that static_cast when implemented correctly can
cast between types where there are two levels of user-defined
conversions required? If so, I ask why 2 as opposed to 1? Have I missed
something?

Thanks,

Richard Hayden.

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John E. Potter)
Date: 1997/03/03
Raw View
On reading static_cast and standard conversions several times, it seems
that the intent of static_cast is to allow explicit use of all implicit
conversions and some of their inverses.  This led to several questions.

4/3 says  T t = e  iff implicit conversion from e to T.

class B { };
class D : public B { };
void foo () {
 D d;
 B b = d;  // implicit conversion
 D& rd(d);
 B& rb = rd; // implicit conversion
 static_cast<B&>(d); // valid by 5.2.9/2
 }
Would an explicit copy ctor for B affect this in any way?

Since implicit conversion of built-in types is covered by standard
conversions, should I conclude that reference types are not built-in
types although pointer types are?

Static_cast 5.2.9 contains
   /2 permitting any implicit conversion
   /4 conversion to void
   /5 B& -> D&, the inverse of the above implicit (not standard) conversion

The following is an attempt to nail down 5.2.9/6.  The question was
originally raised by James Kanze several months ago and received no
complete reply.  My conclusion is a question.

5.2.9/6 allows inverses of some standard conversions with the standard
cv restrictions.  The question is, what are those conversions?

4.1 lvalue to rvalue: excluded
4.2 array to pointer: excluded
4.3 function to pointer: excluded
4.4 qualification: excluded by the standard cv restriction
4.5 integral promotions: inverses of all but enum -> int are in 4.7
   and are thus covered by 5.2.9/2.  int -> enum is 5.2.9/7
4.6 floating promotions: inverse in 4.8 covered by 5.2.9/2
4.7 integral conversions: inverses in 4.7 or 4.5 covered by 5.2.9/2
4.8 floating conversions: inverses in 4.6 or 4.8 covered by 5.2.9/2
4.9 floating/integral conversions: self inverting covered by 5.2.9/2
4.10 pointer conversions:
   /2 T* -> void*: inverse not covered elsewhere, FOUND ONE
   /3 D* -> B*: inverse is 5.2.9/8
4.11 pointer to member B::* -> D::* : inverse is 5.2.9/9
4.12 boolean conversions: excluded (prevents bool -> T*)

I conclude that 5.2.9/6 could be replaced with "void* can be converted
to anything*" with the standard cv restrictions.  It would be much
clearer, but perhaps less palatible.

Did I miss anything?

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: "linh (l.) dang" <linhd@bnr.ca>
Date: 1996/03/20
Raw View
>>>> "Matt" == Matt Austern <austern@isolde.mti.sgi.com> writes:

 Matt> In article <314c3f47.1349350@nntp.ix.netcom.com>
 Matt> jdmorris@ix.netcom.com (Jason D. Morris) writes:
 >> Aren't the old C style casts and C++ functional style casts
 >> depricated under the draft standard?

 Matt> No.  It's true that new-style casts (static_cast, dynamic_cast,
 Matt> reinterpret_cast and const_cast) are almost always a better
 Matt> solution, but old-style casts have not been deprecated.

Since static_cast is not always safe, did anyone consider a set of
implicit_cast<T> template functions as part of the standard library ?

e.g:

template<typename From, typename To>
inline To
implicit_cast(From x)
{
  return x;
}

....

These functions are efficient, safe and might be the fatal blow to the
old-style cast.

--
L.D.
--
=====================================================================
Linh Dang                                 Nortel Technology
Member of Scientific Staff                Speech Recognition Software
linhd@nortel.ca
=====================================================================
---
[ 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: "Nathan Myers, http://www.cantrip.org/" <ncm@cantrip.org>
Date: 1996/03/21
Raw View
linh (l.) dang wrote:

> Since static_cast is not always safe, did anyone consider a set of
> implicit_cast<T> template functions as part of the standard library ?

They were considered at the meeting in Tokyo (Nov. '95) but
rejected as an extension proposal that arrived just too late.
(I gather they were left out of the proposal for the original
suite of casts because they could be implemented in the library,
but nobody got around to proposing them to the library group
until too late.)

If they find wide use they might be added to the next C++ standard.

> These functions are efficient, safe and might be the fatal blow to the
> old-style cast.

One can dream, at least.

Nathan Myers
ncm@cantrip.org  http://www.cantrip.org/
---
[ 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: jpotter@falcon.lhup.edu (John E. Potter)
Date: 1996/03/17
Raw View
alice yang (aliceyang@worldnet.att.net) wrote:
: C++ Guru
:  Would you help me to understand the importance of using "static-cast"?

I responded to this via e-mail.  Much the same as Kanze.  I also had a
problem coming up with an example of static_cast.  The following prompted
some concern that it could be infered that static_cast is useless.

> "when do I HAVE to use static_cast explicity".  It seems that c cast
> can do the same thing anyway (as far as static-cast is concerned)

I also read James Kanze post to your question.  Seems that we agree mostly
except that he prefers the C style since it clears ambiguities while I
prefer the C++ functional style because it looks like an explicit
constructor call.  We all know that that can not be done, but effectively
that is what happens.  The technical rules are:
float(intThing) ==> (float)intThing ==> static_cast<float>(intThing) ==>
create an unnamed temporary float constructed by a standard conversion
from int.  Wow!  By the way, it is an rvalue; so, this is not legal:

float floatThing = float(intThing) *= anotherThing;

However, had it been a class item rather than a built-in and *= were a
member function, the above would be legal.  Non-const member functions
may be used with rvalues.

I did think of an example where I would use static_cast; however, James
would not need to.

long double ld = static_cast<long double>(intThing);

The C++ functional form of cast can not be used except with simple type
identifiers.  Since I prefer function style casts, I always made a bunch
of typedefs to allow their use.

typedef long double longDouble;
long double ld = longDouble(intThing);

I think that I will shift from that to static_cast when my compilers all
catch up to the new rules.  Only one of my four compilers currently
support the new casts.

One word of caution.  In the above formal rules, the step from C style
cast to new style cast has three possibilities.  The compiler must decide
which is appropriate.  I generally do not trust compilers and prefer to
be explicit.  Here is a nasty example.

Thing fun (const Thing& t) {
 return Thing(t) += 10;
 }

The class Thing has a constructor which takes an int.  Since t is of type
thing, the cast calls for use of the copy constructor.  The class does have
a member +=.  I said:

 return static_cast<Thing>(t) += /* implicit */ static_cast<Thing>(10);

The compiler heard:

 return const_cast<Thing>(t) += /* implicit */ static_cast<Thing>(10);

Boy was that a shock.  All of my const parameters got modified and gave
total garbage for results.  The down side is that the compiler did not
support the new casts so that I could not be explicit.  The real problem
was that the compiler did not generate a copy constructor so it could
not use a static_cast.  The rules say that there is always a copy
constructor.  Some people, including compiler writers, think that
declaring any constructor cancels both the generated default and
copy constructors.  Any constructor, including the copy constructor,
cancels the default constructor; however, there must always be a
copy constructor.  There can be two but never none.  I solved my
problem by declaring the copy constructor.

With compilers racing to catch the moving C++ standard, bugs like this
will be around for a while.  If your compiler supports the new style
casts, I would strongly recomend using them in place of C style or C++
functional style.  An explicit conversion/copy constructor call sure looks
nicer, but static_cast reminds us of what we are really doing.

John
---
[ 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: jdmorris@ix.netcom.com (Jason D. Morris)
Date: 1996/03/18
Raw View
Aren't the old C style casts and C++ functional style casts depricated
under the draft standard?

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