Bjarne suggests using the condition in if's as scope restriction. In particular this example.
if ( double d = fd() ) {
// d in scope here...
}
I'm curios how to interpret the declaration in a true / false sense.
It's a declaration
It's a double.
Edit:
It's in 6.3.2.1 The C++ programming language as a recommendation.
Edit2: templatetypedefs suggestion of pointers, in particular with dynamic casts, might give insight to Bjarnes suggestion.
SteveJessop tells me: - A condition is not an expression it can also be a declaration, the value used, is the value being evaluated.
The code that you're seeing is a specialized technique for declaring variables in if statements. You commonly see something like this:
if (T* ptr = function()) {
/* ptr is non-NULL, do something with it here */
} else {
/* ptr is NULL, and moreover is out of scope and can't be used here. */
}
A particularly common case is the use of dynamic_cast here:
if (Derived* dPtr = dynamic_cast<Derived*>(basePtr)) {
/* basePtr really points at a Derived, so use dPtr as a pointer to it. */
} else {
/* basePtr doesn't point at a Derived, but we can't use dPtr here anyway. */
}
What's happening in your case is that you're declaring a double inside the if statement. C++ automatically interprets any nonzero value as true and any zero value as false. What this code means is "declare d and set it equal to fd(). If it is nonzero, then execute the if statement."
That said, this is a Very Bad Idea because doubles are subject to all sorts of rounding errors that prevent them from being 0 in most cases. This code will almost certainly execute the body of the if statement unless function is very well-behaved.
Hope this helps!
In the example Stroustrup gives, the code in the if block divides a value by d:
if (double d = prim(true)) {
left /= d;
break;
}
Division by 0 is undefined behavior, so it makes some sense in this case to test d against the value 0.0 before dividing. Putting the definition in the condition is a convenient way to do this, for the reasons Stroustrup states.
Your code gives no reason why the value 0.0 would be special, and therefore it is not clear why anyone would combine the definition of d with that test. Only use Stroustrup's pattern when "false" values of the type you're defining need to be treated specially. Otherwise just do this:
{
double d = fd();
// d in scope here...
}
It is both a declaration and a double. This is quite equivalent to
{
double d = fd();
if (d) {
}
}
However, this pattern is worth the small additional syntax to simplify, as it is fairly useful and common. In addition, the transformation is less obvious once you start adding else clauses, as d is out of scope for them.
Also, as others have noted, it's useful in general but FP types in specific have some issues when compared against 0.
the if statement predicates on the value that is assigned to the variable in the assignment expression. If the double evaluates to anything but 0.0 it will run the code inside.
Note that you are not supposed to compare doubles with zero, but it generally works in my experience.
Basically, you shouldn't do this.
The other contributors to this topic have found that this expression is used to exclude the zero case so as to avoid a divide-by-zero. That's definitely smart and such a situation legitimizes this usage as far as I'm concerned (but do consider the confusion such code may cause).
Related
I have stumbled upon the following code structure and I'm wondering whether this is intentional or just poor understanding of casting mechanisms:
struct AbstractBase{
virtual void doThis(){
//Basic implementation here.
};
virtual void doThat()=0;
};
struct DerivedA: public AbstractBase{
virtual void doThis(){
//Other implementation here.
};
virtual void doThat(){
// some stuff here.
};
};
// More derived classes with similar structure....
// Dubious stuff happening here:
void strangeStuff(AbstractBase* pAbstract, int switcher){
AbstractBase* a = NULL;
switch(switcher){
case TYPE_DERIVED_A:
// why would someone use the abstract base pointer here???
a = dynamic_cast<DerivedA*>(pAbstract);
a->doThis();
a->doThat();
break;
// similar case statement with other derived classes...
}
}
// "main"
DerivedA* pDerivedA = new DerivedA;
strangeStuff( pDerivedA, TYPE_DERIVED_A );
My guess is, that this dynamic_cast statement is just the result of poor understanding and very bad programming style in general (the whole way the code works, just feels painful to me) and that it doesn't cause any change in behaviour for this specific use case.
However, since I'm not an expert on casting, I'd like to know whether there are any subtle side-effects that I'm not aware of.
Blockquote [C++11: 5.2.7/9]: The value of a failed cast to pointer type is the null pointer value of the required result type.
The dynamic_cast can return NULL if the type was wrong, making the following lines crash. Hence, this can be either 1. an attempt to make (logical) errors more explicit, or 2. some sort of in-code documentation.
So while it doesn't look like the best design, it is not exactly true that the cast has no effect whatsoever.
My guess would be that the coder screwed up.
A second guess would be that you skipped a check for a being null in your simplification.
A third, and highly unlikely possibility, is that the coder was exploiting undefined behavior to optimize.
With this code:
a = dynamic_cast<DerivedA*>(pAbstract);
a->doThis();
if a is not of type DerivedA* (or more derived), the a->doThis() is undefined behavior. And if it is of type DerivedA*, then the dynamic_cast does absolutely nothing (guaranteed).
A compiler can, in theory, optimize out any other possibility away, even if you did not change the type of a, and remain conforming behavior. Even if someone later checks if a is null, the execution of undefined behavior on the very next line means that the compiler is free not to set a to null on the dynamic_cast line.
I would doubt that a given compiler would do this, but I could be wrong.
There are compilers that detect certain paths cause undefined behavior (in the future), eliminate such possibilities from happening backwards in execution to the point where the undefined behavior would have been set in motion, and then "know" that the code in question cannot be in the state that would trigger undefined behavior. It can then use this knowledge to optimize the code in question.
Here is an example:
std::string foo( unsigned int x ) {
std::string r;
if (x == (unsigned)-1)) {
r = "hello ";
}
int y = x;
std::stringstream ss;
ss << y;
r += ss.str();
return r;
}
The compiler can see the y=x line above. If x would overflow an int, then the conversion y=x is undefined behavior. It happens regardless of the result of the first branch.
In short, if the first branch runs, undefined behavior would result. And undefined behavior can do anything, including time travel -- it can go back in time and prevent that branch from being taken.
So the
if (x == (unsigned)-1)) {
r = "hello ";
}
branch can be eliminated by the optimizer, legally in C++.
While the above is just a toy case, gcc does optimizations very much like this. There is a flag to tell it not do.
(unsigned -1 is defined behavior, but overflowing an int is not, in C++. In practice, this is because there are platforms in which signed int overflow causes problems, and C++ doesn't want to impose extra costs on them to make a conforming implementation.)
dynamic_cast will confirm that the dynamic type does match the type indicated by the switcher variable, making the code slightly less dangerous. However, it will give a null pointer in the case of a mismatch, and the code neglects to check for that.
But it seems more likely that the author didn't really understand the use of virtual functions (for uniform treatment of polymorphic types) and RTTI (for the rarer cases where you need to distinguish between types), and attempted to invent their own form of manual, error-prone type identification.
Casts are used for both type conversion and disambiguation. In further research I found these two as examples :
(double) 3; // conversion
(double) 3.0; // disambiguation
Can someone explain the difference, I don't see any. Is this distinction, also valid in C++
EDIT
Originally the code snippet was like so:
(float) 3; // conversion
(float) 3.0; // disambiguation
But changed it to double because floating point literals are no longer float in modern compilers and the question had no meaning. I hope I interpreted the comments correctly and I appologize for any answer already posted that became irrelevant after the edit.
The (double) 3 is a conversion from an Integer (int) to a floting point number (double).
The cast in (double) 3.0 is useless, it doesn't do anything since it's already double.
An unsuffixed floating constant has type double.
(ANSI C Standard, §3.1.3.1 Floating constants)
This answer is valid for C, it should be the same in C++.
This is similar to many things asked of programmers in any language. I will give a first example, which is different from what you are asking, but should illustrate better why this would appear wherever you've seen it.
Say I define a constant variable:
static const a = 5;
Now, what is 'a'? Let's try again...
static const max_number_of_buttons = 5;
This is explicit variable naming. It is much longer, and in the long run it is likely to save your ass. In C++ you have another potential problem in that regard: naming of member variables, versus local and parameter variables. All 3 should make use of a different scheme so when you read your C++ function you know exactly what it is doing. There is a small function which tells you nothing about the variables:
void func(char a)
{
char b;
b = a;
p = b * 3;
g = a - 7;
}
Using proper naming conventions and you would know whether p and g are local variables, parameters to the function, variable members, or global variables. (This function is very small so you have an idea, imagine a function of 1,000 lines of code [I've seen those], after a couple pages, you have no idea what's what and often you will shadow variables in ways that are really hard to debug...)
void func(char a)
{
char b;
b = a;
g_p = b * 3;
f_g = a - 7;
}
My personal convention is to add g_ for global variables and f_ for variable members. At this point I do not distinguish local and parameter variables... although you could write p_a instead of just a for the parameter and now you know for all the different types of variables.
Okay, so that makes sense in regard for disambiguation of variable names, although in your case you specifically are asking about types. Let's see...
Ada is known for its very strong typing of variables. For example:
type a is 1 .. 100;
type b is 1 .. 100;
A: a;
B: b;
A := 5;
B := A;
The last line does NOT compile. Even though type a and type b look alike, the compiler view them both as different numeric types. In other words, it is quite explicit. To make it work in Ada, you have to cast A as follow:
B := B'(A);
The same in C/C++, you declare two types and variables:
typedef int a;
typedef int b;
a A;
b B;
A = 5;
B = A;
That works as is in C/C++ because type a and type b are considered to be exactly the same (int, even though you gave them names a and b). It is dearly NOT explicit. So writing something like:
A = (b) 5;
would explicitly tell you that you view that 5 as of type b and convert it (implicitly) to type a in the assignment. You could also write it in this way to be fully explicit:
A = a(b(5));
Most C/C++ programmers will tell you that this is silly, which is why we have so many bugs in our software, unfortunately. Ada protects you against mixing carrots and bananas because even if both are defined as integers they both are different types.
Now there is a way to palliate to that problem in C/C++, albeit pretty much never used, you can make use of a class for each object, including numbers. Then you'd have a specific type for each different type (because variables of class A and class B cannot just be mixed together, at least not unless you allow it by adding functions for the purpose.) Very frankly, even I do not do that because it would be way too much work to write any C program of any length...
So as Juri said: 3.0 and (double) 3.0 are exactly the same thing and the (double) casting is redundant (a pleonasm, as in you say the same thing twice). Yet, it may help the guy who comes behind you see that you really meant for that number to be a double and not whatever the language says it could eventually be.
I was reading the Wikipedia article about Undefined behaviour.
in C the use of any automatic variable before it has been initialized yields undefined behavior
However, this answer says, it is ok for character types. Is Wikipedia wrong here?
In C (I have no idea about C++), the type unsigned char is the only type that guarantees all possible bit representations have a specific value. There is no trap representation, no invalid values, no padding bits, no nothing (as can be in other types).
However it is a bad idea to make a program that relies on an unknown bit pattern for some reason.
Undefined behavior does not mean illegal or your program will crash here.
If you use an uninitialized variable (which happens if you allocate a primitive variable and don't assign a value to it, character types being one special kind of primitive types), the value is simply not determined. It can be anything. You might not bother the fact that it can be anything, because for example you could assign a value later, maybe only in some case.
However, when this becomes serious is when you read the value of the variable and make further decisions depending on this uninitialized value, for example in a condition:
int x;
if (x > 0) {
...
} else {
...
}
This will bring you here.
What the answer you linked says is that the following is perfectly fine:
int x;
if (someCase) {
x = ...
} else {
...
}
// later:
if (someCase) {
// read x
}
I understand what a double exclamation mark does (or I think I understand) but I am not sure how it is defined on a random object. For example in the code snippet below:
Assignment *a;
if (!getAssignment(query, a))
return false;
hasSolution = !!a;
if (!a)
return true;
How do I know what value will the double exclamation mark result in ? In other words does it always convert to true ? false ? or can you define a behavior for it such as executing a method to determine the result (how does the object know how to act in this situation) ? I am bit confused about this piece of code due to all these exclamation stuff going on.. Any explanation is appreciated.
Hope I was clear and thanks.
a is a pointer. In C++, nullptr is defined to be an invalid pointer. !pointer turns a nullptr pointer into true and a non nullptr pointer into false. !boolean turns true into false and false into true. It will always work.
!(!a) is a useful way to think of it.
Don't think of it as "double exclamation mark", think of it as two separate operators, one running on the result of the other.
For all primitive types, it will "work". !a is equivalent to a == 0, so !!a is equivalent to !(a == 0), which in turn is equivalent to a != 0.
For user-defined types, it won't compile unless they overload operator !. But obviously, in this case, the behaviour could be almost anything.
!! is not a single token in C++ and simply resolves to applying the ! operator twice.
As a is a pointer and not an object of class type the ! cannot be overloaded. It is defined to return true if a is a null pointer and false otherwise.
The second application of ! simply negates the result of the first !.
The expression !!a is equivalent to a != 0.
The code is horribly complicated. In reality, you want to test whether the getAssigment method is successful and whether the assigned pointer is non-null.
The code tests that, albeit in a convoluted fashion, taking advantage of weak typing, rather than trying to embrace explicitness and C++’ strong typing. As a consequence, it’s not idiomatic C++ and rather harder to understand than necessary.
In particular, don’t use !!a in C++. This is an established idiom in weakly-typed languages such as JavaScript to coerce a value into a boolean type. But in C++, this is not commonly used.
It’s not clear what the code does since hasSolution isn’t defined or used. However, I suspect that the code is supposed to be equivalent to the following:
Assignment *a;
return getAssignment(query, a) and a == nullptr;
(Before C++11, you need to write 0 instead of nullptr.)
However, this code still reveals a bad design: why is a passed by reference? Why isn’t it the return value? Worse, a is never used, so unnecessary. If a is indeed unnecessary, it should be left out completely. If it’s necessary, it should be the return value. In other words, the prototype of getAssignment should be as follows:
Assignment* getAssignment(the_type_of_query query);
And it should be used simply as follows:
Assignment* a = getAssignment(query);
Furthermore, I suspect that this code actually assigns memory ownership to the raw pointer a. This is strongly discouraged in modern C++. Either use no pointers or a smart pointer.
bool result = true;
result = !!result; // result = true, e.g. !result is false, !!result is !false.
There is no "!!" operator, so in fact, the statement is equivalent to:
hasSolution = !(!a);
So first, operator!() is called on expression "a", then another operator!() is called on the result. In the case of our code, "a" is a pointer to Assignement. C++ defines a special case for using operator!() on a pointer type: it returns a bool which is true if the pointer is null and false otherwise. In short, the same as the expression (a == 0). Calling operator!() on the result of (!a), which is a bool, simply reverts the result, i.e. returns true if (!a) is false and false if (!a) is true.
So in conclusion, (!!a) return the same result as (a != 0). This is because "a" is a pointer.
The easiest way to remember double-negation !!a is to narrow a!=0 to 1 and a==0 to 0.
Which is in boolean context (i.e. C++) true or false.
I recently saw a piece of code at comp.lang.c++ moderated returning a reference of a static integer from a function. The code was something like this
int& f()
{
static int x;
x++;
return x;
}
int main()
{
f()+=1; //A
f()=f()+1; //B
std::cout<<f();
}
When I debugged the application using my cool Visual Studio debugger I saw just one call to statement A and guess what I was shocked. I always thought i+=1 was equal to i=i+1 so
f()+=1 would be equal to f()=f()+1 and I would be seeing two calls to f(), but I saw only one. What the heck is this? Am I crazy or is my debugger gone crazy or is this a result of premature optimization?
This is what The Standard says about += and friends:
5.17-7: The behavior of an expression of the form E1 op= E2 is equivalent to
E1 = E1 op E2 except that E1 is
evaluated only once.[...]
So the compiler is right on that.
i+=1 is functionally the same as i=i+1. It's actually implemented differently (basically, it's designed to take advantage of CPU level optimization).
But essencially the left side is evaluated only once. It yields a non-const l-value, which is all it needs to read the value, add one and write it back.
This is more obvious when you create an overloaded operator for a custom type. operator+= modifies the this instance. operator+ returns a new instance. It is generally recommended (in C++) to write the oop+= first, and then write op+ in terms of it.
(Note this is applies only to C++; in C#, op+= is exactly as you assumed: just a short hand for op+, and you cannot create your own op+=. It is automatically created for you out of the Op+)
Your thinking is logical but not correct.
i += 1;
// This is logically equivalent to:
i = i + 1;
But logically equivalent and identical are not the same.
The code should be looked at as looking like this:
int& x = f();
x += x;
// Now you can use logical equivalence.
int& x= f();
x = x + 1;
The compiler will not make two function calls unless you explicitly put two function calls into the code. If you have side effects in your functions (like you do) and the compiler started adding extra hard to see implicit calls it would be very hard to actually understand the flow of the code and thus make maintenance very hard.
f() returns a reference to the static integer. Then += 1 adds one to this memory location – there's no need to call it twice in statement A.
In every language I've seen which supports a += operator, the compiler evaluates the operand of the left-hand side once to yield some type of a address which is then used both to read the old value and write the new one. The += operator is not just syntactic sugar; as you note, it can achieve expression semantics which would be awkward to achieve via other means.
Incidentally, the "With" statements in vb.net and Pascal both have a similar feature. A statement like:
' Assime Foo is an array of some type of structure, Bar is a function, and Boz is a variable.
With Foo(Bar(Boz))
.Fnord = 9
.Quack = 10
End With
will compute the address of Foo(Bar(Boz)), and then set two fields of that structure to the values nine and ten. It would be equivalent in C to
{
FOOTYPE *tmp = Foo(Bar(Boz));
tmp->Fnord = 9;
tmp->Quack = 10;
}
but vb.net and Pascal do not expose the temporary pointer. While one could achieve the same effect in VB.net without using "With" to hold the result of Bar(), using "With" allows one to avoid the temporary variable.