> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# C++ Constexpr If

`if constexpr` is a compile-time conditional statement introduced in C++17 that instructs the compiler to evaluate a boolean constant expression and discard the unselected branch from the final instantiated code. Unlike a standard `if` statement, the discarded branch does not participate in template instantiation, return type deduction, or runtime execution.

## Syntax

```cpp theme={"dark"}
if constexpr (condition) {
    // statement-true
} else if constexpr (condition) {
    // statement-true
} else {
    // statement-false
}
```

The `condition` must be a contextually converted constant expression of type `bool`. It must be evaluable entirely at compile time.

## Compiler Mechanics and Discarded Statements

When the compiler evaluates an `if constexpr` statement, the branch that evaluates to `false` becomes a **discarded statement**. The compiler enforces specific rules regarding how these discarded statements are processed:

### 1. Template Instantiation

In templated contexts, if the `condition` depends on a template parameter, the discarded branch is not instantiated. This means code within the discarded branch that would normally be ill-formed for a specific template type will not trigger a compilation error, provided the error depends on the template parameter.

```cpp theme={"dark"}
template <typename T>
void process(T value) {
    if constexpr (std::is_pointer_v<T>) {
        // If T is int, this branch is discarded and NOT instantiated.
        // Therefore, *value does not cause a compilation error.
        *value = 10; 
    } else {
        // If T is int*, this branch is discarded.
        value = 10;
    }
}
```

### 2. Non-Dependent Well-Formedness

A discarded statement is not completely ignored by the parser. It must still be syntactically valid. Furthermore, if the code inside the discarded branch does *not* depend on a template parameter, it must be semantically well-formed, even if it is discarded.

```cpp theme={"dark"}
template <typename T>
void check() {
    if constexpr (sizeof(T) > 4) {
        // Valid: Depends on T. Ignored if sizeof(T) <= 4.
        T::invalid_function(); 
    } else {
        // ERROR: Ill-formed. Does not depend on T. 
        // The compiler will flag this even if the branch is discarded.
        undeclared_global_function(); 
    }
}
```

### 3. Return Type Deduction

When a function uses `auto` for return type deduction, `return` statements inside discarded branches do not participate in deducing the function's return type.

```cpp theme={"dark"}
template <typename T>
auto getValue(T t) {
    if constexpr (std::is_integral_v<T>) {
        return t; // If T is int, return type is deduced as int
    } else {
        return 0.0; // If T is int, this is discarded and does not conflict with 'int'
    }
}
```

If a standard `if` were used in the example above, the compiler would throw an error for inconsistent deduced return types (`int` vs `double`). `if constexpr` prevents this by eliminating the unselected `return` statement before type deduction occurs.

### 4. Initialization Statements

Like standard `if` statements (since C++17), `if constexpr` supports initialization statements. The initialized variable is visible in both the true and false branches, but its type and value must be resolvable at compile time if used within the constant expression condition.

```cpp theme={"dark"}
if constexpr (constexpr int x = sizeof(int); x > 2) {
    // x is available here
} else {
    // x is also available here
}
```

### 5. No Short-Circuiting of Template Substitution

When multiple conditions are chained using logical operators (`&&`, `||`) within an `if constexpr` condition, the *evaluation* of the constant expression short-circuits, but the *substitution* of template parameters into the entire condition occurs *before* evaluation. Consequently, substituting an invalid type into the right-hand side of a logical operator causes a hard compilation error (not SFINAE), even if the left-hand side dictates that the right-hand side would not be evaluated. To achieve true short-circuiting that prevents invalid template substitutions, nested `if constexpr` blocks are required.

```cpp theme={"dark"}
template <typename T>
void evaluate_type() {
    // ERROR: If T does not have a nested 'value' member, substitution fails 
    // and causes a hard error, even if has_value_v<T> is false.
    /* 
    if constexpr (has_value_v<T> && T::value > 0) { 
        // ...
    } 
    */

    // CORRECT: The nested 'if constexpr' ensures substitution into T::value 
    // only occurs if the first condition is true.
    if constexpr (has_value_v<T>) {
        if constexpr (T::value > 0) {
            // ...
        }
    }
}
```

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor C++ Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
