cpp17 · advanced
C++17: if constexpr
if constexpr (C++17) is a compile-time conditional inside templates whose false branch is discarded — not instantiated — for a particular template instantiation. Because the rejected branch is never instantiated, it may contain code that would be ill-formed for other types (for example calling v.str() when T is int), which a runtime if could never permit since a runtime if compiles both branches. The discarded branch must still be syntactically parseable, just not semantically valid. This collapses what previously required SFINAE overload sets or tag dispatch into a single readable function, and is ideal for type-dispatched serializers and printers, trait-based branching, unwrapping optional/variant, and writing the base case of parameter-pack recursion (if constexpr (sizeof...(rest)) recurse; else stop).
C++17 if constexpr: the not-taken branch is discarded (not instantiated) for a given template instantiation, so each branch may be ill-formed for other types — it replaces SFINAE/tag dispatch for type-dispatched generic code.
The code
template <class T>auto to_string(const T& v) { if constexpr (std::is_arithmetic_v<T>) return std::to_string(v); // only this branch else if constexpr (std::is_same_v<T, const char*>) return std::string(v); else return v.str(); // compiled only for T with .str()}
// pre-C++17 you needed tag dispatch or SFINAE overloads for thisWhat this lesson walks through
- 01Compile-time branch selection
- 02Why a runtime if fails here
- 03Gotcha — only discards inside a template
- 04Where it shines
if constexpr discards the not-taken branch at compile time — the rejected branch is not instantiated for that T. That means each branch may contain code that would be ill-formed for other types, which a runtime if could never allow. It collapses what used to need SFINAE or tag dispatch into one readable function.
See it animated — step by step, at your own pace
Unlock the full interactive walkthrough of C++17: if constexpr and 100+ animated C++ interview lessons.