Как стать автором
Обновить

Комментарии 15

Примечательно то, что на данный момент в плюсах нет способа устранить этот копипаст. 

"Можно ли реализовать обобщенную арифметику для enum?" - можно https://godbolt.org/z/Yee376o9Y

"Нужно ли это авторам libc++?" - нет.

Хорошее замечание, спасибо.
Действительно, можно было бы решить поставленную в статье проблему следующим образом: godbolt.org (чуть модифицированное ваше решение). Но в коде стандартной библиотеки, я согласен с вами, такое неоправданно.

чуть модифицированное ваше решение

Не очень я понял смысла этой великой модификации. Ну, то что переехать функция должна была в `namespace std` - это было понятно из контекста, а вот что даёт анонимный namespace чёт хоть убейте вдупить не могу)

Если мы оставим шаблонную реализацию битовых операций в namespace std, то using namespace std в пользовательском коде подтянет их в пользовательский неймспейс — загрязнит его реализациями битовых операций для пользовательских enumов.

Поздравляю, теперь в каждом TU, который использует эти операторы, будет их копия. Не нужно использовать anonymous namespace в заголовках.

Не понял, почему нельзя через наследование шаблонного класса, или через шаблонный класс параметризуемый шаблоном собственно реализации конечного класса с битами. И так и эдак вывернуть можно при желании. И всяко это будет лучше, чем виртуальные функции которые неизвестно девиртуализируются ли при компиляции.

По мне в ряде случаев это спорная функциональность.

Например, при использовании POD вдруг могут появиться новые поля, размер данных поплывёт.

Даже в приведённых примерах: экземпляр а-ля-Shape допустимо создавать (функции определяем). В случае interface Shape уже будут вопли компилятора. Т.е. нужно будет изучать, а что такое "interface" (это то же кастомный код, не библиотечный)? А насколько хорошо он написан? В общем, напоминает переопределение #define sizeof(x) ... - а дальше отладчик это наше всё :(((

Метаклассы предлагают программисту контракт: какие поля они добавляют, какую функциональность реализуют. Применяя метакласс к своему классу, программист должен осознавать вносимые им изменения.
В приведенных примерах interface Shape не компилируется, потому что статья описывает функциональность, которая только предложена для включения в стандарт, но еще не принята и не реализована.
Такие метаклассы как interface вполне могут стать частью стандартной библиотеки.

Я не понял, а концепты для этого нельзя применять?

  • пишем шаблоны всяких внешних функций (тех же операторов), принимающих не произвольные типы, а экземпляры концепта

  • объявляем интересующие нас типы экземплярами концепта

  • и вуаля?

https://gcc.godbolt.org/z/zs4f1G8WW

Концепты доступны в C++20, а концепты-для-бедных в виде обычного SFINAE - ещё в C++11, если не 03.

https://gcc.godbolt.org/z/oMc5G4v7x

Если некий класс должен удовлетворять сразу нескольким концептам - ну, например, value, ordered и aggregate, - тогда как быть?

  • синтаксически

  • семантически

Каждое из преобразований синтаксического дерева структуры допишет туда всякие служебные члены, а потом следующее преобразование должно разбираться - вот это было в исходном коде, а это предыдущее добавило?

То есть, определения этих плагинов компилятора надо писать с оглядкой на возможные комбинации?

Либо же комбинирование синтаксически невозможно, поэтому если кто хочет, то пусть пишет комбинированные плагины по своему вкусу.
Будут там value_ordered, value_aggregate, value_aggregate_ordered, ordered_aggregate_value... ?

Ещё одна точка сопротивления: время компиляции.
Компилятор всё больше превращается в интерпретатор компилятора.
Причём ему придётся загружать этот код для интерпретации в каждой единице трансляции независимо: а вдруг там от дефайнов или скоупа что-нибудь зависит!

В отличие от честных плагинов...
Даже если те не скомпилированы в динамическую библиотеку, а хранятся в каком-то исходном коде на каком-то языке. Один раз оттранслировать в машинное представление и потом быстренько грузить.

Конечно, главный довод ЗА - это уменьшить количество языков.
Сейчас исходники на C++ содержат два языка: макропроцессора и собственно C++. На Qt - ещё добавляется один язык кодогенератора.
И нужно постараться, чтоб они не конфликтовали (а макросы, как мы знаем, отлично конфликтуют, особенно, с шаблонами).
Но может быть, не надо упихивать всё в один язык и один исходник?
Пусть в проекте будет два исходника - один с пользовательскими плагинами компилятора, другой - с кастомизированным C++?

Вот ведь как складывается история... С++ начинался с попытки слегка улучшить Си, добавить классы, тонкий синтаксический сахар над структурами и функиями. А сейчас приходят (но еще не пришли окончательно) к синтаксическим макросам, по сути плагинам к компилятору. Правда, выглядит все это до крайности криво, именно из-за эволюционного развития языка. Интересно, дойдет ли язык в этой эволюции до простой кодогенерации любых произвольных фрагментов кода? А до использования внешних языков для доступа к синтаксическому дереву (по типу связки HTML + JavaScript)?

Всё это на С++ уже реализуемо, называется template.
Енам не может быть template, но зато можно сделать шаблон оператора | & и т.д. для них с необходимыми ограничениями на аргументы. Но никому это не нужно

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории