Чи шаблони C ++ є лише своєрідним прославленим макросом?


27

З різних порівнянь шаблонів C ++ та таких дженериків C # / Java, як цей,

/programming/31693/what-are-the-differences-between-generics-in-c-and-java-and-templates-in-c/31929#31929

Я зрозумів, що шаблони C ++ реалізуються за допомогою певної попередньої обробки (заміна простого тексту перед розбором), а не компіляція. Тому що перевірка типу в шаблонах C ++ нагадує макроси C. Я маю на увазі, якщо є деякі помилки, це помилки згенерованого коду після обробки шаблонів кодових блоків, а не від самих шаблонів. Іншими словами, вони є лише своєрідною верхньою версією макросів у С.

Потім я знайшов деякі інші факти, що підтверджують це -

  • Я подумав, якщо шаблони C ++ будуть реалізовані за допомогою попередньої обробки, виникнуть проблеми з динамічним посиланням (з використанням .dll). І швидкий гугл це підтримав.

  • Інший момент - цілі константи можна передавати як аргументи шаблонам. І навіть підтримує якусь рекурсію. Але ця рекурсія не знайдена у складеному складі / машинному коді. Управління рекурсією керує часом компіляції, генеруючи функції для кожного рекурсивного виклику і, таким чином, маючи більший, але швидший виконуваний двійковий файл.

Хоча на відміну від макросів C, він має деякі переважні здібності. Але чи не реалізований шаблон C ++ з якоюсь попередньою обробкою? Як це реалізується в різних компіляторах C ++?


19
Ні. Складаються шаблони C ++.
Едвард Странд

2
Яке ваше визначення "попередньої обробки"? А про "складання"? Досить широке визначення поняття "попередня обробка" може включати все, що робить компілятор; зрештою, компілятор дійсно просто обробляє джерело до того, як воно буде виконано, ні?
James McNellis

@James McNellis IMHO, якщо ви можете просто розмежувати попередню обробку від усіх інших речей, зроблених для компіляції, досить зрозуміти моє питання. Для уточнення препроцесора- en.wikipedia.org/wiki/Preprocessor#Lexical_preprocessors
Гюльшан

6
Якщо ви маєте на увазі цю форму попередньої обробки, то ні, шаблони C ++ - це не просто якийсь прославлений макрос.
James McNellis

1
Мова шаблонів насправді завершена, тому вони набагато більше, ніж розширені макроси.
davidk01

Відповіді:


9

Шаблони C ++ є своєрідним макросом Lisp (або навіть більше, Scheme). Це повна система Тьюрінга, яка оцінює час компіляції, але вона сильно обмежена, оскільки немає доступу з цієї мови до базового середовища C ++. Отже, так, шаблони C ++ можна розглядати як певну форму попередньої обробки, з дуже обмеженою взаємодією з кодом, що генерується.


2
"але вона сильно обмежена, оскільки немає доступу з цієї мови до базового середовища C ++." -- Що це означає? Я намагався проаналізувати це твердження, але не вдалося.
Quant_dev

2
Ум, насправді ... github.com/kmichel/bf0x
Антон Голов

3
@ SK-логіка: В бік C ++ 11 є C ++, якщо ви (педантично) не ставитесь до різних версій однієї мови як до різних мов.
Джон Перді

3
@ Джона Перді, C ++ 11 не існувало (офіційно) до моменту цієї відповіді. Сьогодні приклад був би складнішим, як декомпозиція структури даних, використання бібліотечної функції тощо.
SK-логіка

1
@ SK-логіка: Чи трапляється вам знати реалізацію C ++ з макросами, подібними до Lisp? Мені нудить обмеження шаблонів. Приклад мови синтаксису в стилі C ++ з потужною макросистемою в Haxe : haxe.org/manual/macros . (Не допомагає мені, оскільки я використовую C ++ для своєї мети - програмування 8-бітових мікроконтролерів; для кращого мови є кращі мови).
pfalcon

41

Можливо, найбільша відмінність полягає в тому, що макроси C розгортаються у фазі попередньої обробки, перш ніж проводиться будь-яке інше компілювання, тоді як шаблони C ++ є частиною компіляції. Це означає, що шаблони C ++ відомі, серед іншого, і мають масштаб, і не є простою підстановкою тексту. Вони можуть компілюватись до реальних функцій, а тому уникають більшості проблем, що мають макроси. Зрозуміти тип означає, що вони можуть бути загальними або спеціалізованими: наприклад, легко надати swapшаблонну функцію та легко написати спеціалізації, які добре працюють, навіть якщо об'єкти керують накопичувальною пам'яттю.

Отже: шаблони C ++ не є попередньо обробленими в тому ж сенсі, що макроси є, вони не є різновидом макросу C, і неможливо використовувати макроси C для дублювання того, що роблять шаблони.

Шаблони живуть у файлах заголовків, а не у пов'язаних бібліотеках, правда, але якщо ви постачаєте .dll, ви, ймовірно, також надаєте файл заголовка для його використання.


12
Їм не потрібно жити у файлі заголовка (це просто найпростіша техніка їх використання). Ви можете визначити їх у вихідному файлі та вручну примусити інстанціювати шаблон у вихідному файлі (компіляційний блок). Потім посилання дозволить визначити моменти як звичайні (це методика обмеження шаблонів певними типами та недопущення всіх загальних типів).
Мартін Йорк

@Martin: Я не впевнений, чи ця технологія (хоча підтримується) насправді явно підтримується стандартом. Інакше всі компілятори вже exportреалізували б. Я знаю, що це працює для функцій, але я сумніваюся, що він працює для класів: як би ви дізналися їх розмір?
Матьє М.

@Matthieu M: Це не має нічого спільного з ключовим словом експорту. Він стосується "явного" опису шаблону і добре визначений у стандарті.
Мартін Йорк

2
@Matthieu M .: Якщо компілятор знає підпис функції, а лінкер може знайти реалізацію, все круто. Це стосується того, чи є функція шаблонною функцією. На практиці вони, як правило, живуть у заголовкових файлах, тому що форсування конкретних екземплярів, як правило, більше роботи, ніж варто, але Мартін вірно зазначає альтернативу.
Девід Торнлі

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

5

Чи має значення, як вони реалізовані? Ранні компілятори C ++ були лише попередніми процесорами, які подавали код до компілятора змінного струму, це не означає, що C ++ - це лише прославлений макрос.

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

Існує безліч способів робити шаблони коду типу в c, жоден з яких не дуже приємний, коли ви виходите за рамки простих типів.


Я не говорив про те, щоб C ++ був прославленим макросом. Я дуже захоплююся С ++. Просто цікаво.
Гульшан

2
@Gulshan: Ні, ти нічого про це не сказав. Тим не менш, саме так працювали ранні компілятори C ++ (за винятком того, що CFront був чимось компілятором, а не просто макропрепроцесором), а ваші висловлювання про шаблони C ++ приблизно так само застосовні до самого раннього C ++.
Девід Торнлі

CFront компілював C ++ до C. Рядок між препроцесором і компілятором чітко визначений: компілятор намагається зрозуміти його вхід - за допомогою розбору, побудови AST і т.п.
Джон Перді

1
Я думаю, що Давид мав на увазі, що існує основний підмножина C ++ і що шаблони можна розглядати як якісь макроси, які використовуються для загальної програми в цьому підмножині, які потім можуть бути складені як подальший, окремий етап.
Джорджіо

5

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

Ще одна відмінність полягає в тому, що шаблони шанують простори імен.


2

Шаблони IMHO, C ++ та C Макроси мали вирішити дві абсолютно різні проблеми. Оригінальна бібліотека стандартних шаблонів C ++ була механізмом чіткого роз'єднання класів контейнерів (масивів, пов'язаних списків тощо) від загальноприйнятих до них загальних функцій (наприклад, сортування та конкатенація). Наявність абстрактних уявлень про ефективні алгоритми та структури даних призводить до більш виразного коду, оскільки було значно менше здогадів щодо того, як найкраще реалізувати функцію, що працює на певній частині даних. Макроси C значно більше відповідали тому, що зазвичай можна побачити в макросах Ліспа, оскільки вони забезпечували спосіб "розширити" мову за допомогою вкладеного коду. Прикольне те, що стандартна бібліотека C ++ розширила функціональність шаблонів, щоб охопити переважну більшість, ніж те, для чого ми використовуємо #define в C.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.