Прощавай, SFINAE, ласкаво просимо, if constexpr

Що таке 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?

pic

Гілка умовного оператора, яка не відповідає вимогам часу компіляції, видаляється з фінальної реалізації функції areEqualModernApproach.

Висновок

if constexpr забезпечує елегантний спосіб вставлення точок розгалуження у процес компіляції без недоліків, пов’язаних із методом SFINAE.

Якщо у вас є відгуки, запитання або ідеї, не соромтеся звертатися до мене через LinkedIn або Gmail.

Перекладено з: Farewell SFINAE, welcome if constexpr

Leave a Reply

Your email address will not be published. Required fields are marked *