Skip to content

Commit 453a61c

Browse files
authored
Merge pull request #5065 from TylerMSFT/githubs
improve code examples
2 parents 559719f + d9885ae commit 453a61c

File tree

1 file changed

+74
-43
lines changed

1 file changed

+74
-43
lines changed

docs/cpp/if-else-statement-cpp.md

Lines changed: 74 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
---
22
title: "if-else statement (C++)"
33
description: "Use if-else, if-else with initializer, and if-constexpr statements to control conditional branching."
4-
ms.date: 10/02/2020
4+
ms.date: 10/16/2023
55
f1_keywords: ["else_cpp", "if_cpp"]
66
helpviewer_keywords: ["if keyword [C++]", "else keyword [C++]"]
7-
ms.assetid: f8c45cde-6bce-42ae-81db-426b3dbd4caa
87
---
98
# if-else statement (C++)
109

11-
An if-else statement controls conditional branching. Statements in the *`if-branch`* are executed only if the *`condition`* evaluates to a non-zero value (or **`true`**). If the value of *`condition`* is nonzero, the following statement gets executed, and the statement following the optional **`else`** gets skipped. Otherwise, the following statement gets skipped, and if there's an **`else`** then the statement following the **`else`** gets executed.
10+
An if-else statement controls conditional branching. Statements in the *`if-branch`* are executed only if the *`condition`* evaluates to a nonzero value (or **`true`**). If the value of *`condition`* is nonzero, the following statement gets executed, and the statement following the optional **`else`** gets skipped. Otherwise, the following statement gets skipped, and if there's an **`else`** then the statement following the **`else`** gets executed.
1211

13-
*`condition`* expressions that evaluate to non-zero are:
12+
*`condition`* expressions that evaluate to nonzero are:
1413

1514
- **`true`**
1615
- a non-null pointer,
17-
- any non-zero arithmetic value, or
16+
- any nonzero arithmetic value, or
1817
- a class type that defines an unambiguous conversion to an arithmetic, boolean, or pointer type. (For information about conversions, see [Standard Conversions](../cpp/standard-conversions.md).)
1918

2019
## Syntax
@@ -69,52 +68,54 @@ This sample code shows several **`if`** statements in use, both with and without
6968

7069
using namespace std;
7170

72-
class C
73-
{
74-
public:
75-
void do_something(){}
76-
};
77-
void init(C){}
78-
bool is_true() { return true; }
79-
int x = 10;
80-
8171
int main()
8272
{
83-
if (is_true())
73+
int x = 10;
74+
75+
if (x < 11)
8476
{
85-
cout << "b is true!\n"; // executed
77+
cout << "x < 11 is true!\n"; // executed
8678
}
8779
else
8880
{
89-
cout << "b is false!\n";
81+
cout << "x < 11 is false!\n"; // not executed
9082
}
9183

9284
// no else statement
93-
if (x == 10)
85+
bool flag = false;
86+
if (flag == true)
9487
{
95-
x = 0;
88+
x = 100; // not executed
9689
}
9790

98-
C* c;
99-
init(c);
100-
if (c)
91+
int *p = new int(25);
92+
if (p)
10193
{
102-
c->do_something();
94+
cout << *p << "\n"; // outputs 25
10395
}
10496
else
10597
{
106-
cout << "c is null!\n";
98+
cout << "p is null!\n"; // executed if memory allocation fails
10799
}
108100
}
109101
```
110102

103+
Output:
104+
105+
```output
106+
x < 11 is true!
107+
25
108+
```
109+
111110
## <a name="if_with_init"></a> if statement with an initializer
112111

113-
Starting in C++17, an **`if`** statement may also contain an *`init-statement`* expression that declares and initializes a named variable. Use this form of the if-statement when the variable is only needed within the scope of the if-statement. **Microsoft-specific**: This form is available starting in Visual Studio 2017 version 15.3, and requires at least the [`/std:c++17`](../build/reference/std-specify-language-standard-version.md) compiler option.
112+
Starting in C++17, an **`if`** statement might also contain an *`init-statement`* expression that declares and initializes a named variable. Use this form of the if-statement when the variable is only needed within the scope of the if-statement. **Microsoft-specific**: This form is available starting in Visual Studio 2017 version 15.3, and requires at least the [`/std:c++17`](../build/reference/std-specify-language-standard-version.md) compiler option.
114113

115114
### Example
116115

117116
```cpp
117+
// Compile with /std:c++17
118+
118119
#include <iostream>
119120
#include <mutex>
120121
#include <map>
@@ -123,28 +124,27 @@ Starting in C++17, an **`if`** statement may also contain an *`init-statement`*
123124

124125
using namespace std;
125126

126-
map<int, string> m;
127+
map<int, string> m{ {1, "one"}, {2, "two"}, {10,"ten"} };
127128
mutex mx;
128-
bool shared_flag; // guarded by mx
129-
void unsafe_operation() {}
129+
bool shared_flag = true; // guarded by mx
130+
int getValue() { return 42; }
130131

131132
int main()
132133
{
133134

134135
if (auto it = m.find(10); it != m.end())
135136
{
136-
cout << it->second;
137-
return 0;
137+
cout << it->second << "\n";
138138
}
139139

140-
if (char buf[10]; fgets(buf, 10, stdin))
140+
if (int x = getValue(); x == 42)
141141
{
142-
m[0] += buf;
142+
cout << "x is 42\n";
143143
}
144144

145145
if (lock_guard<mutex> lock(mx); shared_flag)
146146
{
147-
unsafe_operation();
147+
cout << "setting shared_flag to false\n";
148148
shared_flag = false;
149149
}
150150

@@ -156,31 +156,62 @@ int main()
156156
}
157157
```
158158
159+
Output:
160+
161+
```Output
162+
ten
163+
x is 42
164+
setting shared_flag to false
165+
Error! Token must not be a keyword
166+
```
167+
159168
## <a name="if_constexpr"> if constexpr statements
160169

161170
Starting in C++17, you can use an **`if constexpr`** statement in function templates to make compile-time branching decisions without having to resort to multiple function overloads. **Microsoft-specific**: This form is available starting in Visual Studio 2017 version 15.3, and requires at least the [`/std:c++17`](../build/reference/std-specify-language-standard-version.md) compiler option.
162171

163172
### Example
164173

165-
This example shows how you can write a single function that handles parameter unpacking. No zero-parameter overload is needed:
174+
This example shows how you can conditionally compile a template based on the type sent to it:
166175

167176
```cpp
168-
template <class T, class... Rest>
169-
void f(T&& t, Rest&&... r)
170-
{
171-
// handle t
172-
do_something(t);
177+
// Compile with /std:c++17
178+
#include <iostream>
173179

174-
// handle r conditionally
175-
if constexpr (sizeof...(r))
180+
template<typename T>
181+
auto Show(T t)
182+
{
183+
//if (std::is_pointer_v<T>) // Show(a) results in compiler error for return *t. Show(b) results in compiler error for return t.
184+
if constexpr (std::is_pointer_v<T>) // This statement goes away for Show(a)
176185
{
177-
f(r...);
186+
return *t;
178187
}
179188
else
180189
{
181-
g(r...);
190+
return t;
182191
}
183192
}
193+
194+
int main()
195+
{
196+
int a = 42;
197+
int* pB = &a;
198+
199+
std::cout << Show(a) << "\n"; // prints "42"
200+
std::cout << Show(pB) << "\n"; // prints "42"
201+
}
202+
```
203+
204+
The **`if constexpr`** statement is evaluated at compile time, and the compiler only generates code for the **`if`** branch that matches the type of the argument sent to the function template. If you comment out the **`if constexpr`** statement and uncomment the **`if`** statement, the compiler generates code for both branches. That means you get an error:
205+
- If you call `ShowValue(a);` you get an error on `return *t` because `t` isn't a pointer, even though the **`if`** statement is false and the code is never executed.
206+
- If you call `ShowValue(pB);` you get an error on `return t` because `t` is a pointer, even though the **`if`** statement is true and the code is never executed.
207+
208+
Using `if constexpr` solves this problem because only the statement that matches the type of the argument sent to the function template is compiled.
209+
210+
Output:
211+
212+
```output
213+
42
214+
42
184215
```
185216

186217
## See also

0 commit comments

Comments
 (0)