Scope of an object created in an if-condition in C++ - 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.

Related

c++ macro using variable from an other macro

I need to make foo compile by implementing the macros for it:
int foo(std::string tag)
{
SWITCH_STRING(tag)
{
STRING_CASE(a)
{
return 1;
}
STRING_CASE(b)
{
return 2;
}
STRING_CASE(abc)
{
return 3;
}
STRING_ELSE
{
return -1;
}
}
}
I would like to use the tag parameter in SWITCH_STRING(tag) and compare it to the letter parameter in STRING_CASE(letter), to implement this switch like syntax, I'm stuck for a while and new to macros in c++ could you offer a solution to how to implement the macros please?
#include <iostream>
#include <string>
// Write macros here |
#define SWITCH_STRING(tag)
#define STRING_CASE(letter) letter == tag ? true : false
#define STRING_ELSE
I have to admit: Macros can be fun. We all should know that they should be avoided. Though, as this is an exercise about macros, we can put the discussion whether to use a macro or not aside.
The point of the exercise is that you cannot (directly) switch on a std::string. This answer shows how this limitation can be worked-around. Being required to write exremely verbose repetetive code, the macro is kind of justified. For the sake of completeness I want to add how it can be solved using your original approach, using a series of if instead of the switch.
First, I write the function that does what is asked for without any macro involved:
int foo(std::string tag)
{
std::string& temp = tag;
{
if (temp == "a")
{
return 1;
}
if (temp == "b")
{
return 2;
}
if (temp == "abc")
{
return 3;
}
{
return -1;
}
}
}
It isnt that nice that it uses ifs not else if that should be prefered for mutually exclusive cases. However, as each case returns, the result wont differ (if that isnt the case, you'll have to add some goto vodoo as outlined in the other answer). Having that, it is straightforward to see what macros are needed:
#define SWITCH_STRING(tag) std::string& temp = tag;
#define STRING_CASE(X) if (temp == #X)
#define STRING_ELSE
This kind of answers your question about how to use the parameter of one macro in a second one: You don't. Instead you can use a reference whose name does not depend on the actual name of tag anymore.
Full example
What you might do to switch on string:
constexpr std::size_t myhash(std::string_view) { /* .. */ }
int foo(const std::string& tag)
{
switch (tag)
{
case myhash("a"): { return 1; }
case myhash("b"): { return 2; }
case myhash("abc"): { return 3; }
default: { return -1; }
}
}
That doesn't need MACRO.
If you have collisions with your cases, compilation would fail (same value in switch)
and you will need another hash function.
If you want to prevent collisions (from input string), you might do:
constexpr std::size_t myhash(std::string_view) { /* .. */ }
int foo(const std::string& tag)
{
switch (tag)
{
case myhash("a"): { if (tag != "a") { goto def; } return 1; }
case myhash("b"): { if (tag != "b") { goto def; } return 2; }
case myhash("abc"): { if (tag != "abc") { goto def; } return 3; }
default: { def: return -1; }
}
}
which might indeed be less verbose with MACRO
#define CaseHash(str, c) case myhash(c): if (str != c) { goto def; }
#define DefaultHash default: def
to result to
constexpr std::size_t myhash(std::string_view) { /* .. */ }
int foo(const std::string& tag)
{
switch (tag)
{
CaseHash(tag, "a") { return 1; }
CaseHash(tag, "b") { return 2; }
CaseHash(tag, "abc") { return 3; }
DefaultHash: { return -1; }
}
}

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.

Getting a strange int value

When I cout my lettercase variable to the console, I get -858993460. Everything else seems to be working okay. What am I missing here?
So here's a sample of my code:
Here's main:
int main()
{
int lettercase = 0;
Switch switcher(lettercase);
lettercase = switcher.getLettercase();
cout << "Lettercase: " << lettercase << endl;
return 0;
}
I also have a separate class called Switch.
Here's a sample of its header file:
class Switch {
public:
// DEFAULT CONSTRUCTOR
Switch();
// OVERLOAD CONSTRUCTOR
Switch(int);
// DESTRUCTOR
~Switch();
// Lettercase accessor
int getLettercase();
private:
int lettercase;
};
And here's a sample of my definition:
// DEFAULT
Switch::Switch() {
int lettercase = 0;
}
// OVERLOAD
Switch::Switch(int lettercase) {
// CHANGE LETTER CASE
if (lettercase == 1) {
lettercase = 0;
} else {
lettercase = 1;
}
}
// DESTRUCTOR
Switch::~Switch() {
}
// ACCESSOR
int Switch::getLettercase() {
return lettercase;
}
// OVERLOAD
Switch::Switch(int lettercase) {
// CHANGE LETTER CASE
if (lettercase == 1) {
lettercase = 0;
} else {
lettercase = 1;
}
}
You have scope issues here. You're trying to change the class variable lettercase, but because the argument for the constructor is also called lettercase, you have to use this->lettercase if you want to access the class variable. I suggest changing the name of your parameter here.
Something like this:
// OVERLOAD
Switch::Switch(int initCase) {
// CHANGE LETTER CASE
if (initCase == 1) {
lettercase = 0;
} else {
lettercase = 1;
}
}
The reason you were getting that odd int is because your scope issues prevented you from ever initializing the class variable lettercase, but your getter was still accessing this variable and returning the uninitialized value.
EDIT: Your default constructor also has a problem, here:
Switch::Switch() {
int lettercase = 0;
}
This isn't doing what you think it's doing (or what you want it to do). Rather than initializing the class variable, lettercase, this is creating a new variable, lettercase, (scope) and initializes it to 0. Instead, your default constructor should look like this:
Switch::Switch() {
lettercase = 0;
}

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

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.

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.