Skip to content

C++ Decision Making

Decision-making structures allow your program to execute different blocks of code based on whether certain conditions are true or false. This enables programs to react dynamically to different inputs or situations.

A typical decision-making structure evaluates a condition (an expression that results in true or false). If the condition is true, a specific block of code executes. Optionally, if the condition is false, another block of code might execute.

C++ provides several types of decision-making statements:

StatementDescription
if statementExecutes a block of code only if a specified boolean condition is true.
if...else statementExecutes one block of code if the condition is true and another block if the condition is false.
if...else if...else statementTests multiple conditions in sequence and executes the block corresponding to the first true condition. An optional final else block executes if none of the preceding conditions are true.
switch statementAllows a variable to be tested for equality against a list of constant values (cases). It provides an efficient alternative to long if...else if chains for specific scenarios.
Nested if statementsYou can place if or if...else statements inside other if or else blocks to create more complex decision logic.
Nested switch statementsYou can use one switch statement inside a case of another switch statement, though this can sometimes make code harder to read.

C++17 introduced if statements with initializers. This allows you to declare and initialize a variable within the scope of the if statement itself, making code more concise and improving locality.

// C++17: if with initializer
if (int errorCode = getError(); errorCode != 0) {
std::cerr << "An error occurred: " << errorCode << std::endl;
// errorCode is only visible within the if and else blocks
} else {
// errorCode is also visible here
std::cout << "Operation successful." << std::endl;
}

C++17 also added the [[fallthrough]] attribute for switch statements. If you intentionally want one case to fall through to the next, you should add this attribute to make your intent clear and suppress potential compiler warnings.

switch (value) {
case 1:
doSomething();
[[fallthrough]]; // Explicitly indicate fallthrough
case 2:
doSomethingElse();
break;
default:
handleDefault();
}

For compile-time decisions based on template parameters or constexpr values, C++17 introduced if constexpr. This evaluates the condition at compile time and discards the branch that is not taken, potentially leading to more efficient code.

template<typename T>
void process(T value) {
if constexpr (std::is_integral_v<T>) {
std::cout << "Processing an integral type." << std::endl;
} else if constexpr (std::is_floating_point_v<T>) {
std::cout << "Processing a floating-point type." << std::endl;
} else {
std::cout << "Processing another type." << std::endl;
}
}

The conditional (or ternary) operator ? : provides a concise way to express a simple if...else statement within an expression. Its general form is:

condition ? expression_if_true : expression_if_false;

The condition is evaluated first. If it is true, expression_if_true is evaluated, and its result becomes the value of the entire conditional expression. If condition is false, expression_if_false is evaluated, and its result becomes the value.

Example:

int x = 10, y = 20;
int maxVal = (x > y) ? x : y; // maxVal will be assigned the value of y (20)
std::cout << "The maximum value is: " << maxVal << std::endl;

While concise, overuse of the ternary operator, especially nested ones, can decrease code readability compared to a standard if...else statement.