Що таке if constexpr?
Конструкція if constexpr
була представлена в C++17 і дозволяє виконувати розгалуження під час компіляції. Це забезпечує більш зрозумілу, читабельну та легшу для підтримки альтернативу SFINAE (Substitution Failure Is Not An Error).
Розгляньмо простий приклад, щоб продемонструвати можливості if constexpr
. Для порівняння двох узагальнених змінних потрібно враховувати специфіку кожного можливого типу. Хоча змінні узагальнені, порівнювати числа з плаваючою точкою не можна так само, як і цілі числа. Тому потрібне розгалуження під час компіляції. Розгляньмо два підходи до вирішення цієї проблеми:
Традиційний підхід з використанням SFINAE:
#include <cmath>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_floating_point_v<T>, bool> areEqual(T aOp1, T aOp2)
{
return fabs(aOp1 - aOp2) < std::numeric_limits<T>::epsilon();
}
template <typename T>
std::enable_if_t<std::is_integral_v<T>, bool> areEqual(T aOp1, T aOp2)
{
return aOp1 == aOp2;
}
Залежно від типу T
, який виводиться під час компіляції, буде обрано одну реалізацію функції areEqual
.
Сучасний підхід з використанням if constexpr
template <typename T>
bool areEqualModernApproach(T aOp1, T aOp2)
{
if constexpr(std::is_integral_v<T>)
return aOp1 == aOp2;
else if constexpr(std::is_floating_point_v<T>)
return fabs(aOp1 - aOp2) < std::numeric_limits<T>::epsilon();
else
static_assert(false, "Unsupported type");
}
У порівнянні з SFINAE (який вимагає багато шаблонного коду), логіка в підході if constexpr
знаходиться в межах однієї функції-шаблону, а наміри стають зрозумілішими, оскільки код читається послідовно, а не через розв'язання перевантажень.
Для цікавих: як виглядає код після виконання if constexpr
?
Гілка умовного оператора, яка не відповідає вимогам часу компіляції, видаляється з фінальної реалізації функції areEqualModernApproach
.
Висновок
if constexpr
забезпечує елегантний спосіб вставлення точок розгалуження у процес компіляції без недоліків, пов’язаних із методом SFINAE.
Якщо у вас є відгуки, запитання або ідеї, не соромтеся звертатися до мене через LinkedIn або Gmail.
Перекладено з: Farewell SFINAE, welcome if constexpr