LINUX.ORG.RU

Вычисления на этапе компиляции, DSL и C++20

 , , , ,


0

3

Читал тут С++20 на подходе! Встреча в Рапперсвил-Йона и последние пункты про constexpr заинтересовали

Ещё одно занятное изменение, которое рассматривается для приёма в C++20 — это constexpr! функции.

Такие функции обязаны выполняться только на этапе компиляции, любая попытка использовать их в runtime приведёт к ошибке компиляции. Это одно из изменений необходимых для рефлексии в C++

...

Множество языков программирования в данный момент компилируют/транслируют регулярные выражения ещё перед запуском программы. Таким образом, когда программа стартует, все регулярные выражения уже преобразованы в соптимизированный конечный автомат.

В C++ это не так:

bool is_valid_mail(std::string_view mail) {
    static const std::regex mail_regex(R"((?:(?:[^<>()\[\].,;:\s@\"]+(?:\.[^<>()\[\].,;:\s@\"]+)*)|\".+\")@(?:(?:[^<>()\[\].,;:\s@\"]+\.)+[^<>()\[\].,;:\s@\"]{2,}))");

    return std::regex_match(
        std::cbegin(mail),
        std::cend(mail),
        mail_regex
    );
}
В коде выше конечный автомат из регулярного выражения будет строится при первом заходе в функцию is_valid_mail(). Это долгая операция, которая в добавок будет выполняться в критической секции.

С готовящимися новинками для constexpr вычислений (constexpr new, is_constexpr_evaluated() и др.) можно будет в C++ делать множество вещей на этапе компиляции, в том числе можно будет сделать constexpr std::regex.

С constexpr std::regex конечный автомат для функции is_valid_mail() построится ещё на этапе компиляции.

Непонятно, в этом «множестве других языков программирования» сделана какая-то специальная поддержка регулярных выражений, или же они научились на этапе компиляции разбирать и оптимизировать произвольные DSL из строки (регэкспы это тоже DSL кмк)? С помощью каких механизмов это делается? Я вспоминаю синтаксические макросы и зависимые типы, но в плюсах явно ни то, ни другое, тогда что? Какие будут ограничения у новых constexpr! по сравнению с другими подходами?

Помню, что в Rust на этапе компиляции разбирается строка формата для printf, выглядит близкой задачей. В общем если кто может нормально осветить тему компайл-тайм вычислений, то пожалуйте в тред

сумасшедшие извращенцы

вычисления на этапе компиляции надо делать так:

пишется программка, собирается, вычисляет, результаты заносит в header, либо сочиняет код, ибо порождает бинарники для линковки(так как раз можно regex «оптимизировать», собрав его по настоящему - и не только regex).

то что они пытаются делать - вообще-то делается в скриптах. там как раз прямо в ходе разбора исходников вычисляют.

i36_zubov ()
Ответ на: комментарий от i36_zubov

Так делали 30 лет назад, сейчас стараются делать иначе.

Внешняя программа для кодогенерации это всегда плохая интероперабельность с целевым языком, да и генерировать код одного ЯП на другом — то ещё удовольствие.

Crocodoom ★★ ()

Помню, что в Rust на этапе компиляции разбирается строка формата для printf, выглядит близкой задачей

Не совсем. println это макрос. Для других макросов управляемых строками там тоже в компайл тайм собирается. Для функций - нет.

Aswed ★★★★★ ()

Вычисления на этапе компиляции

Еще часик можно накинуть ко времени компиляции проекта, походу.

А можно что-нибудь придумать, что бы такое делалось только для релизной конфигурации, а дебаг собирался быстро, но без этого компайл-тайм? Есть такие задумки вообще в среде С++-сников на острие прогресса?

Deleted ()
Ответ на: комментарий от i36_zubov

ишется программка, собирается, вычисляет, результаты заносит в header

Что за подходы 20го века? Если можно написать понятный читаемый код в пару строк и чтобы компилятор все сделал как надо, то так и надо делать. Все то о чем вы говорите - это костыли закрывающие слабость AI и кривизны дизайна изначальных версий языка/фреймворка.

Dudraug ★★★★★ ()
Ответ на: комментарий от Deleted

Еще часик можно накинуть ко времени компиляции проекта, походу.

Не хочешь долго собирать, то

1) купи мощный ксеон с 100500 ядрами и ssd для сборки (можно шарить между довольно большой командой разработчиков).

2) не используй регэкспы, а пиши конечный автомат вручную. Это конечно займет чуть больше человекочасов и увеличит размер кода(а значит и потенциально место обитания багов).

Dudraug ★★★★★ ()
Ответ на: комментарий от i36_zubov

сейчас
прочих хацкелей

Что касается хацкеля, это происходит примерно такое же время, сколько С++ живет.

А раст конечно молодец.

Но для меня это оффтоп. Я с практической точки зрения, в контексте C++ интересуюсь

Deleted ()

Такие функции обязаны выполняться только на этапе компиляции, любая попытка использовать их в runtime приведёт к ошибке компиляции. Это одно из изменений необходимых для рефлексии в C++

Странный подход. А если мне одна и та же функция нужна и на этапе компиляции и на этапе выполнения, я должен буду её копипастить? И все функции, которые она использует? Логичней было бы сделать наоборот.

Legioner ★★★★★ ()
Ответ на: комментарий от Legioner

А если мне одна и та же функция нужна и на этапе компиляции и на этапе выполнения, я должен буду её копипастить?

Так ведь есть же обычный constexpr. Он работает и там, и там.

Кроме того, вот что еще обсуждается: https://habr.com/company/yandex/blog/413719/#comment_18850925

eao197 ★★★★★ ()
Ответ на: комментарий от Crocodoom

Так делали 30 лет назад, сейчас стараются делать иначе

И всё равно получается хуже, чем было 50 лет назад в лиспе.

в этом «множестве других языков программирования» сделана какая-то специальная поддержка регулярных выражений

Видимо речь идёт о языках, где регулярки являются самостоятельным типом данных со своими литералами.

no-such-file ★★★★★ ()
Ответ на: комментарий от no-such-file

И всё равно получается хуже, чем было 50 лет назад в лиспе.

Ну и где сейчас этот Лисп? Лол.

Там за 50 лет даже синтаксиса не получилось сделать.

anonymous ()
Ответ на: комментарий от Legioner

Вот здесь начиная с со слайда №13 рассматриваются разные ограничения constexpr и разбирается как сделать так, чтобы constexpr вызывался только в compile-time. Только там все это через хаки делается, а в C++20 могут официально одобренный способ завезти.

ЗЫ. Это доклад с CppCon-2015. Наверняка где-то и видео есть, может там объясняют, зачем это нужно.

eao197 ★★★★★ ()

Не так уж и давно сам Страуструп встревожился сложностью цепепе - http://open-std.org/JTC1/SC22/WG21/docs/papers/2018/p0977r0.pdf

И вот теперь, когда в цепепе можно будет наконец-то сгенерить строчку в компайл-тайме, как чувствует себя Страуструп? Теперь то цепепе встал на путь правильный, или ещё надо лет 12 всё тщательно обдумать?

Полагаю, что теперь то желающих поизучать цепепе возрастёт. Ну и какой теперь то уж стартап без цепепе?

azelipupenko ()
Ответ на: комментарий от anonymous

Ну и где сейчас этот Лисп? Лол.

Лисп сейчас тут http://www.lispworks.com/ или тут https://racket-lang.org/ :-) Лол :-)

Там за 50 лет даже синтаксиса не получилось сделать.

Так Лисп он же без синтаксиса ведь :-) Ты разве не знал? :-) Это же тебе не цепепе :-)

azelipupenko ()
Ответ на: комментарий от Deleted

О, да неужели. Несколько поколений ЯП родились и сдохли, а в С++ скоро появится рефлексия. Сила!

В цепепе ещё и метапрограммирование есть. На шаблонах. Сила! А ты писал когда-нибудь метапрограммы на шаблонах цепепе, не считая вычисления ряда Фибоначчи?

azelipupenko ()
Ответ на: комментарий от Deleted

А раст конечно молодец.

Но для меня это оффтоп. Я с практической точки зрения, в контексте C++ интересуюсь

Ocaml, Rust и (вероятно) Haskell сделают тебя лучше, на каком бы языке ты не программировал.

tailgunner ★★★★★ ()
Последнее исправление: tailgunner (всего исправлений: 1)

они научились на этапе компиляции разбирать и оптимизировать произвольные DSL из строки (регэкспы это тоже DSL кмк)? С помощью каких механизмов это делается?

Может, я неправильно понял вопрос, но вычисление constexpr делается интерпретацией Си++-кода.

tailgunner ★★★★★ ()
Ответ на: комментарий от tailgunner

сделают тебя лучше

Это не мне говори) Я хоть и не гуру, но интересовался. Курс по Ocaml пройден в позапрошлом году, Rust потихоньку юзаю, по Haskell валяются книжки Душкина (сойдет :) и подшивка «Функционального программирования» из студенческих лет ;)

Deleted ()
Ответ на: комментарий от tailgunner

А раст конечно молодец.
Но для меня это оффтоп

Я имел ввиду, что меня сейчас очень сильно анноит скорость сборки проекта C++ , и словами о расте тут не поможешь никак. Вот если бы придумали какой-нибудь JIT или еще что-нибудь, что бы дебаг собирался быстрее раз в 100. Пусть бы выполнялся чуть медленнее, но можно было бы отдельные тесты гонять

Deleted ()
Ответ на: комментарий от azelipupenko

Не так уж и давно сам Страуструп встревожился сложностью цепепе
Полагаю, что теперь то желающих поизучать цепепе возрастёт. Ну и какой теперь то уж стартап без цепепе?

Ирония да.

На самом деле, любой язык - тлен, главное - предметка. Куда относятся и вопросы производительности, и расширяемости, кстати. А уж узкоспециализированное что-то вообще кайф. Я поэтому за C++ не топлю, хоть и люблю и использую.

Deleted ()