im a beginner starting to learn c++ i have a question.. Can i write scripts in do while loop i mean like this...
//you type do then like
do{
// your code here
}while(condition{ // <-- the question is here
then the code of the script
} ) closing Parenthesis and curly braces
yeah if you didn't understand that my question was that can i expand my condition in the while Parenthesis?? please answer because I'm learning C++ and I wanna improve.
The while condition takes an expression. That includes things like variables (foo), operators (1 + 2), and function calls. But it excludes things like if statements and additional loops. If you need to do something complicated inside of a while block, you should put it in a function.
do {
// ...
} while (should_continue(foo, bar));
bool should_continue(int foo, int bar) {
// ... complicated code goes here ...
}
Technically speaking, in C++11 and onward, you can create and evaluate a lambda in the same line, allowing arbitrary statements in expression context, but this is not very readable and should generally be a sign that your code needs to be split up into more functions.
// Don't do this; your coworkers will despise you.
do {
// ...
} while (([&]() {
// ... complicated code goes here ...
})());
Some non-portable compiler extensions will also allow the syntax you suggested in the question, where you can just throw braces { ... } with arbitrary statements in expression context. But, again, this is non-portable and not very readable code to begin with. So just write a function.
Related
For example, I'd like to have something like this:
If(condition) object.start();
// Do some unrelated processing
If(condition) object.stop();
As a simple example of what I would like to happen. Are there any language agnostic ways to organize this, especially as you have more conditional lines of code?
I suppose you're asking this because the condition is expensive or non-repeatable.
One typical solution would be to set a boolean variable in the first IF, and let the second IF check that boolean variable instead of re-executing the condition.
boolVar=false
if (condition) {
boolVar=true
object.start()
}
// do unrelated stuff
if (boolVar) {
object.stop()
}
Another typical solution would be something like this :
if (condition) {
object.start()
doSomething()
object.end()
} else {
doSomething()
}
Don't be afraid of simple solutions, if they're good enough. :)
I have code that does something like this:
//datareader.cpp
if (populateFoo(dataReader, foo))
else {
// Do other things with the reader.
}
//foo.cpp
bool populateFoo(const DataReader &dataReader, Foo &foo)
{
if (dataReader.name() == "bar") {
foo.bar() = dataReader.value();
return true;
} // More similar checks.
return false;
}
I feel like it's misleading to have an if statement with conditions that have side-effects. However, I can't move the body of the populateFoo function into datareader.cpp. Is there a good way to restructure this code so we get rid of this misleading if statement, without duplicating the body of populateFoo()?
Do you have a strong hatred of local variables? If not:
bool populated = populateFoo(dataReader, foo);
if (populated)
{
// Do things
}
else
{
// Do other things
}
The compiler will almost certainly emit exactly the same code, so performance shouldn't be an issue. It's a readability/style choice, ultimately.
The obvious solution seems like storing the result of populateFoo and using it for determining whether populateFoo was successful:
bool fooPopulated = populateFoo(dataReader, Foo);
if (!fooPopulated)
//Do other things with reader.
However, I don't find the original difficult to understand, and it's a fairly well-established practice to both modify values and test the success of the modification in the same line. However, I would change it to:
if (!populateFoo(dataReader, Foo)
//Do other things with reader.
How about:
if (!populateFoo(dataReader, foo)) {
// Do other things with the reader.
}
Edit: The title of the question suggests it is the fact the if statement is empty that bothers you but the body seems more that it is the side effect that is the concern. I think it's fine in C++ to have conditions in if statements that have side effects but this won't solve your issue if you want to avoid that.
Having conditions with side-effects is quite common - think about calling a C API and checking its return code for errors.
Usually, as long as it's not buried in a complicated expression where it may be missed by the casual bystander, I don't bother to do particular refactorings, but, in case you wanted to make it extra clear (or document what the return value is, which is particularly useful in case of booleans) just assign it to a variable before the branch - or even just a few comments may help.
You could split the populateFoo function into two, a const check function (shouldPopulateFoo) that checks the condition, and another non-const function that performs the actual modifications (populateFoo):
//datareader.cpp
if (shouldPopulateFoo(dataReader)) {
populateFoo(dataReader, foo);
}
else {
// Do other things with the reader.
}
//foo.cpp
bool shouldPopulateFoo(const DataReader &dataReader) /* const */
{
return (dataReader.name() == "bar");
}
void populateFoo(const DataReader &dataReader, Foo &foo) /* non-const */
{
assert(shouldPopulateFoo(dataReader));
foo.bar = dataReader.value();
}
Note that when using these functions as class methods, you could declare the check function const.
How about:
if (populateFoo(dataReader, foo) == false) {
// Do other things with the reader.
}
It is very readable, I often see code where the returned value from function is a signal to the caller for branching in the caller. The else block with empty if block bothers me more then the side effects inside the if (). There is a sense of reverse logic, which is alway less readable.
When refactoring some code, I often encounter this :
bool highLevelFunc foo()
{
// ...
bool result = LesserLevelFunc();
if (!result) return false;
// ... Keep having fun if we didn't return
}
Is there any way to make this a little more sexy and less verbose ? Without any overhead or pitfall of course.
I can think of a macro
#define FORWARD_IF_FALSE(r) if (!r) return r;
bool highLevelFunc foo()
{
// ...
FORWARD_IF_FALSE(LesserLevelFunc());
// ...
}
Anything better, i.e without preprocessor macro?
To me, "readable" code is sexy. I find the original code more readable than your proposal, since the original uses standard C++ syntax and the latter uses a macro which I'd have to go and look up.
If you want to be more explicit, you could say if (result == false) (or better yet, if (false == result) to prevent a possible assignment-as-comparison bug) but understanding the ! operator is a fairly reasonable expectation in my opinion.
That said, there is no reason to assign the return value to a temporary variable; you could just as easily say:
if (!LesserLevelFunc()) return false;
This is quite readable to me.
EDIT: You could also consider using exceptions instead of return values to communicate failure. If LesserLevelFunc() threw an exception, you would not need to write any special code in highLevelFunc() to check for success. The exception would propagate up through the caller to the nearest matching catch block.
Because you might be continuing if LesserLevelFunc returns true, I suggest keeping it pretty close to how it is now:
if (!LesserLevelFunc())
return false;
First of all introducing the macro you are making the code unsafe. Moreover your macro is invalid.
The expression after the negation operator shall be enclosed in parentheses.
#define FORWARD_IF_FALSE(r) if (!( r ) ) return r;
Secondly the macro calls r twice. Sometimes two calls of a function is not equivalent to one call of the same function. For example the function can have some side effects or internal flags that are switched on/off in each call of the function.
So I would keep the code as is without introducing the macro because the macro does not equivalent to the symantic of the original code.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?
Why is the do while(false) necessary in the macros below?
#define LOG(message, ...) \
do { \
Lock<MutualExclusion> lock (logMutex); \
.... a lot of code ...
} while (false)
I dont think it serves any functional purpose. Am I overlooking something?
It turns a block into a single statement. If you just use a block (i.e. code enclosed in {}) strange things can happen, for example
#define STUFF() \
{ do_something(); do_something_else(); }
if (cond)
STUFF();
else
//...
the extra semi-colon breaks the syntax. The do {} while(false) instead is a single statement.
You can find more about this and other macro tricks here.
So you are forced to add semicolon at the end of the macro, when you use it. This is a common idiom and only way to enforce it.
If somebody has code that does this:
if (something)
LOG("My log message");
That would expand to:
if (something)
Lock<MutualExclusion> lock (logMutex);
// A bunch of other code
Which is incorrect (only the first line would be under the if statement).
The macro makes sure that the macro call is inside of a block of code.
People use it because otherwise, you can screw up your ifs with compound statements. Imagine
#define hai int x; \
x = 0;
if (condition)
hai;
else
func();
Imagine what the preprocessed source looks like.
if (condition)
int x;
x = 0;
else
func();
Oh wait- now our else doesn't work.
Macros like that however are typically unnecessary in C++.
The reason for this weird practice in #define's is to encapsulate the different assignments within a loop that is executed exactly once, so one may use the macro like a function. For example, with the code you posted, one can write:
if(...)
LOG(x, y);
else
// Something else
and it is expanded as
if(...)
do {...} while(false);
else
// Something else
This would not work without the do...while(false) surrounding the different assignments, because that would be expanded as
if(...)
Lock<MutualExclusion> lock (logMutex);
// Other code... Outside the if statement!
Also forcing a semicolon after the macro makes it look like a function and you wont get errors because you added an semicolon like after a normal function.
It provides local scope to that which is inside the macro.
It looks to me like it is only used for scoping rules, so that Lock<MutualExclusion> falls out of scope at the end of the block.
If that's the reason for it, then it's completely unnecesarry:
// some other code...
string s = "oh hai";
{
Lock<MutualExclusion> lock(logMutex);
// MAGIC HAPPENS
}
s = "oh bai";
In C++ you can initialize a variable in an if statement, like so:
if (CThing* pThing = GetThing())
{
}
Why would one consider this bad or good style? What are the benefits and disadvantages?
Personally i like this style because it limits the scope of the pThing variable, so it can never be used accidentally when it is NULL. However, i don't like that you can't do this:
if (CThing* pThing = GetThing() && pThing->IsReallySomeThing())
{
}
If there's a way to make the above work, please post. But if that's just not possible, i'd still like to know why.
Question borrowed from here, similar topic but PHP.
The important thing is that a declaration in C++ is not an expression.
bool a = (CThing* pThing = GetThing()); // not legit!!
You can't do both a declaration and boolean logic in an if statement, C++ language spec specifically allows either an expression or a declaration.
if(A *a = new A)
{
// this is legit and a is scoped here
}
How can we know whether a is defined between one term and another in an expression?
if((A *a = new A) && a->test())
{
// was a really declared before a->test?
}
Bite the bullet and use an internal if. The scope rules are useful and your logic is explicit:
if (CThing* pThing = GetThing())
{
if(pThing->IsReallySomeThing())
{
}
}
About the advantages:
It's always recommended to define variables when you first need them, not a line before. This is for improved readability of your code, since one can tell what CThing is without scrolling and searching where it was defined.
Also reducing scope to a loop/if block, causes the variable to be unreferenced after the execution of the code block, which makes it a candidate for Garbage Collection (if the language supports this feature).
if (CThing* pThing = GetThing())
It is bad style, because inside the if you are not providing a boolean expression. You are providing a CThing*.
CThing* pThing = GetThing();
if (pThing != NULL)
This is good style.
You can have initialization statements inside if and switch since C++17.
Your code would now be:
if (CThing* pThing = GetThing(); pThing->IsReallySomeThing())
{
// use pThing here
}
// pThing is out of scope here
One reason I don't normally do that is because of the common bug from a missed '=' in a conditional test. I use lint with the error/warnings set to catch those. It will then yell about all assignments inside conditionals.
Just an FYI some of the older Microsoft C++ compliers(Visual Studios 6, and .NET 2003 I think) don't quite follow the scoping rule in some instances.
for(int i = 0; i > 20; i++) {
// some code
}
cout << i << endl;
I should be out of scope, but that was/is valid code. I believe it was played off as a feature, but in my opinion it's just non compliance. Not adhering to the standards is bad. Just as a web developer about IE and Firefox.
Can someone with VS check and see if that's still valid?
This shoulddoesn't work in C++ sinceeven though it supports short circuiting evaluation. MaybeDon't try the following:
if ((CThing* pThing = GetThing()) && (pThing->IsReallySomeThing()))
{
}
err.. see Wesley Tarle's answer
So many things. First of all, bare pointers. Please avoid them by all means. Use references, optional, unique_ptr, shared_ptr. As the last resort, write your own class that deals with pointer ownership and nothing else.
Use uniform initialization if you can require C++11 (C++14 preferred to avoid C++11 defects): - it avoids = vs == confusion and it's stricter at checking the arguments if there are any.
if (CThing thing {})
{
}
Make sure to implement operator bool to get predictable conversion from CThing to bool. However, keep in mind that other people reading the code would not see operator bool right away. Explicit method calls are generally more readable and reassuring. If you can require C++17, use initializer syntax.
if (CThing thing {}; thing.is_good())
{
}
If C++17 is not an option, use a declaration above if as others have suggested.
{
CThing thing {};
if (thing.is_good())
{
}
}
You can also enclose the assignment in an extra set of ( ) to prevent the warning message.
I see that as kind of dangerous. The code below is much safer and the enclosing braces will still limit the scope of pThing in the way you want.
I'm assuming GetThing() sometimes returns NULL which is why I put that funny clause in the if() statement. It prevents IsReallySomething() being called on a NULL pointer.
{
CThing *pThing = GetThing();
if(pThing ? pThing->IsReallySomeThing() : false)
{
// Do whatever
}
}
also notice that if you're writing C++ code you want to make the compiler warning about "=" in a conditional statement (that isn't part of a declaration) an error.
It's acceptable and good coding practice. However, people who don't come from a low-level coding background would probably disagree.