Free tools Windows power users keep installed
One-click scans. No signup required.
if constexpr lets a C++17 template choose a code path at compile time based on a constant expression, commonly a type trait. When the condition is resolved for a template specialization, the unselected branch is discarded rather than instantiated. That makes it possible to keep type-specific operations together in one function template—without making every operation valid for every type.
What if constexpr does
C++17 introduced if constexpr as an if statement whose condition must be a compile-time constant expression. The language feature is documented in cppreference’s description of if statements; the C++17 feature overview identifies the feature-test macro as __cpp_if_constexpr, with value 201606L (C++ feature-test macros).
In a template, the important behavior happens after substitution determines the condition. If the condition is no longer value-dependent, the branch not selected for that specialization is discarded and not instantiated. This allows the selected branch to use operations that are appropriate for its type, even if those operations would be invalid for a different type.
Example: use a different operation for pointers
#include <iostream>
#include <type_traits>
template<class T>
void print_value(const T& value) {
if constexpr (std::is_pointer_v<T>) {
std::cout << *value;
} else {
std::cout << value;
}
}
For T = int*, std::is_pointer_v<T> is true and the pointer branch is selected, so the function dereferences value. For T = int, the other branch is selected and the function writes the value directly. The unselected branch is discarded for each specialization, which is why the dereference does not have to be valid for int.
#1 Best Overall
This is the compile-time branching behavior described in Microsoft Learn’s documentation on if constexpr: a template can make a compile-time choice without requiring separate overloads for each case.
How it differs from a normal if
| Statement | How the condition is chosen | What happens to the other branch | Use it when |
|---|---|---|---|
Normal if |
At runtime, from a Boolean value | For an instantiated function, both branches generally need to be well-formed | The choice depends on runtime data |
if constexpr |
At compile time, from a constant-expression condition | In a template, a non-selected branch is discarded when the condition is resolved | The choice depends on a type or another compile-time property |
if constexpr does not make a runtime decision happen at compile time. If a function needs to choose based on a value that changes while the program runs, use a normal if.
When it simplifies template code
Use if constexpr when one function template has a small number of clear branches whose operations differ by type or compile-time property. A type trait can select a branch, and the shared function body can keep related logic in one place instead of distributing it across overloads.
Overloads, tag dispatch, and SFINAE remain alternatives. They move selection into overload resolution or constrain which overload participates; if constexpr branches inside the function body. Which approach is clearer depends on the design: consider how much code is duplicated, how easily readers can follow the shared logic, and how clearly unsupported types fail. Those are engineering trade-offs, not guarantees that one technique always produces better diagnostics or more readable code.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
What if constexpr does not discard
- Code outside the relevant template context: A discarded statement outside a template is still checked. The feature is not a universal substitute for preprocessor conditionals such as
#if. - Errors in non-dependent names: Names that do not depend on template parameters must still be valid during the initial template check. A later discarded branch does not hide such errors.
- A condition that is not a constant expression: The condition must meet the compile-time constant-expression requirement; a runtime value is not sufficient.
For the language rule and its template-instantiation context, see the C++ working draft N4659.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Check compiler support with the feature-test macro
The feature-test macro is __cpp_if_constexpr. The C++ feature-test macro reference lists its value as 201606L. Code that conditionally uses the feature can test the macro after including the appropriate feature-test macro header for its implementation and language mode; compiler support still depends on the compiler and the selected C++ standard mode.
Quick Recap
Best Value
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

