Це почалося як питання SO, але я зрозумів, що це досить нетрадиційно, і, виходячи з фактичного опису на веб-сайтах, він може бути краще підходить для програмістів.se, оскільки питання має велику концептуальну вагу.
Я вивчав кланг LibTooling, і це дуже потужний інструмент, здатний викрити всю " солону крупу " коду по-дружньому, тобто семантично , і не здогадуючись. Якщо clang може скласти ваш код, тоді clang певний щодо семантики кожного окремого символу всередині цього коду.
Тепер дозвольте мені на мить відступити.
Існує багато практичних проблем, які виникають, коли людина займається метапрограмуванням шаблонів на C ++ (і особливо, коли заходить за рамки шаблонів на територію розумних, хоча і жахливих макросів). Якщо чесно, для багатьох програмістів, в тому числі і я, багато звичайних способів використання шаблонів теж дещо жахливі.
Думаю, хорошим прикладом можуть бути рядки часу компіляції . Це питання, якому зараз вже понад рік, але зрозуміло, що C ++ на даний момент не спрощує простого смертного. Незважаючи на те, що ці параметри недостатньо для того, щоб викликати у мене нудоту, вона все ж залишає мене невпевненою в тому, що я можу створити магічний, максимально ефективний машинний код, щоб відповідати будь-яким фантазійним додаткам для мого програмного забезпечення.
Я маю на увазі, визнаймо, люди, струнні досить прості та основні. Деякі з нас просто хочуть зручного способу випромінювання машинного коду, який має певні рядки, «запечені» значно більше, ніж ми отримуємо при простому кодуванні. У нашому C ++ коді.
Введіть clang та LibTooling, який розкриває абстрактне синтаксичне дерево (AST) вихідного коду та дозволяє простому користувальницькій програмі C ++ правильно та надійно маніпулювати необробленим вихідним кодом (використовуючи Rewriter
) поряд із багатою семантичною об'єктно-орієнтованою моделлю всього в AST. З ним обробляється багато речей. Він знає про розширення макросів і дозволяє вам слідкувати за цими ланцюгами. Так, я кажу про перетворення вихідного коду або переклад.
Моя основна теза тут полягає в тому, що кланг тепер дозволяє нам створювати виконувані файли, які самі можуть функціонувати як ідеальні спеціальні етапи препроцесора для нашого програмного забезпечення C ++, і ми можемо реалізувати ці етапи метапрограмування за допомогою C ++. Нас просто обмежує той факт, що цей етап повинен приймати вхід, який є дійсним кодом C ++, і виробляти як вихід більш дійсний код C ++. Плюс будь-які інші обмеження, застосовані вашою системою збирання.
Вхід повинен бути принаймні дуже близьким до дійсного коду C ++, тому що, нарешті, clang - це перехідник компілятора, і ми просто роздивляємось та творчим з його API. Я не знаю, чи є якесь положення про можливість визначення нового синтаксису для використання, але явно ми повинні розробити способи його правильного розбору та додати його до проекту clang, щоб це зробити. Очікувати більше - це щось у проекті "clang", що виходить за межі сфери.
Не проблема. Я б міг уявити, що деякі неопераційні макро функції можуть впоратися з цим завданням.
Ще один спосіб розглянути те, що я описую, - це реалізувати конструкції метапрограмування за допомогою програми C ++, маніпулюючи AST нашим вихідним кодом (завдяки кланг та його API), а не реалізовувати їх, використовуючи більш обмежені інструменти, доступні в самій мові. Це також має чіткі переваги для компіляції (шаблони-важкі заголовки сповільнюють компіляцію пропорційно тому, як часто ви їх використовуєте. Багато складених матеріалів потім ретельно узгоджується і викидається лінкером).
Це, однак, пов'язано з тим, щоб запровадити додатковий крок або два в процесі збирання, а також вимагати написання деякого (правда,) дещо більш детального програмного забезпечення (але принаймні це просто C ++) під час виконання нашого інструменту .
Це не вся картина. Я майже впевнений, що існує набагато більший простір функціональності, який можна отримати від створення коду, що є надзвичайно складним або неможливим за допомогою основних мовних особливостей. У C ++ ви можете написати шаблон або макрос або шалену комбінацію обох, але в інструменті clang ви можете змінювати класи та функції будь-яким способом, якого ви можете досягти за допомогою C ++ під час виконання , маючи повний доступ до смислового вмісту, крім шаблону та макросів та всього іншого.
Отже, мені цікаво, чому всі вже не роблять цього. Це те, що ця функція від clang є такою новою, і ніхто не знайомий з величезною ієрархією класів AST? Це не може бути.
Можливо, я трохи недооцінюю складність цього, але робити "маніпуляцію з рядком під час компіляції" інструментом "Кланг" майже кримінально просто. Це багатослівно, але шалено прямо. Все, що потрібно, - це купа макрофункціональних функцій, які відображають реальні std::string
операції. Плагін clang реалізує це, отримуючи всі відповідні неопераційні виклики макрокоманд і виконує операції з рядками. Потім цей інструмент вставляється як частина процесу збирання. Під час складання ці неопераційні виклики макро-функцій автоматично оцінюються в їхніх результатах, а потім вставляються назад як звичайні старі рядки часу компіляції в програму. Потім програма може бути складена як завжди. Насправді ця отримана програма також набагато більш портативна, як результат, не вимагає нового модного компілятора, що підтримує C ++ 11.