Разница между if constexpr
и if заключается в том, может ли выражение всегда выполняться во время компиляции.В вашем примере вы используете аргумент шаблона, поэтому не имеет значения, какой из них вы пишете.Разницу можно заметить, если у вас будет следующий код:
constexpr bool is_negative(int n)
{
if (n >= 0) return false;
else return true;
}
int main(int argc, char**)
{
constexpr bool v = is_negative(1);
bool b = is_negative(argc);
return static_cast<int>(v || b);
}
Для приведенного выше кода запись if constexpr
не будет работать.Поскольку вы можете вызывать функцию со значением времени выполнения.
Опять же, это не должно иметь значения, так как оба пути кода допустимы.При использовании функции с постоянными значениями должны включаться обычные оптимизации компилятора.
Реальный интерес к if constexpr
заключается в том, что допустим только один путь:
template <typename T>
constexpr auto get_value(T t) {
if constexpr(std::is_pointer_v<T>)
return *t; // deduces return type to int for T = int*
else
return t; // deduces return type to int for T = int
}
Если T будет int, путь кода с *t
недопустим, как вы можете 't разыменовываете int.Однако, поскольку каждый использует if constexpr
вместо if
, код в ложном пути должен быть синтаксически корректным, только если он зависит от аргумента шаблона.
Поскольку вы ищете руководство, компилятор уже требует: Используйте if constexpr
, когда один из путей кода недопустим.Используйте if
в зависимости от аргументов.
Для случая, когда условие if вычисляется во время компиляции с двумя допустимыми путями, используйте if constexpr
, чтобы требовать его оптимизации даже в отладочных сборках, используйте if
, если вы хотите пройти через негов отладочных сборках.
Если вы пойдете в крайности, выражение может стать слишком сложным для компилятора, чтобы оптимизировать его в производственной сборке, и в этом случае if constexpr
снова может быть интересным, находясь в горячем пути.Лично я еще не был в такой ситуации, однако я не использовал его так много.