Введення в магію шаблонів

Введення в магію шаблонів -3

  • 22.06.15 3:59 •
  • ferus •
  • # 260899 •
  • Хабрахабр •
  • 11 •
  • 4897

- такий же як Forbes, тільки краще.

Шаблони в С ++ є засобами метапрограмування і реалізують поліморфізм часу компіляції. Що це таке?
Це коли ми пишемо код з поліморфним поведінкою, але сама поведінка визначається на етапі компіляції - тобто на противагу поліморфізму віртуальних функцій, отриманий бінарний код вже буде мати постійне поведінку.



Ми використовуємо шаблони для краси. Кожен С ++ розробник знає, що таке краса, краса - це коли код компактний. зрозумілий і швидкий.

Мета-магія і неявні інтерфейси


Що таке метопрограмма? Метопрограмма - це програма, результатом роботи якої буде інша програма. Для С ++ виконанням метапрограмм займається компілятор, а результатом є бінарний файл.

Перші заклинання: чарівна дубина


Введення в магію шаблонів

Конкретизуємо наш шаблон і подивимося, які типи ми отримали для різних параметрів шаблону:


У висновку програми видно, що типи конкретизацій шаблону різні навіть для еквівалентних типів - unsigned char char. При цьому вони ідентичні для char CHAR, тому що typedef не створює тип, а лише дає йому інше ім'я. Ідентичні вони і для виразів 1 і 2-1, тому що компілятор обчислює вирази і замість 2-1 використовує 1.

Звідси і випливає, що ми не можемо використовувати для шаблонів роздільну компіляцію без додаткових проблем:


Взагалі, в стандарті С ++ для цього є ключове слово export. однак ця фіча занадто важко буде реалізувати і відсутній в більшості компіляторів. Є компілятори, які її підтримують, але не раджу її використовувати в переносимому коді.

Крім класів існують і шаблони функцій:

Якщо компілятор може вивести тип параметра шаблона з типу параметрів - він так і вчинить, при цьому нам не потрібно вказувати його в коді. Якщо немає, то ми можемо визначити роздільну функцію:


Вона не несе ніяких накладних витрат.

Спеціалізація - це новий рівень


Введення в магію шаблонів

Зазвичай використовуючи шаблони ми хочемо написати універсальний код, проте в деяких випадках ми можемо програти в продуктивності. Для вирішення проблеми існує спеціальне закляття - спеціалізація шаблону. Спеціалізація - це повторне визначення шаблону з конкретним типом або класом типів:


Компілятор сам вибере найбільш точно відповідну спеціалізацію, в прикладі це клас типів "покажчик на тип".

Зловісна магія: рекурсія


Спеціалізації і той факт, що ми можемо використовувати шаблони в шаблонах, дає дам одну дуже цікаву можливість - рекурсія часу компіляції.

Введення в магію шаблонів

Найпростіший і популярний приклад - обчислення будь-якого ряду або полінома, скажімо, сума ряду натуральних чисел:


Дивимося ... Працює! Круто? Збільшимо кількість ітерацій до 500:


Тепер компіляція займає більше часу, при цьому час виконання програми - константа! Чудеса!

Не роби козу якщо хотів грозу


Тут є пара моментів.

Введення в магію шаблонів

Максимальна глибина рекурсії за замовчуванням обмежена реалізацією, для нового gcc це 900, для старих версій він менше. параметр

знімає це обмеження.

Другий підводний камінь - не чекайте звітів про помилки. Міняємо суму на факторіал:


Отримуємо некоректний результат, і жодного попередження.

Третій момент, очевидний: ми можемо створити занадто багато майже однакових конкретизацій шаблону і замість приросту продуктивності отримати приріст бінарного коду.

Потужні заклинання древніх


А чи можна поєднати магію успадкування з шаблонної магією?

Введення в магію шаблонів

Стародавні використовують для цього заклинання CRTP. Ідея проста: можна застосувати не віртуальне успадкування і забезпечити поліморфну ​​поведінку за допомогою явного приведення типу спадкоємця до типу батька. Давайте розглянемо приклад використання:


Ми отримуємо успадковані inline методи з поліморфним поведінкою! Хто скаже що це не круто - мій ворог назавжди.

Стародавні також радять додавати в конструктор батька щось типу того:


Щоб демони, розбуджені потужним заклинанням, не змогли завдати шкоди викликав їх магу.

Введення в магію шаблонів

Є ще багато таємних технік, древніх і не дуже. Сподіваюся на не скоро зустріч / * в пеклі * /, і нехай прибуде з вами сила древніх.

Схожі статті