Archived

This topic is now archived and is closed to further replies.

felonius

do you use static_cast or C-style cast?

Recommended Posts

According to The C++ Programming language it seems that one should use static_case, const_cast, reinterpret_cast and dynamic_cast in favor for C-style casts. I am, however, finding that I am having trouble to change habits to them since it requires me to write more code and because I feel it messes my code more than C-style casts - although I understand the arguments for the contrary. Furthermore, since C++ supports user-defined conversions that when used are using the syntax of the C-style cast I think C++ is a somewhat inconsistant at this point. My question here is, do you use the new casts types or do you style use C-style casts? Why? And if yes, how did you manage to change style? Did you find it worthwhile?

Share this post


Link to post
Share on other sites
quote:
Original post by felonius
I am, however, finding that I am having trouble to change habits to them since it requires me to write more code and because I feel it messes my code more than C-style casts - although I understand the arguments for the contrary.

Since you don''t state what they are, it''s not clear what you think the arguments to the contrary are. Here''s a couple that you may already have heard:

1. The c-style cast syntax is overloaded in meaning, and so it is not always clear what is intended. Splitting the possible meanings into different language constructs achieves higher intentionality.

2. Since casts are generally considered undesirable, the fact that they "mess-up" the visual appearance of your source can be considered A Good Thing. It makes them easy to grep for, and the presence of such a construct should provide a visual jolt to an experienced developer.
quote:

Furthermore, since C++ supports user-defined conversions that when used are using the syntax of the C-style cast I think C++ is a somewhat inconsistant at this point.

Can you give an example of such a user-defined conversion? I suspect you''re talking about function-style casts. Those too are sometimes regarded as poor form, as are implicit conversions. The new-style casts are something that are somewhat justfied in being inconsistent. Since you won''t be using many of them, there should not be too much disruption to the symmetry of your programs.
quote:

My question here is, do you use the new casts types or do you style use C-style casts? Why?

Yes, for the reasons given above.
quote:

And if yes, how did you manage to change style?

By becoming convinced that it is worth the few hours of mental discipline to get into the habit of using them.
quote:

Did you find it worthwhile?

Yes.


[ C++ FAQ Lite | ACCU | Boost | Python | Agile Manifesto! ]

Share this post


Link to post
Share on other sites
I use new style casts - absolutely necessary for dynamic_cast - use RTTI and don''t use c-style casts for that - I have seen numerous bugs related to code using c-style casts when dynamic_cast would have caught the problem.

I use const_cast to indicate when I am doing something sketchy.

I use reintepret_cast usually with void* and function pointers.

I admit for generic number conversion I might use a c-style cast - but usually the warning about conversion may lose significant digits is surpressed in our code base.

User-defined conversions can be somewhat sketchy - I generally avoid them and prefer explicit conversions - e.g. methods named GetAsString() or some such - I also avoid single parameter constructors and implicit conversion using the explicit keyword.

I do find it worthwhile to use the new casts - at the very least dynamic_cast is a must, but it also helps show what you are doing with the cast.

I force myself to use the correct casting operator by thinking about what I am trying to do and in our code reviews I check that in other people''s code.

Share this post


Link to post
Share on other sites
quote:
Original post by SabreMan
Since you don''t state what they are, it''s not clear what you think the arguments to the contrary are. Here''s a couple that you may already have heard:



You sum the arguments up very well. These are also presented in Stroustrups book so I didn''t think it was necessary to print here.

quote:

Can you give an example of such a user-defined conversion? I suspect you''re talking about function-style casts. Those too are sometimes regarded as poor form, as are implicit conversions.



I don''t know what a function-style cast is. "user-defined conversion" is the official term. Example:

class SmallInt {
public:
operator int();
};

---------

Could we get the story from somebody that tried the new casts and ditched them again?

Share this post


Link to post
Share on other sites
quote:
Original post by felonius
I don''t know what a function-style cast is. "user-defined conversion" is the official term.

Implicit conversions, including the one you showed are generally considered bad form, as they can allow erroneous code to compile. It is usually better to make conversions explicit, as SteveC explained. In that respect, the inconsistency issue becomes somewhat moot.
quote:

Could we get the story from somebody that tried the new casts and ditched them again?

Are you trying to convince yourself that the casts are worthwhile, or that they''re not worthwhile? Why don''t you try using them consistently throughout a project and then reflect on your own experiences? That might be the only good way to answer your own question.

Share this post


Link to post
Share on other sites
>> Are you trying to convince yourself that the casts are worthwhile, or that they''re not worthwhile?

Well, I am trying to figure out what people are doing in practice and would like the case reviewed from people from both sides. As said I have tried the new casts but feel uncomfortabele with them, so unless there is a strong force towards them I think I will just stick to the old ones.

I use casts mainly for two reasons,
* To do bit manipulations of various integer values or conversion between various integer types.
* As intended with dynamic_cast. I can accept dynamic_cast since I find that the run-time type check is useful.

And doing static_cast each time I need to change integer types just seem like a lot of fuss for nothing.

Share this post


Link to post
Share on other sites
I use the new-style casts in all my new code. I rarely need more than a couple of casts per file anyway, so it''s no big deal. Some compilers can give out extra warnings about these casts too, plus they are certainly safer (eg. casting away const-ness while being confident you aren''t inadvertently changing the value if you got something wrong).

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files ]

Share this post


Link to post
Share on other sites
I can''t bring myself to use the new casts. I do too much programming with C APIs that force casting all over the place. The new casts are too verbose for code that uses them extensively.

Share this post


Link to post
Share on other sites
quote:
Original post by sjelkjd
int someval=int(float(a)/float(100));



With syntax-highlight editor... this should be ok. But it really looks like function call to me... I would do these in the C-cast way for fundamental type.

But I''ll be using the CPP construct for doing class-casting.

Share this post


Link to post
Share on other sites
Yeah, I agree that the old C-style casts use a syntax that is consistant with constructors taking another class or type as argument and this speaks against using the new casts.

e.g. if I had a class Date and a class NumSec and had made a constructor to Data like this:

Date::Date(NumSec ns);

then I would be in fact casting between the two types when I wrote

mydate = Date(mynumsec);

or

mydate = (Date)mynumsec;

would you also use the new casts in this case? To me it seems that we are just using a constructor. These new cast styles just seems so inconsistant with the rest of C++ while C-style casts fit perfectly in.

Share this post


Link to post
Share on other sites
My 0.02 is that [1](int)x is much worse than [2]int(x). But maybe these are the same thing, i dunno. The way i see it is in [2] i''m constructing a temporary int(or whatever) and assigning it to lhs. So...is [2] the same as [1]? Or is my rationalization correct?

Share this post


Link to post
Share on other sites
quote:
Original post by sjelkjd
My 0.02 is that [1](int)x is much worse than [2]int(x). But maybe these are the same thing, i dunno. The way i see it is in [2] i''m constructing a temporary int(or whatever) and assigning it to lhs. So...is [2] the same as [1]? Or is my rationalization correct?


If I understand it correctly they ([1] and [2]) are semantically identical and this why I am having a hard time seeing why

int(x) is not deprecated while
(int)x is deprecated

Share this post


Link to post
Share on other sites
quote:
Original post by SabreMan
That''s a function-style cast.



Call it a constructor, call it a function-style cast, it is the same thing - at least when constructors only take a single argument. (In fact section 6.2.8 in Stroustrups book is titled "constructors" but is about function-style casts)

Why differentiate between function-style casts and type casts? Conceptually they seem to be the very same thing.

Share this post


Link to post
Share on other sites
quote:
Original post by felonius
Why differentiate between function-style casts and type casts?

Because they are only equivalent for built-in types. For a user-defined type, it is a construction rather than a cast.

Share this post


Link to post
Share on other sites
quote:
Original post by felonius
If I understand it correctly they ([1] and [2]) are semantically identical and this why I am having a hard time seeing why

int(x) is not deprecated while
(int)x is deprecated

Er, because the first one looks like a standard constructor call whereas the second one looks like nothing?



[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files ]

Share this post


Link to post
Share on other sites
reinterpret_cast
static_cast
dynamic_cast
etc.

Are these C++ language features? Or are they MS-specific language extensions?

Basically what I''m asking is, are they part of the ANSI/ISO C++ standard?

____________________________________________________________
Direct3D vs. OpenGL

Share this post


Link to post
Share on other sites
quote:
Original post by sjelkjd
Ok then, so a question: which is better style?
int i=float(f);
or int i=static_cast<float>(f);



Mind if I add some more?
....
OR
int i = (float)f;

is the assembly output the same for all?

Share this post


Link to post
Share on other sites
My 2 cents -- of course you''re avoiding casts as frequently as possible - but where their essential and clutter up code you can just stick a macro definition in misc.h or something like that. ie:
//misc.h
#define RCAST(p) (reinterpret_cast)p
#define CCAST(p) (static_cast)p
#define BLCAST(p) (broken_leg_cast)p

Share this post


Link to post
Share on other sites
I have been thinking this over, and here is what I will do in the future.

I will use the new dynamic_cast, reinterpret_case and const_cast as recommended in the standard since they are rare and needs special attention (dynamic_cast even does something useful).

I will use the C-style case instead of static_cast. I think static_cast just messes up the code and makes it inconsistant with function-style casts and user defined conversions. And it won''t protect you anyway since the user cannot be prevented from using C-style casts.

If the C++ standard commiteee wants to get rid of C-style casts they should remove it completely - possibly only when a certain compiler option is given. The current state of affairs is not satisfying.

Share this post


Link to post
Share on other sites
Just an interesting note, here''s a little trick I learned to convert one pointer to another, without using c-style casts, or new-style casts:


  
// say we have a new thread, and we want to convert the LPVOID parm to a pointer to some class, say CFoo


DWORD WINAPI ThreadProc(LPVOID pContext)
{
union
{
LPVOID pVoid;
CFoo* pFoo;
} uCaster;
uCaster.pVoid = pContext;
// you can now make calls on uCaster.pFoo

CFoo* pObj = uCaster.pFoo;
pObj->SomeMethod();
// or just

uCaster.pFoo->SomeMethod();
}



Yah, it''s just a loophole in the language, and it''s probably not very tasteful, but interesting none the less.

Share this post


Link to post
Share on other sites