Мазмунга өтүү

constexpr менен компиляция учурунда программалоо

Сабактын башталышы

constexpr менен компиляция учурунда программалоо

Эсептөөнү аткаруу убактысынан компиляторго которуу - шаблон метапрограммалоонун заманбап мураскери

Негизги идея: constexpr үй-бүлөсү компиляторго функция же өзгөрмө компиляция учурунда эсептелүүгө жарактуу экенин билдирет. Аргументтердин өзү компиляция убагынын константалары болгондо, натыйжаны компилятор эсептеп, аны бинардык файлга литерал катары бышырат - аткаруу убагында процессорго эч кандай иш калбайт. Шаблон метапрограммалоо (TMP) эсептөөнү табышмактай окулган рекурсивдүү шаблон инстанциялары түрүндө коддогон жерде, constexpr сизге кадимки функцияларды - циклдер, локалдык өзгөрмөлөр жана if менен - жазууга мүмкүнчүлүк берет, алар кошумча компиляция учурунда да иштейт.
Теманын аягында сиз:
  • constexpr функциясын (компиляцияда иштеши мүмкүн) consteval функциясынан (иштеши милдеттүү) айырмалай аласыз;
  • constexpr өзгөрмөсү качан компиляцияда эсептөөнү мажбурлаарын жана бул жөнөкөй const дан кантип айырмаланарын билесиз;
  • if constexpr менен бутактарды компиляцияда таштап, SFINAE жана тег-диспетчерлөө кодуңуздун көбүнөн баш тарта аласыз;
  • constexpr эмне үчүн маанилерди эсептөө үчүн TMP ни негизинен алмаштырганын түшүндүрүп, шаблондор жана TMP дагы эле керек болгон учурларды атай аласыз.

Тема бул курстагы Шаблон метапрограммалоо, SFINAE жана чектөөлөр жана Концепттер (C++20) темаларына негизделет. Сиз рекурсивдүү шаблонду жана тип трейтин окуй аласыз деп болжолдонот.

1. constexpr функциялары - убада эмес, уруксат

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

constexpr long factorial(int n) {
    long result = 1;                 // C++14: локалдык өзгөрмөлөр, циклдер
    for (int i = 2; i <= n; ++i)     // жана мутация - баары уруксат
        result *= i;
    return result;
}

constexpr long f5 = factorial(5);    // компилятор эсептейт -> 120
int r = read_int();                  // кайсы бир аткаруу убагындагы маани
long fr = factorial(r);              // ошол эле функция, аткаруу убагында иштейт

Бул Шаблон метапрограммалоо темасында кездешкен рекурсивдүү шаблондук факториалга караганда канчалык окулуктуу экенине көңүл буруңуз. Бул кадимки императивдик код. C++14 тен бери constexpr функциясы циклдерди, бир нече операторду, локалдык өзгөрмөлөрдү жана аларды өзгөртүүнү камтышы мүмкүн; C++11 деги бир гана return чектөөсү эчак жоюлду.

Константалык эсептөө контексти деген эмне? Тил константалык туюнтманы талап кылган жерлер:

  • constexpr өзгөрмөсүнүн инициализатору же static_assert шарты;
  • типтик эмес шаблон аргументи, мисалы std::array<int, factorial(5)>;
  • массивдин өлчөмү, санагычтын мааниси, case белгиси.
Эч бир аргумент менен константа бере албаган constexpr функциясы туура эмес (диагностика талап кылынбайт). Бирок аткаруу убагындагы аргументтер менен чакырылган туура constexpr функциясы толук калыпта: ал жөн гана аткаруу убагында иштейт.

Бул сабакты YourAIZone платформасында улантыңыз

Толук сабакта — толук түшүндүрмө, чыгарылган мисалдар, көп кездешкен каталар, заматта текшерилүүчү тесттер жана ЖИ-репетитор. Конок катары дароо баштаңыз же прогрессти сактоо үчүн аккаунт түзүңүз.

Толук сабакта

  • Толук түшүндүрмө
  • Чыгарылган мисалдар
  • Көп кездешкен каталар жана алардан кантип качуу керек
  • Тест суроолору: 15
  • Тема боюнча суроолорго жооп берген ЖИ-репетитор
  • Окуучу, ата-эне жана мугалим үчүн прогрессти көзөмөлдөө