Why would you cast the lhs of an assignment? - c++

I came across some code that boils down to the following:
enum BAR { /* enum values omitted */ }
class Foo{
public:
void set(const BAR& bar);
private:
uint32_t bits;
};
void Foo::set(const BAR& bar)
{
(uint32_t&)bits = bits | bar;
}
I don't understand the point of the c-style cast in the assignment in Foo::set. Why would you cast the lhs of an assignment? Am I crazy, or does this have a purpose?

In this case, I can't see any reason for the cast, as the thing being cast is of the same type as the cast. In general, it could be used to force a particular assignement operator to be used.
I will now repeat my mantra: If your code contains casts, there is probably something wrong with the code or the design and you should examine both with a view to removing the cast.

I agree with Neil Butterworth, the cast in this case isn't necessary and it is a definite "code smell".

It does nothing at all, as far as I can tell, even if BAR is defined with values outside the uint32 range. Looks like noise to me.

I can't say for sure without knowing the background, but it looks like someone may have taken some existing C code and wrapped it in a C++ class. The cast may be a leftover from the c code.

I'm not sure this is legal. a cast is not an lvalue...
Either way, it looks fairly pointless.

If you only want to permit certain value to be assigned (e.g., the checking on the assignment is done as if to variable typed as per the cast, instead of just letting anything go through as if you widened the rhs).

Related

Why can you do this conversion?

Why can you do this:
class Dummy {
double i,j;
};
class Addition {
int x,y;
public:
Addition (int a, int b) { x=a; y=b; }
int result() { return x+y;}
};
int main () {
Dummy d;
Addition * padd;
padd = (Addition*) &d;
cout << padd->result();
return 0;
}
Why is padd = (Addition*) &d; valid when it will generate a run-time error whenever it gets used afterwards? A quote from cplusplus.com:
Unrestricted explicit type-casting allows to convert any pointer into
any other pointer type, independently of the types they point to.
But why can you convert any pointer into any other pointer type just if you precede the reference with a casting operator?
Talking about that casting operator, how can it convert all types to another type? Does it call a conversion constructor because if so, I do not get it, because both Dummy nor Addition do not have a conversion constructor so how does this operation work then? How many operators does it have and is it the parentheses that are the operator itself, like = is an operator.
These kinds of casts are C style casts, and will let you cast just about anything to anything else. A cast is a statement to the compiler to disregard it's type safety rules and trust that you know best. This is sometimes necessary when the type system can't have all the information it needs to reach the right conclusions. However, if you are lying to the compiler about something's type, then you are producing undefined behavior.
In c++, you should avoid preforming C style casts and prefer the safer c++ alternatives (listed here. Theses casts can't completely protect you from yourself, but they do allow you to communicate the kind of cast you want to preform. Using this extra information, the compiler can warn you if your casts would do something other than what you expect them to do.
When you use:
padd = (Addition*) &d;
the compiler assumes that you, the person in charge, know what you are doing. If you shoot yourself in the foot, that's of your own choosing. The compiler is happy to let you do that.
If you would like the compiler to prevent you from such accidental, shoot-yourself-in-the-foot, situations, use static_cast.
padd = static_cast<Addition*>(&d);
The compiler will let you know that that is not OK.
If you use a C style cast, there is no check for errors or compatibility between the pointers. Also, I think you misunderstand the purpose of the unary operator &, in this case it gives the address of d and is not related to references.
Objects in memory are just bits that the program knows to be some type, if you tell it that it is another type it will not affect anything in the variable.

TypeCasting Struct and Classes

I am very new to C++. Currently I am reviewing a source code where I saw some typecasting, but I didn't understand it.
Here is the code.
struct str {
char *a;
int b;
};
class F {
public:
char* val;
};
F f1;
Can anyone explain the below Assignement Please.or is that typecasting valid??
str* ptr = (str*) f1->val;
Can anyone explain the below Assignement Please.
It means "pretend that the val pointer points to an object of type str, even though it's declared to point to a completely different type char; give me that pointer and trust that I know what I'm doing".
That's assuming that the real code either declares F * f1;, or accesses it as f1.val; the code you've posted won't compile.
or is that typecasting valid??
If the pointer really does point to an object of the correct type, then it's valid; otherwise, using the pointer will cause the program to fail in all sorts of catastrophic ways.
Typecasting is something that should very rarely be necessary. If you really do need it, you should never (as in absolutely never, under any circumstances) use that C-style cast; it means "force the conversion with no checks whatsoever, as long as there's some way to do it, even if it makes absolutely no sense". Use static_cast or dynamic_cast when you can, and reinterpret_cast or const_cast when you're doing something really dodgy. And don't use any of them unless you know what you're doing, and have a very good reason for circumventing the type system.

C++ reference syntax

Which is the correct way to specify a reference. I know both works with the compiler, but wanted to know the correct way since I have seen both in code bases.
void Subroutine(int &Parameter)
{
Parameter=100;
}
OR
void Subroutine(int& Parameter)
{
Parameter=100;
}
There is no 'correct' way, in the same way like there is no 'correct' way to place your parentheses and brackets. It's a matter of style and preference.
It's more important to be consistent.
When it comes to pointers, C programmers tend to write int *i which reads "evaluating *i yields an int". This is not possible with references. If you write int &i, evaluating &i does not yield an int, but rather a pointer to an int, because & has different meanings in declarations and expressions.
That's why I prefer to declare reference variables as int& i, because i is a reference to an int.
It's a matter of preference, both are correct, personally I nowadays like to write it as type&
I think the two are functionally identical. I personally prefer int& Parameter since it makes more sense to me -- i.e. a variable named Parameter is of type reference-to-int, whereas int &Parameter doesn't immediately make that connection to me. Most examples I've seen use the int& form as well. (i.e. see http://www.cprogramming.com/tutorial/references.html).
That's code style issue, no one is good or bad, correct or wrong.
I use this:
int & a;
int * b;
Too many spaces (any maybe a little confusing with binary operator & and *) but it looks clear to me.
As long as consistent, whatever your style is correct.

Can parentheses take arbitrary identifiers as arguments? C++

For example, is
(const int)* someInt;
valid code?
If so, is that statement different than
const int* someInt;
?
You can put arbitrarily many parentheses around expressions without changing the meaning. But you cannot do the same with types. In particular, as the others have pointed out, the parenthese in your code change the meaning from a declaration to a cast.
You can do a c style cast with any type inside, but the expression that you are trying to cast may not be able to be casted that way.
You can't have any arbitrary type on the right hand side of a cast. You need a user defined conversion operator to perform the conversion.
This seems for me valid, because you can have everytime a pointer to an constant value.
I don't think that between the two exists an difference.
if someInt is defined as
int *someInt;
then
(const int)* someInt;
is valid. Else you will encounter error.
You deference a pointer to int and cast the resulting value to const int.
And yes, this statement without an assignment, is wasted.
int rtn = (const int)* someInt;

why implicit conversion is harmful in C++

I understand that the keyword explicit can be used to prevent implicit conversion.
For example
Foo {
public:
explicit Foo(int i) {}
}
My question is, under what condition, implicit conversion should be prohibited? Why implicit conversion is harmful?
Use explicit when you would prefer a compiling error.
explicit is only applicable when there is one parameter in your constructor (or many where the first is the only one without a default value).
You would want to use the explicit keyword anytime that the programmer may construct an object by mistake, thinking it may do something it is not actually doing.
Here's an example:
class MyString
{
public:
MyString(int size)
: size(size)
{
}
//... other stuff
int size;
};
With the following code you are allowed to do this:
int age = 29;
//...
//Lots of code
//...
//Pretend at this point the programmer forgot the type of x and thought string
str s = x;
But the caller probably meant to store "3" inside the MyString variable and not 3. It is better to get a compiling error so the user can call itoa or some other conversion function on the x variable first.
The new code that will produce a compiling error for the above code:
class MyString
{
public:
explicit MyString(int size)
: size(size)
{
}
//... other stuff
int size;
};
Compiling errors are always better than bugs because they are immediately visible for you to correct.
It introduces unexpected temporaries:
struct Bar
{
Bar(); // default constructor
Bar( int ); // value constructor with implicit conversion
};
void func( const Bar& );
Bar b;
b = 1; // expands to b.operator=( Bar( 1 ));
func( 10 ); // expands to func( Bar( 10 ));
A real world example:
class VersionNumber
{
public:
VersionNumber(int major, int minor, int patch = 0, char letter = '\0') : mMajor(major), mMinor(minor), mPatch(patch), mLetter(letter) {}
explicit VersionNumber(uint32 encoded_version) { memcpy(&mLetter, &encoded_version, 4); }
uint32 Encode() const { int ret; memcpy(&ret, &mLetter, 4); return ret; }
protected:
char mLetter;
uint8 mPatch;
uint8 mMinor;
uint8 mMajor;
};
VersionNumber v = 10; would almost certainly be an error, so the explicit keyword requires the programmer to type VersionNumber v(10); and - if he or she is using a decent IDE - they will notice through the IntelliSense popup that it wants an encoded_version.
Mostly implicit conversion is a problem when it allows code to compile (and probably do something strange) in a situation where you did something you didn't intend, and would rather the code didn't compile, but instead some conversion allows the code to compile and do something strange.
For example, iostreams have a conversion to void *. If you're bit tired and type in something like: std::cout << std::cout; it will actually compile -- and produce some worthless result -- typically something like an 8 or 16 digit hexadecimal number (8 digits on a 32-bit system, 16 digits on a 64-bit system).
At the same time, I feel obliged to point out that a lot of people seem to have gotten an almost reflexive aversion to implicit conversions of any kind. There are classes for which implicit conversions make sense. A proxy class, for example, allows conversion to one other specific type. Conversion to that type is never unexpected for a proxy, because it's just a proxy -- i.e. it's something you can (and should) think of as completely equivalent to the type for which it's a proxy -- except of course that to do any good, it has to implement some special behavior for some sort of specific situation.
For example, years ago I wrote a bounded<T> class that represents an (integer) type that always remains within a specified range. Other that refusing to be assigned a value outside the specified range, it acts exactly like the underlying intger type. It does that (largely) by providing an implicit conversion to int. Just about anything you do with it, it'll act like an int. Essentially the only exception is when you assign a value to it -- then it'll throw an exception if the value is out of range.
It's not harmful for the experienced. May be harmful for beginner or a fresher debugging other's code.
"Harmful" is a strong statement. "Not something to be used without thought" is a good one. Much of C++ is that way (though some could argue some parts of C++ are harmful...)
Anyway, the worst part of implicit conversion is that not only can it happen when you don't expect it, but unless I'm mistaken, it can chain... as long as an implicit conversion path exists between type Foo and type Bar, the compiler will find it, and convert along that path - which may have many side effects that you didn't expect.
If the only thing it gains you is not having to type a few characters, it's just not worth it. Being explicit means you know what is actually happening and won't get bit.
To expand Brian's answer, consider you have this:
class MyString
{
public:
MyString(int size)
: size(size)
{
}
// ...
};
This actually allows this code to compile:
MyString mystr;
// ...
if (mystr == 5)
// ... do something
The compiler doesn't have an operator== to compare MyString to an int, but it knows how to make a MyString out of an int, so it looks at the if statement like this:
if (mystr == MyString(5))
That's very misleading since it looks like it's comparing the string to a number. In fact this type of comparison is probably never useful, assuming the MyString(int) constructor creates an empty string. If you mark the constructor as explicit, this type of conversion is disabled. So be careful with implicit conversions - be aware of all the types of statements that it will allow.
I use explicit as my default choice for converting (single parameter or equivalent) constructors. I'd rather have the compiler tell me immediately when I'm converting between one class and another and make the decision at that point if the conversion is appropriate or instead change my design or implementation to remove the need for the conversion completely.
Harmful is a slightly strong word for implicit conversions. It's harmful not so much for the initial implementation, but for maintenance of applications. Implicit conversions allow the compiler to silently change types, especially in parameters to yet another function call - for example automatically converting an int into some other object type. If you accidentally pass an int into that parameter the compiler will "helpfully" silently create the temporary for you, leaving you perplexed when things don't work right. Sure we can all say "oh, I'll never make that mistake", but it only takes one time debugging for hours before one starts thinking maybe having the compiler tell you about those conversions is a good idea.