Шаблондорду метапрограммалоо
Компиляторду коддун иштеши башталганга чейин типтерди жана маанилерди эсептеген программага айландыруу
- эки фазалуу моделди түшүндүрүү: компилятор эмнени эсептейт, процессор эмнени эсептейт;
constexprфункциялары жанаconsteval(C++20) менен эсептөөнү компиляция этабына которуу;<type_traits>китепканасы менен типтерди изилдөө жана өзгөртүү;- чаташкан перегрузкалардын ордуна
if constexprаркылуу бир функциянын ичинде типтер боюнча бутактоо; static_assertменен компиляция этабында келишимдерди камсыздоо жана TMP чыныгы алмашууларын түшүнүү.
1. Эки дүйнө: компиляция убактысы жана аткаруу убактысы
Ар бир C++ программасы эки дүйнөдө жашайт. Компиляция убактысынын дүйнөсүндө компилятор типтерди жана константалык туюнтмаларды башкарат, шаблондорду инстанцирлейт жана constexpr кодду эсептейт. Аткаруу убактысынын дүйнөсүндө процессор компиляциядан аман калган машина кодун аткарат. Метапрограммалоо — бул мүмкүн болушунча көп пайдалуу ишти биринчи дүйнөдө жасап, экинчисине аз калтыруу өнөрү.
Шаблондорду сиз орто курстан билесиз: template<typename T> бир аныктаманын көп типке кызмат кылышына мүмкүндүк берет. TMP үчүн негизги ой — шаблонду инстанцирлөө өзү эсептөө болуп саналат. Сиз std::vector<int> деп жазганда, компилятор вектор шаблонун int аргументи менен иштетип, таптакыр жаңы тип чыгарат. Шаблонго башка аргументтерди берсеңиз — башка типтерди эсептейт: бул компилятор аткарган типтерден (жана маанилерден) типтерге (жана маанилерге) карай таза функция.
Эмне үчүн керек? Үч конкреттүү пайда:
- Ылдамдык: компиляция этабында эсептелген маани бинардык файлда литерал болуп калат; процессор аны кайра эсептебейт.
- Коопсуздук: компиляция учурунда кармалган ката эч качан колдонуучуга жетпейт.
static_assertлогикалык катаны курулуш катасына айлантат. - Чыгымсыз жалпылык: бир жалпы алгоритм аткаруу убактысында нөл бутактоо менен ар бир типке адистеше алат.