SFINAE жана чектөөлөр
Перегрузкаларды типтер боюнча тандоо: enable_if, tag dispatch, аныктоо идиомасы жана концепттер эмнени оңдогону
- алмаштыруудагы каталык эмне экенин жана SFINAE так кайда иштээрин ("түз контекстте") түшүндүрө аласыз,
- шаблондорду
std::enable_ifаркылуу чектей аласыз - кайтаруу тибинде, шаблон параметринде же жарыяланбаган мааниси боюнча параметрде, - тип трейттери боюнча компиляция учурунда tag dispatch менен диспетчерлей аласыз,
- "бул тип X колдойбу?" деген суроону аныктоо идиомасы (
void_t) менен бере аласыз, - SFINAEнин чыныгы чектөөлөрүн атай аласыз жана эмне үчүн C++20 концепттери аны алмаштырарын түшүнөсүз.
1. Перегрузканы чечүү жана алмаштыруу
Компилятор талапкер функциялардан перегрузкалар топтомун түзүп, андан кийин эң мыкты дал келүүнү тандаарын сиз билесиз. Функция шаблондору үчүн адегенде кошумча кадам бар: компилятор конкреттүү талапкерди түзүү үчүн чыгарылган шаблон аргументтерин шаблондун сигнатурасына алмаштырышы керек. SFINAE ушул алмаштыруу кадамында жашайт.
Алмаштыруу сигнатуранын түз контекстинде - кайтаруу тиби, параметрлер тизмеси же шаблон параметрлеринин тизмеси - туура эмес тип же туюнтма жаратканда, бул каталык эмес. Талапкер жөн гана алынып салынат, ал эми перегрузканы чечүү калган талапкерлер менен уланат.
// Эки перегрузка. Алмаштыруу кайсынысы *каралаарын* чечет.
template <typename T>
typename T::value_type first(const T& c) { return *c.begin(); } // T::value_type керек
int first(int x) { return x; } // жөнөкөй запастагы вариант
first(std::vector<int>{1,2}); // vectorдо ::value_type бар -> шаблон тандалды
first(42); // intте ::value_type жок -> шаблон унчукпай алынды,
// int перегрузкасы колдонулат. Компиляция катасы жок.
"каталык эмес" деген сөз айкашы - маңызы ушул: эгер бул катуу каталык болсо, шаблон перегрузкасын кошуу байланышсыз чакырууларды бузмак. Анын ордуна ийгиликсиз алмаштыруу жөн гана талапкерлердин тизмесин кыскартат.