This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Declaring and initializing a variable in a Conditional or Control statement in C++
Instead of this...
int value = get_value();
if ( value > 100 )
{
// Do something with value.
}
... is it possible to reduce the scope of value to only where it is needed:
if ( int value = get_value() > 100 )
{
// Obviously this doesn't work. get_value() > 100 returns true,
// which is implicitly converted to 1 and assigned to value.
}
If you want specific scope for value, you can introduce a scope block.
#include <iostream>
int get_value() {
return 101;
}
int main() {
{
int value = get_value();
if(value > 100)
std::cout << "Hey!";
} //value out of scope
}
Can you declare a variable and compare it within the if() statement? No.
Can you declare a variable and compare it in such a way that the scope is tightly-bound to the if() block? Yes!
You can either declare a variable:
if (int x = 5) {
// lol!
}
or you can do things with one:
int x = foo();
if (x == 5) {
// wahey!
}
You can't do both!
You can cheat a little where the only thing you need to do is compare with true, because the declaration itself evaluates to the value of the new object.
So, if you have:
int foo()
{
return 0;
}
Then this:
if (int x = foo()) {
// never reached
}
is equivalent to:
{
int x = foo();
if (x) {
// never reached
}
}
This final syntax, using a standalone scope block, is also your golden bullet for more complex expressions:
{
int x = foo();
if (x > bar()) {
// wahooza!
}
}
Put it in a function:
void goodName(int value) {
if(value > 100) {
// Do something with value.
}
}
//...
goodName(get_value());
How about using for instead?
for (int value = get_value(); value > 100; value = 0) {
//...
}
If you want to go C++11 on it, you can use a lambda:
[](int value = get_value()) {
if (value > 100) {
//...
std::cout << "value:" << value;
}
}();
Or you could just add an extra set of braces for a nested scope, although it's not exactly pretty:
{
int value = get_value();
if ( value > 100 )
{
// Do something with value.
}
}
//now value is out of scope
You can write a small function which can do the comparison for you and return the value the if comparison returns true, else return 0 to avoid executing the if block:
int greater_than(int right, int left)
{
return left > right ? left : 0;
}
Then use it as:
if ( int value = greater_than(100, get_value()))
{
//wow!
}
Or you can use for as other answer said. Or manually put braces to reduce the scope of the variable.
At any rate, I would not write such code in production code.
Don't write code for machines. Write code for humans. Machines will understand anything as long as you follow their grammar; humans understand what is readable to them. So readability should be your priority over unnecessary scoping.
In this particular case, you can bodge it:
if (int value = (get_value() > 100 ? get_value() : 0)) {
...
}
I don't really recommend it, though. It doesn't work for all possible tests that you might want to perform, and it calls get_value() twice.
Related
So I'm trying to write a recursive function that keeps track of how often it got called. Because of its recursive nature I won't be able to define an iterator inside of it (or maybe it's possible via a pointer?), since it would be redefined whenever the function gets called. So i figured I could use a param of the function itself:
int countRecursive(int cancelCondition, int counter = 0)
{
if(cancelCondition > 0)
{
return countRecursive(--cancelCondition, ++counter);
}
else
{
return counter;
}
}
Now the problem I'm facing is, that the counter would be writeable by the caller of the function, and I want to avoid that.
Then again, it wouldn't help to declare the counter as a const, right?
Is there a way to restrict the variable's manipulation to the function itself?
Or maybe my approach is deeply flawed in the first place?
The only way I can think of solving this, is to use a kind of "wrapper-function" that keeps track of how often the recursive function got called.
An example of what I want to avoid:
//inside main()
int foo {5};
int countToZero = countRecursive(foo, 10);
//countToZero would be 15 instead of 5
The user using my function should not be able to initially set the counter (in this case to 10).
You can take you function as is, and wrap it. One way I have in mind, which completely encapsulates the wrapping is by making your function a static member of a local class. To demonstrate:
int countRecursive(int cancelCondition)
{
struct hidden {
static int countRecursive(int cancelCondition, int counter = 0) {
if(cancelCondition > 0)
{
return countRecursive(--cancelCondition, ++counter);
}
else
{
return counter;
}
}
};
return hidden::countRecursive(cancelCondition);
}
Local classes are a nifty but rarely seen feature of C++. They possess some limitations, but fortunately can have static member functions. No code from outside can ever pass hidden::countRecursive an invalid counter. It's entirely under the control of the countRecursive.
If you can use something else than a free function, I would suggest to use some kind of functor to hold the count, but in case you cant, you may try to use something like this using friendship to do the trick:
#include <memory>
class Counter;
int countRecursive(int cancelCondition, std::unique_ptr<Counter> counter = nullptr);
class Counter {
int count = 0;
private:
friend int countRecursive(int, std::unique_ptr<Counter>);
Counter() = default; // the constructor can only be call within the function
// thus nobody can provide one
};
int countRecursive(int cancelCondition, std::unique_ptr<Counter> c)
{
if (c == nullptr)
c = std::unique_ptr<Counter>(new Counter());
if(cancelCondition > 0)
{
c->count++;
return countRecursive(--cancelCondition, std::move(c));
}
else
{
return c->count;
}
}
int main() {
return countRecursive(12);
}
You can encapsulate the counter:
struct counterRecParam {
counterRecParam(int c) : cancelCondition(c),counter(0) {}
private:
int cancelCondition;
int counter;
friend int countRecursive(counterRecParam);
};
Now the caller cannot modify the counter, and you only need to modify the function slightly:
int countRecursive(counterRecParam crp)
{
if(crp.cancelCondition > 0)
{
--crp.cancelCondition;
++crp.counter;
return countRecursive(crp);
}
else
{
return crp.counter;
}
}
And the implicit conversion lets you call it with an int
counterRecursive(5);
One way to do this is to use a functor. Here's a simple example:
#include <iostream>
class counter
{
public:
unsigned operator()(unsigned m, unsigned n)
{
// increment the count on every iteration
++count;
// rest of the function
if (m == 0)
{
return n + 1;
}
if (n == 0)
{
return operator()(m - 1, 1);
}
return operator()(m - 1, operator()(m, n - 1));
}
std::size_t get_count() const
{
return count;
}
private:
// call count
std::size_t count = 0;
};
int main()
{
auto f = counter();
auto res = f(4, 0);
std::cout << "Result: " << res << "\nNumber of calls: " << f.get_count() << std::endl;
return 0;
}
Output:
Result: 13
Number of calls: 107
Since the count is stored in the object itself, the user cannot overwrite it.
Have you tried using "static" counter variable. Static variables gets initialized just once, and are best candidates to be used as counter variables.
I continue to run into an issue in building a recursive function where its returned value is different from the value I expect it to return. I'm fairly certain it relates to the recursive nature of the function, but I don't understand what is happening.
int foo(std::string, int = 0);
int main() {
std::string testString = "testing";
std::cout << foo(testString);
}
int foo(std::string givenString, int numberToReturn) {
if (givenString.length() == 0) {
std::cout << "Number to return before actually returning: " << numberToReturn << "\n";
return numberToReturn;
}
if (true) {
numberToReturn++;
}
std::string newString = givenString.erase(0, 1);
foo(newString, numberToReturn);
}
In this minified example, I have function foo with a string and an int with a default value of 0. Given the string "testing" and no integer, I would expect the recursive function to increment numberToReturn for each call and pass the new value to the next call. This must be partly right because if I cout numberToReturn when I reach the base case, I get the expected value (which in this case it would be 7). But as soon as I return that value, it changes to a much larger number (6422160 in my case).
So with that said, why does the number change on return and how do I prevent that change from happening or otherwise return the correct/expected value?
Edit: For anyone with a similar problem in the future, my issue was that each recusrion call must return something, not just the last one. In my case, returning the last line of function foo solves the issue. Not returning something for every function call leads to undefined behavior.
Your function must always end with return, if it doesn't your function will return some random uninitialised value. For example
int foo( int x )
{
if ( x == 0 )
{
return x;
}
foo(x-1);
}
is roughly equivalent to:
int foo( int x )
{
if ( x == 0 )
{
return x;
}
foo(x-1);
return someRandomValue();
}
what you actually want is:
int foo( int x )
{
if ( x == 0 )
{
return x;
}
return foo(x-1);
}
Lambdas are an awesome way to create reusable code inside a function/method without polluting the parent class. They're a very functional replacement for C-style macros most of the time.
However, there's one bit of syntactic sugar from macros that I can't seem to replicate with a lambda, and that's the ability to exit from the containing function. For example, if I need to return while checking the range of a series of ints, I can do that easily with a macro:
const int xmin(1), xmax(5);
#define CHECK_RANGE(x) { if((x) < xmin || (x) > xmax) return false; }
bool myFunc(int myint) {
CHECK_RANGE(myint);
int anotherint = myint + 2;
CHECK_RANGE(anotherint);
return true;
}
Obviously this is an oversimplified example, but the basic premise is that I'm performing the same check over and over on different variables, and I think it's more readable to encapsulate the check and related exits. Still, I know that macros aren't very safe, especially when they get really complex. However, as far as I can tell, trying to do the equivalent lambda requires awkward additional checks like so:
const int xmin(1), xmax(5);
auto check_range = [&](int x) -> bool { return !(x < xmin || x > xmax); };
bool myFunc(int myint) {
if(!check_range(myint)) return false;
int anotherint = myint + 2;
if(!check_range(anotherint)) return false;
return true;
}
Is there a way to do this with a lambda? Or am I missing some alternative solution?
Edit: I recognize that returning from inside a macro is generally a bad idea unless significant precautions are taken. I'm just wondering if it's possible.
You are correct--there's no way to return from the caller from inside a lambda. Since a lambda can be captured and stored to be called later, from inside an arbitrary caller, doing so would result in unpredictable behavior.
class Foo
{
Foo(std::function<void(int)> const& callMeLater) : func(callMeLater) {}
void CallIt(int* arr, int count)
{
for (index = count; index--;)
func(count);
// do other stuff here.
}
std::function<void(int)> func;
};
int main()
{
auto find3 = [](int arr)
{
if (arr == 3)
return_from_caller; // making up syntax here.
};
Foo foo(find3);
};
Is there a way to do this with a lambda?
Not exactly like the macro but your lambda, instead of returning a bool, can throw a special exception (of type bool, by example)
auto check_range
= [](int x) { if ( (x < xmin) || (x > xmax) ) throw bool{false}; };
and the function myFunc() can intercept this special type
bool myFunc (int myint)
{
try
{
check_range(myint);
int anotherint = myint + 2;
check_range(anotherint);
return true;
}
catch ( bool e )
{ return e; }
}
For a single check_range() call, this is (I suppose) a bad idea; if you have a lot of calls, I suppose can be interesting.
The following is a full working example
#include <iostream>
constexpr int xmin{1}, xmax{5};
auto check_range
= [](int x) { if ( (x < xmin) || (x > xmax) ) throw bool{false}; };
bool myFunc (int myint)
{
try
{
check_range(myint);
int anotherint = myint + 2;
check_range(anotherint);
return true;
}
catch ( bool e )
{ return e; }
}
int main ()
{
std::cout << myFunc(0) << std::endl; // print 0
std::cout << myFunc(3) << std::endl; // print 1
std::cout << myFunc(7) << std::endl; // print 0
}
No better way to do this than just to use the return value of the lambda and then return from the calling function. Macros are ew for this.
As it stands in C++, that is the idiomatic way to exit from a function that uses another condition to determine whether or not to exit.
Not C++11, but people have hacked C++2a coroutines to basically do this.
It would look a bit like:
co_await check_range(foo);
where the co_await keyword indicates that in some cases, this coroutine could return early with an incomplete result. In your cases, this incomplete result would be non-resumabable error.
The playing around I saw was with optionals, and required using a shared ptr, but things may improve before it is standardized.
There is a initial game difficulty which is
game_difficulty=5 //Initial
Every 3 times if you get it right, your difficulty goes up to infinity but every 3 times you get it wrong, your difficulty goes down but not below 5. So, in this code for ex:
if(user_words==words) win_count+=1;
else() incorrect_count+=1;
if(win_count%3==0) /*increase diff*/;
if(incorrect_count%3==0) /*decrease difficulty*/;
How should I go about doing this?
Simple answer:
if(incorrect_count%3==0) difficulty = max(difficulty-1, 5);
But personally I would wrap it up in a small class then you can contain all the logic and expand it as you go along, something such as:
class Difficulty
{
public:
Difficulty() {};
void AddWin()
{
m_IncorrectCount = 0; // reset because we got one right?
if (++m_WinCount % 3)
{
m_WinCount = 0;
++m_CurrentDifficulty;
}
}
void AddIncorrect()
{
m_WinCount = 0; // reset because we got one wrong?
if (++m_IncorrectCount >= 3 && m_CurrentDifficulty > 5)
{
m_IncorrectCount = 0;
--m_CurrentDifficulty;
}
}
int GetDifficulty()
{
return m_CurrentDifficulty;
}
private:
int m_CurrentDifficulty = 5;
int m_WinCount = 0;
int m_IncorrectCount = 0;
};
You could just add this as a condition:
if (user words==words) {
win_count += 1;
if (win_count %3 == 0) {
++diff;
}
} else {
incorrect_count += 1;
if (incorrect_count % 3 == 0 && diff > 5) {
--diff
}
}
For example:
if(win_count%3==0) difficulty++;
if(incorrect_count%3==0 && difficulty > 5) difficulty--;
This can be turned into a motivating example for custom data types.
Create a class which wraps the difficulty int as a private member variable, and in the public member functions make sure that the so-called contract is met. You will end up with a value which is always guaranteed to meet your specifications. Here is an example:
class Difficulty
{
public:
// initial values for a new Difficulty object:
Difficulty() :
right_answer_count(0),
wrong_answer_count(0),
value(5)
{}
// called when a right answer should be taken into account:
void GotItRight()
{
++right_answer_count;
if (right_answer_count == 3)
{
right_answer_count = 0;
++value;
}
}
// called when a wrong answer should be taken into account:
void GotItWrong()
{
++wrong_answer_count;
if (wrong_answer_count == 3)
{
wrong_answer_count = 0;
--value;
if (value < 5)
{
value = 5;
}
}
}
// returns the value itself
int Value() const
{
return value;
}
private:
int right_answer_count;
int wrong_answer_count;
int value;
};
And here is how you would use the class:
Difficulty game_difficulty;
// six right answers:
for (int count = 0; count < 6; ++count)
{
game_difficulty.GotItRight();
}
// check wrapped value:
std::cout << game_difficulty.Value() << "\n";
// three wrong answers:
for (int count = 0; count < 3; ++count)
{
game_difficulty.GotItWrong();
}
// check wrapped value:
std::cout << game_difficulty.Value() << "\n";
// one hundred wrong answers:
for (int count = 0; count < 100; ++count)
{
game_difficulty.GotItWrong();
}
// check wrapped value:
std::cout << game_difficulty.Value() << "\n";
Output:
7
6
5
Once you have a firm grasp on how such types are created and used, you can start to look into operator overloading so that the type can be used more like a real int, i.e. with +, - and so on.
How should I go about doing this?
You have marked this question as C++. IMHO the c++ way is to create a class encapsulating all your issues.
Perhaps something like:
class GameDifficulty
{
public:
GameDifficulty () :
game_difficulty (5), win_count(0), incorrect_count(0)
{}
~GameDifficulty () {}
void update(const T& words)
{
if(user words==words) win_count+=1;
else incorrect_count+=1;
// modify game_difficulty as you desire
if(win_count%3 == 0)
game_difficulty += 1 ; // increase diff no upper limit
if((incorrect_count%3 == 0) && (game_difficulty > 5))
game_difficulty -= 1; //decrease diff;
}
inline int gameDifficulty() { return (game_difficulty); }
// and any other access per needs of your game
private:
int game_difficulty;
int win_count;
int incorrect_count;
}
// note - not compiled or tested
usage would be:
// instantiate
GameDiffculty gameDifficulty;
// ...
// use update()
gameDifficulty.update(word);
// ...
// use access
gameDifficulty.gameDifficulty();
Advantage: encapsulation
This code is in one place, not polluting elsewhere in your code.
You can change these policies in this one place, with no impact to the rest of your code.
Afaik, every pair of { } in the code creates a new scope. Even if it's used just for the sake of it without any if, for, function or other statement that demands it:
void myFun(void)
{
int a;
{
int local;
}
}
I started wondering - when the if statement is written without using the braces (with 1-line body) does it still create a new scope?
voidmyFun(int a)
{
int b;
if (a == 1)
int tmp; // is this one local to if?
else
int tmp2; // or this one?
b = 2; // could I use tmp here?
}
N4140 [stmt.select]/1 reads:
The substatement in a selection-statement (each substatement, in the else form of the if statement) implicitly defines a block scope
So, the code
if (a == 1)
int tmp; // is this one local to if?
else
int tmp2; // or this one?
is equivalent to
if (a == 1)
{
int tmp; // yes, this one is local to if
}
else
{
int tmp2; // and this one as well
}
In short - yes. It's a single line scope.
In other words, writing:
if (someCondition)
int i = 7;
Is identical, scope-wise, to writing:
if (someCondition)
{
int i = 7;
}
Yes! tmp are local to if and tmp2 is local to else. If you try using tmp or temp2 outside, you should get variable not defined error. It is because,
if(<condition>) <my-statment>
if(<condition>)
{
<my-statment>
}
For compiler, both of them are equal.
Yes, even if the if and for do not have {}, the variables declared in it are local to it.
So, if you try something like
if ( something )
int a = 3;
std::cout << a; // there is no other identifier called a in your program
it will not compile, because it is the same as
if ( something )
{
int a = 3;
}
std::cout << a;
and you will get a variable not declared in this scope error.
So,
voidmyFun(int a)
{
int b;
if (a == 1)
int tmp; // is this one local to if? Ans:- Yes
else
int tmp2; // or this one? Ans:- It is local to else block
b = 2; // could I use tmp here? Ans:- No
}
So, the variable inside the else ( tmp2 ) is local to else and not to if.