Should I use returning functions when the return value isn't needed? - c++

I have a function that looks like this:
int Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return 0;
}
else {
// do other stuff
}
}
}
I'm wondering if it is common or proper to have a returning function, rather than a void function, for the sole purpose of leaving the function (the value being returned wouldn't do anything in the program except for ending the function). Is this good practice, or is there a better way to end a function?

There is no problem with void functions. If it does not return anything useful, it should be void.

Just make your function void, and simply return?
// vv void return type
void Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return; // <<<< No return value
}
else {
// do other stuff
}
}
}

You can easily just use return; with no parameter to exit a void function. Your above code would become:
void Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return;
}
else {
// do other stuff
}
}
}

If there is no useful value for the function to return, it is better not to return a value - because the calling code should check the returned value.
Your code can be doubly simplified:
void Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return;
}
// do other stuff
}
}
The else is unnecessary; the only way to execute the 'do other stuff' is if something is false.

Related

How do I make a function execute a task when it ends?

I have a function that I wish to be called infinitely as long as conditions are met. However, I cannot simply call the function inside of itself, as that will cause a stack overflow. How do I end the function and start another one at the same time?
Example:
int myFunc() {
//do stuff
char again;
std::cout << "Do it again?\n";
std::cin >> again;
//I want to do this, but in a way that ends the function first.
if (again = y) {
myFunc();
}
}
Well you haven't given any code example, so I'm probably out on a limb here, but I'm guessing you have something like this:
void my_func()
{
// do stuff
// ...
while (cond)
{
my_func();
}
}
There's two ways you can fix this:
1)
// this is wherever you call my_func
void some_other_func()
{
while (cond)
{
my_func();
}
}
void my_func()
{
// do stuff
// ...
}
(better, you only have to edit my_func to call a private implementation of the actual method part)
void my_func_impl()
{
// do stuff
// ...
}
void my_func()
{
while (cond)
{
my_func_impl();
}
}
EDIT
Now that you posted an example, this is how I'd refactor your code to accomplish this:
void doIt() {
// do stuff
}
void myFunc() {
//do stuff
char again;
while (1) {
std::cout << "Do it again?\n";
std::cin >> again;
if (again = y) {
doIt();
}
// if the answer wasn't yes, the if case won't enter
// break the loop in that case
break;
}
}
int myFunc() {
char again;
do {
std::cout << "Do it again?\n";
std::cin >> again;
} while (again == 'y');
}

Jumping from a scope

Is it possible to jump from an unnamed scope?
void MyFunc() {
{
... // Code
if (!head_size) {
goto _common_error; // <- break and continue don't work here
}
... // Code
if (!tail_size) {
goto _common_error; // second time
}
... // Code
}
_common_error:
{
... // Code
}
}
My question is not whether this can be redesigned, but whether there is a trick in c++ that I don't know.
Is there a mechanism in c++ other than goto to jump out of an unnamed scope? break and continue do not work in scopes.
Update1: changed word namespace to scope
Yes, you need to use goto to jump out of a scope.
break can only be used to jump out of a loop or switch.
But you can use a (questionable) trick by using a dummy loop:
void MyFunc() {
do {
... // Code
if (!head_size) {
break;
}
... // Code
if (!tail_size) {
break;
}
... // Code
} while (false);
{
... // Error handling code
}
}
Using macro magic
#define BREAKABLE_SCOPE() for (char __scope = 0; __scope == 0; __scope++)
You can then do
int main()
{
// Will only print "Hello!"
BREAKABLE_SCOPE()
{
printf("Hello!");
break;
printf("Hello again!");
}
return 0;
}
Please note that macros will reduce the readability of your code.

How to check if bool method returns value in an if statement C++

I'm having a go at creating classes and have created this method inside
Input.cpp:
bool Input::CheckKeyPress(char key)
{
SDL_Event ev;
while (SDL_PollEvent(&ev))
{
keyState = SDL_GetKeyboardState(NULL);
if (ev.type == SDL_KEYDOWN)
{
switch (key)
{
case 'w' :
if (keyState[SDL_SCANCODE_W])
{
return 1;
}
else
{
return 0;
}
case 'a' :
if (keyState[SDL_SCANCODE_A])
{
return 1;
}
else
{
return 0;
}
case 's' :
if (keyState[SDL_SCANCODE_S])
{
return 1;
}
else
{
return 0;
}
case 'd' :
if (keyState[SDL_SCANCODE_D])
{
return 1;
}
else
{
return 0;
}
}
}
}
}
I try to use it in an if-statement in my main class like so:
if (bool Input::CheckKeyPress(w))
{
//do stuff
}
However as expected I get an error saying: "A function type is not allowed here" So what do I do?
Just write:
if (CheckKeyPress(w))
{
//do stuff
}
You have already told the compiler that the CheckKeyPress() method returns a bool. Here, you are just calling the function, so you don't need to mention the return type again. When the control will call the function CheckKeyPress(), it will return a bool value that would be checked for its truth within the if statement.
Note: There are two possibilities:
Instance is a different class:
If Instance is altogether a different class and CheckKeyPress() is
one of the methods that it contains, then you first need to create an object of the Instance class like below:
Instance it = new Instance(); //or just Instance it;
and then access the function via:
it.CheckKeyPress();
If the method is static:
In this case you need to call the method as:
Input::CheckKeyPress(w)
without just the return type (bool).
Hope this is helpful. Thank you for your inputs, #user4581301.

Scope of an object created in an if-condition in C++

In the following example
void fun() {
if(int i=SOME_VALUE) {
// ...
} else {
// ...
}
}
What is the scope of i? Can we use it inside the if-block? Can we use it inside the else-block?
Edit:
As a follow-up, in this modified example
void fun() {
if(int i=SOME_VALUE) {
// ...
} else if(int j=SOME_OTHER_VALUE){
// ...
} else {
// ...
}
}
Can we access both i and j in the else clause?
Yes, and yes.
A typical use for this is dynamic casting:
if (auto p = dynamic_cast<Derived*>(base_pointer))
{
// p is a Derived*
}
else
{
// not the right dynamic type
}
Another construction I've been finding useful:
if (auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(std::fopen("file.txt", "rb"), std::fclose))
{
// file exists, use fp.get()
}
else
{
// file does not exist
}
And one more:
if (pid_t pid = fork())
{
waitpid(pid, nullptr, 0);
}
else
{
execl("/bin/rm", "/bin/rm", "-rf", "/", static_cast<char*>(nullptr));
}
Yes, you can use the variable declared in the if condition in the else substatement like your example.
However, if you declare i inside the if substatement like this:
if (some_condition) {
int i = 42;
// ...
} else {
std::cout << i; //error
// ...
}
in the else part, the variable i is no longer in scope.
Yes, because the variable is "created" in the outermost scope and only then, evaluated in the if condition. Your code could be rewritten like:
int i = SOME_VALUE;
if(i) {
// ...
} else {
// ...
}
and not like:
if(SOME_VALUE) {
int i = SOME_VALUE;
// ...
} else {
// ...
}
as you may have though.
The second question can be answered the same way.

How to implement final conditions properly?

This is what I'm trying to do (this is a simplification of a real project):
int param;
int result;
void isolated(int p) {
param = p;
try {
// make calculations with "param" and place the
// result into "result"
process();
} catch (...) {
throw "problems..";
}
}
I can't change the way process() works, since this function is not created in the project and is a third-party function. It works with global variables param and result and we can't change this.
The problem appears when isolated() is called back from process() with another parameter. I want to catch this situation, but don't know how to do it, since finally is absent in C++. I feel that I should use RAII technique, but can't figure out how to do it in this case properly.
This is how I can make it with code duplication:
int param;
int result;
void isolated(int p) {
static bool running;
if (running) {
throw "you can't call isolated() from itself!";
}
running = true;
param = p;
try {
// make calculations with "param" and place the
// result into "result"
process();
running = false;
} catch (...) {
running = false; // duplication!
throw "problems..";
}
}
"finally" like situations are handled in C++ using guard objects, that do their finally thing in the destructor. This is IMHO much more powerful approach, because you have to analyze the situation to finalize in order to create a reuseable object. In this case, we need to make process rentrant, because parameters and returns are passed in globals. The solution is to save their values on entry and restore them on exit:
template<class T>
class restorer
{
T &var; // this is the variable we want to save/restore
T old_value; // the old value
restorer(const restorer&);
void operator=(const restorer&);
public:
restorer(T &v) : var(v), old_value(v) {}
~restorer() { var=old_value; }
};
int param;
int result;
int isolated(int p) {
restorer<int> rest_param(param);
restorer<int> rest_result(result);
param = p;
try {
// make calculations with "param" and place the
// result into "result"
process();
return result;
} catch (...) {
return 0;
}
}
Maybe I didn't get it right, but why don't you use a flag? You want to know when the isolated() is called from the process(), right?
int isolated(int p) {
static int execDeep = 0;
execDeep++;
// your code here
execDeep--;
}
Now you can check 'execDeep' value, > 1 means it is called from the process() while still being executed.
I still don't quite sure how finally is related here, but you could try Boost.ScopeExit if you want to avoid creating a scope guard structure yourself.
Example:
#include <boost/scope_exit.hpp>
#include <cstdio>
int isolated(int p) {
static bool running = false;
if (running) {
printf("Throwing %d\n", p);
throw p;
}
printf("Starting %d\n", p);
running = true;
BOOST_SCOPE_EXIT( (p)(&running) ) { // <--
printf("Stopping %d\n", p); // <--
running = false; // <--
} BOOST_SCOPE_EXIT_END // <--
// ...
if (p)
isolated(p*10);
// ...
printf("Returing %d\n", p);
return 4;
}
int main() {
printf(">> first\n");
isolated(0);
printf(">> second\n");
try {
isolated(1);
printf(">> third (should not be printed.)\n");
} catch(int p) {
printf("Caught %d\n", p);
}
isolated(0);
printf(">> fourth\n");
return 0;
}
Result:
>> first
Starting 0
Returing 0
Stopping 0
>> second
Starting 1
Throwing 10
Stopping 1
Caught 10
Starting 0
Returing 0
Stopping 0
>> fourth
Could this work?
int save = -10000000000;
int param;
int result;
int isolated(int p) {
if (save != -10000000000)
{
// run the other condition
}
else
{
save = p;
param = p;
try {
// make calculations with "param" and place the
// result into "result"
process();
return result;
} catch (...) {
return 0;
}
}
}
If I understand correctly, you want to automatically set the running flag to false at the end of function. If that is the requirement then you can use the ScopeGuard approarch mentioned in the link.