Концепттер (C++20)
Шаблондорду окулуучу түрдө чектөө - шаблон параметрлерине аталышы бар, текшериле турган талаптар
- чектелбеген шаблондор жана эски
enable_if/SFINAE ыкмалары эмне үчүн жаман каталарды берерин түшүндүрүү, - стандарттык китепкананын концепттерин колдонуу (
std::integral,std::convertible_to,std::sortable, ...), - чектөөлөрдү төрт башка жол менен, анын ичинде кыскартылган
autoформасы менен тиркөө, - өз концептиңизди
requires-туюнтмасы менен жазуу (жөнөкөй, курама, типтик жана ичкериленген талаптар), - эң адистешкен перегрузканы тандоо үчүн чектөөлөрдүн сиңирүүсүн (subsumption) колдонуу.
1. Көйгөй: чектелбеген шаблондор жана SFINAE
Сиз функция шаблонун жазганды билесиз. Кыйынчылык - жылаңач template<typename T> эч нерсе убада кылбайт. Типке коюлган талаптар денесинин ичинде гана жашайт, ошондуктан туура эмес тип кайсы бир ички операция иштебей калганга чейин компиляцияланат:
template <typename T>
T twice(T x) { return x + x; } // T'де operator+ бар деп үнсүз болжолдойт
twice(std::string{"hi"}); // компиляцияланат: "hihi"
twice(std::vector<int>{1,2}); // КАТА - бирок <vector> тереңинде, беттеген ызы-чуу
C++20'га чейин чечим SFINAE ("Substitution Failure Is Not An Error") std::enable_if менен болгон: жаман тип перегрузканы жоготуп жиберсин деп, чектөөнү сигнатурага киргизчүсүз. Ал иштеди, бирок аны окуу мүмкүн эмес эле:
template <typename T,
typename = std::enable_if_t<std::is_integral_v<T>>>
T twice(T x) { return x + x; } // "эгер T бүтүн сан болсо гана" - бирок муну ким окуйт?
Ниет ("T бүтүн сан болушу керек") шаблон түтүктөрүнө көмүлгөн, ката билдирүүлөрү дагы эле коркунучтуу, ал эми чектөөнү кайра колдонууга же атоого болбойт. Концепттер мунун баарын окулуучу, аталышы бар келишим менен алмаштырат.