Sobes.tech
Senior

C++та SFINAE (Substitution Failure Is Not An Error) эмне?

sobes.tech AI

AIден жооп

SFINAE (Substitution Failure Is Not An Error) — бул C++ тийшиндеги эреже, ал эми эгер компилятор шаблон аргументтерин функция же класс сигнатурасына орноткондо, жана бул орнотуу туура эмес кодго алып келсе (мисалы, бул тип үчүн жок мүчөнү колдонууга аракет кылуу), бул дароо каталык деп эсептелбейт. Анын ордуна, компилятор бул шаблон мисалын жөн гана көз жаздымда калтырып, чечим кабыл алууда улантат.

Бул эреже компиляция этабында метапрограммалоо үчүн колдонулат, ал шаблондардын жүрүм-туруму шаблон аргументтеринин касиеттерине көз каранды болушу мүмкүн экенин камсыз кылат.

SFINAE колдонулушунун мисалдары:

  • белгилүү мүчөлөрдүн же колдоого алынган операциялардын болушуна жараша жүктөлгөн функциялар же шаблон класстарынын специализацияларын тандоо.
  • C++20 чейин концепттерди (концепттер пайда болгонго чейин) ишке ашыруу, шаблон түрлөрүн чектөө үчүн.
  • Тип-караштар (type traits) түзүү.

SFINAE менен std::enable_if колдонуу мисалы:

#include <iostream>
#include <type_traits> // std::enable_if үчүн

// Функция шаблону, ал гана бүтүн типтер үчүн компиляцияланат
template <typename T>
typename std::enable_if<std::is_integral<T>::value, void>::type
print_if_integral(T value) {
    std::cout << "Бүтүн тип: " << value << std::endl;
}

// Функция шаблону, ал гана ондук бөлүкчөлөргө ээ типтер үчүн компиляцияланат
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, void>::type
print_if_floating_point(T value) {
    std::cout << "Ондук бөлүкчө тип: " << value << std::endl;
}

int main() {
    print_if_integral(5);       // Биринчи функция чакырылат
    print_if_floating_point(3.14); // Экинчи функция чакырылат
    // print_if_integral("салам"); // Каталар — орнотуу ийгиликсиз, функциялар көз жаздымда калат

    return 0;
}

Бул мисалда std::enable_if кайтаруучу тип катары колдонулат. Эгер std::is_integral<T>::value чын болсо, анда std::enable_if void типин камсыз кылат. Эгер шарт жалган болсо, std::enable_if type мүчөсүн камсыз кылбайт, бул функциянын сигнатурасында орнотуунун ийгиликсиздигине алып келет жана компилятор бул специализацияны көз жаздымда калтырат.