C++ IIFEs: initializing a `const` from an exhaustive switch

Today I Learned · September 18, 2026

C++ IIFEs: initializing a const from an exhaustive switch

When a value is the output of branching logic, a const initializer feels out of reach — until you wrap the branch in a lambda and call it immediately. An IIFE (immediately invoked function expression) is just that: a lambda with a trailing ().

const string_view name = [&it]() {
  switch (it) {
    case ItemType::Weapon: return "Weapon";
    case ItemType::QuestItem: return "Quest Item";
    case ItemType::Consumable: return "Consumable";
  }
  std::unreachable();
}();

Why the IIFE

Without it you’d have to declare the variable first and mutate it in each arm:

string_view name;
switch (it) {
  case ItemType::Weapon: name = "Weapon"; break;
  case ItemType::QuestItem: name = "Quest Item"; break;
  case ItemType::Consumable: name = "Consumable"; break;
}

Two problems. name cannot be const — it starts default-constructed and gets assigned per arm. And a forgotten case leaves it silently empty instead of erroring. The IIFE solves both at once:

  1. The lambda returns the value, so the whole ...() call is the initializer and const just works.
  2. Every case returns from the lambda, making the switch exhaustive by construction — there is no fall-through path to a wrong value.

Reading the pieces

Piece Job
[&it] captures the enum by reference
() { ... } zero-argument lambda
case ItemType::X: return "..." returns from the lambda, feeding the binding
std::unreachable() [[noreturn]] fallback after the exhaustive switch
trailing () immediately invokes the lambda

The exhaustive-switch contract

Gotchas