Defining a variable in an if-statement?

I was just shocked that this is allowed:

if( int* x = new int( 20 ) ) { std::cout << *x << "!\n"; // delete x; } else { std::cout << *x << "!!!\n"; // delete x; } // std:cout << *x; // error - x is not defined in this scope 

So, is this allowed by the standard or just a compiler extension?




<sub> PS Since there were a few comments about this, please ignore that this example is "bad" or dangerous. I know that. This is the first thing that occurred to me as an example.

+69
c ++ variables standards if-statement
Sep 29 '12 at 18:22
source share
5 answers

This is allowed by the specification since C ++ 98.

From section 6.4, “Expressions of Choice”:

The name entered by the declaration in the condition (either entered by the qualifier-type-seq, or the condition declarator) is in scope from the declaration point to the end of the substitutions controlled by the condition.

The following example is from the same section:

 if (int x = f()) { int x; // ill-formed, redeclaration of x } else { int x; // ill-formed, redeclaration of x } 
+73
Sep 29 '12 at 18:28
source share

This is the standard, even in the old version of C ++ 98:

enter image description here

+18
Sep 29 '12 at 18:28
source share

Not quite an answer (but comments are not very suitable for code samples), which is another reason why this is incredibly convenient:

 if (int* x = f()) { std::cout << *x << "\n"; } 

Whenever the API returns an “option” type (which also has an available logical conversion), this type of construct can be used so that the variable is only available in a context where it is reasonable to use its value. This is a really powerful idiom.

+15
Sep 29 '12 at 19:39
source share

The definition of a variable in the conditional part of the while , if and switch is standard. The relevant clause is clause 6.4 [stmt.select], which defines the syntax of the condition.

By the way, your use is pointless: if new fails, it throws an exception std::bad_alloc .

+7
Sep 29 '12 at 18:27
source share

Here is an example that demonstrates the non-standard use of a variable declared in an if condition.

The type of the variable is int & which can be converted to a boolean value and used in the then and else branches.

 #include <string> #include <map> #include <vector> using namespace std; vector<string> names {"john", "john", "jack", "john", "jack"}; names.push_back("bill"); // without this push_back, my g++ generated exe fails :-( map<string, int> ages; int babies = 0; for (const auto & name : names) { if (int & age = ages[name]) { cout << name << " is already " << age++ << " year-old" << endl; } else { cout << name << " was just born as baby #" << ++babies << endl; ++age; } } 

exit

 john was just born as baby #1 john is already 1 year-old jack was just born as baby #2 john is already 2 year-old jack is already 1 year-old bill was just born as baby #3 

Unfortunately, a variable in a condition can only be declared with the syntax of declaration =.

This eliminates other possible useful cases of types with an explicit constructor.

For example, the following example using std::ifstream will not compile ...

 if (std::ifstream is ("c:/tmp/input1.txt")) { // won't compile! std::cout << "true: " << is.rdbuf(); } else { is.open("c:/tmp/input2.txt"); std::cout << "false: " << is.rdbuf(); } 

Edited January 2019 ... now you can imitate what I explained cannot be done ...

This works for movable classes such as ifstream in C ++ 11 and even for non-copyable classes starting with C ++ 17 with copy permission.

Edited May 2019: use auto to ease verbosity

 { if (auto is = std::ifstream ("missing.txt")) { // ok now ! std::cout << "true: " << is.rdbuf(); } else { is.open("main.cpp"); std::cout << "false: " << is.rdbuf(); } } struct NoCpy { int i; int j; NoCpy(int ii = 0, int jj = 0) : i (ii), j (jj) {} NoCpy(NoCpy&) = delete; NoCpy(NoCpy&&) = delete; operator bool() const {return i == j;} friend std::ostream & operator << (std::ostream & os, const NoCpy & x) { return os << "(" << xi << ", " << xj << ")"; } }; { auto x = NoCpy(); // ok compiles // auto y = x; // does not compile if (auto nocpy = NoCpy (7, 8)) { std::cout << "true: " << nocpy << std::endl; } else { std::cout << "false: " << nocpy << std::endl; } } 
+2
Apr 17 '13 at 2:30
source share



All Articles