The if constexpr statement can be used to conditionally compile code. The condition must be a constant expression. The branch not selected is discarded. A discarded statement inside a template is not instantiated. For example:

template<class T, class ... Rest>
void g(T &&p, Rest &&...rs)
{
  // ... handle p
  if constexpr (sizeof...(rs) > 0)
    g(rs...);  // never instantiated with an empty argument list
}

In addition, variables and functions that are odr-used only inside discarded statements are not required to be defined, and discarded return statements are not used for function return type deduction.

if constexpr is distinct from #ifdef. #ifdef conditionally compiles code, but only based on conditions that can be evaluated at preprocessing time. For example, #ifdef could not be used to conditionally compile code depending on the value of a template parameter. On the other hand, if constexpr cannot be used to discard syntactically invalid code, while #ifdef can.

if constexpr(false) {
    foobar;  // error; foobar has not been declared
    std::vector<int> v("hello, world");  // error; no matching constructor
}