Re[9]: Чем современные шаблоны лучше макросов? :)
От: ArtDenis Россия  
Дата: 24.01.22 12:45
Оценка: 11 (1)
Здравствуйте, ArtDenis, Вы писали:

AD>В русте макросы настолько круты, что могут своровать твой закрытый ключ при открытии проекта с макросом: https://github.com/lucky/bad_actor_poc


Раз уж шутка зашла...

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

https://docs.rs/cpp/latest/cpp/

  Вот как-то так
use cpp::cpp;

cpp!{{
    #include <stdio.h>
    #include <stdint.h>
}}

fn test_cpp(n: i32) {
    let cpp_sum = unsafe{cpp! ([n as "int32_t"] -> i32 as "int32_t" {
        int32_t sum = 0;
        for (int i = 0; i <= n; i++) {
            printf("%u\n", i);
            sum += i;
        }
        return sum;
    })};

    println!("cpp_sum={}", cpp_sum);
}

fn main() {
    test_cpp(42);
}

К сожалению, IDE не настолько круто, как макросы, так что никакой плюсовой раскраски синтаксиса нету ((
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[10]: Чем современные шаблоны лучше макросов? :)
От: удусекшл  
Дата: 24.01.22 15:27
Оценка: 9 (1) +1 :))
Здравствуйте, ArtDenis, Вы писали:

AD>В русте макросы настолько круты, что позволяют в коде делать инлайн-вставки кода на си и плюсах с возможностью отладки


AD>https://docs.rs/cpp/latest/cpp/


Ну наконец-то теперь на расте можно писать на плюсах
Re[5]: Чем современные шаблоны лучше макросов? :)
От: ArtDenis Россия  
Дата: 24.01.22 22:09
Оценка:
Здравствуйте, netch80, Вы писали:

N>Можно подробнее про расстреливание ног?


К сожалению потерял ссылку на презентацию, в которой чуть-ли не через слайд было "вы видите тут UB? а оно есть" (( Но вообще при аккуратном и простом использовании плюсовые корутины вполне себе нормальные. Главное — держать ухо (asan) востро
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re: Чем современные шаблоны лучше макросов? :)
От: Sm0ke Россия ksi
Дата: 30.03.22 06:57
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

Мой телег: dima_ksi
Напиши)

тема
Отредактировано 14.04.2022 16:03 Sm0ke . Предыдущая версия .
Re: Чем современные шаблоны лучше макросов? :)
От: fk0 Россия https://fk0.name
Дата: 30.03.22 11:17
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Помню, как в начале 90-х все пищали: "ах, шаблоны — это так круто и удобно, попрощаемся же навсегда с macro hell". Теперь мы уже много лет имеем template hell, но настолько привыкли считать, что шаблоны — это круто, что как-то даже стыдно думать об альтернативах. А ведь на обработку сотен-тысяч навороченных макросов требовались ничтожные, по нынешним временам, ресурсы, но сейчас обработка сравнимого количества шаблонов требует многократно бОльших ресурсов, а отлаживать их нередко бывает сложнее, чем макросы.


Ты сравниваешь несравнимое. Шаблоны вместе с системой типов образуют своеобразный _ДЕКЛАРАТИВНЫЙ_ язык программирования,
где компилятор самостоятельно ищет и применяет подходящее решение по заданным программистом правилам (описаниям
шаблонов, типов, функций...)

А макросы -- это просто подстановка текста.

Никакого hell ни там, ни там нет. Нужно просто понимать и уметь пользоваться.

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

ЕМ>Современные компиляторы используют предкомпиляцию шаблонов, но она, по сути, не столько ускоряет компиляцию вообще, сколько снижает тормоза, создаваемые множеством многоуровневых шаблонных конструкций. И все равно оптимизатору приходится как-то систематизировать функции, чтобы объединить те, что отличаются только типами, но при этом не оформлены ни в шаблоны, ни в перегрузки.


Шаблоны "предкомпилируются" только на уровне синтаксического разбора. Предкомпилировать их принципиально невозможно, т.к. конкретные типы и параметры шаблона обретают конкретный смысл только в момент использования шаблона. Этим часто пользуются, чтобы отложить компиляцию класса, например, к моменту первого использования шаблона. Что позволяет использовать в определении класса ещё не определённые типы, например.

ЕМ>Считается, что функциональный стиль использования шаблонов — это благо, но многие ли способны быстро разобраться в иерархии и взаимодействии шаблонов в какой-нибудь Boost? В конце концов, какая часть математиков интуитивно воспринимает факториал, как отображение множества целых чисел само на себя, или, на худой конец, как рекурсию, а не как последовательное (итеративное) произведение?


Прочитал, ничего не понял. Если понимать систему шаблонов, как я сказал выше, как декларативный ЯВУ, то достаточно быстро всё становится на места. Если интерпретировать по-привычке сверху-вниз, то наврное тяжело.

ЕМ>Вот будь вместо шаблонов приличный макропроцессор, в котором можно и параметры вызова разобрать, и циклические конструкции использовать, и за счет объединения с компилятором использовать в условиях типы, классы и их свойства — какие у шаблонов остались бы преимущества?


Все преимущества остались бы. Так как шаблоны -- это ни разу не подстановка текста. Шаблоны исторически выросли из макропроцессора, да. Но сейчас уже совсем другие времена...

В обычном макропроцессоре вполне можно использовать циклические конструкции (единственное что -- глубина рекурсии принципиально ограничена, хотя может быть достаточно глубокой, с шаблонами, кстати, та же история), хотя и нетривиальным способом. Да, пожалуй это трюк который следовало изобрести (первые публикации где-то 2011 год, если не позже, а существует макропроцессор с 80-х). Идея в том, что во-первых нужно многократное раскрытие текста макроса (пропорционально глубине рекурсии), что осуществляется при передаче текста аргументом в другой макрос. Во-вторых, рекурсия искусственно прерывается только когда препроцессор в процессе раскрытия макроса наталкивается на макрос с тем же именем, что раскрываемый сейчас. Соответственно можно устроить пинг-понг macro1 -> macro2 -> macro1 -> macro2... где многократное разворачивание последовательности выполняется внешним псевдо-рекурсивным макросом вызванным многократно, много раз (лимит не нужен, можно вызвать с глубиной 999, например, и если на 300-м разе всё раскрылось, на последующих итерациях текст просто останется неизменным). Пример: https://github.com/swansontec/map-macro

Что значит "параметры вызова разобрать"?

Разница шаблонов с макропроцессором в том, что макропроцессор не понимает смысла в тексте который он подставляет, а шаблоны связаны с грамматикой и системой типов языка. И это не подстановка. Шаблон генерирует новую сущность в терминах самого языка.
Re[4]: Чем современные шаблоны лучше макросов? :)
От: fk0 Россия https://fk0.name
Дата: 30.03.22 11:36
Оценка:
Здравствуйте, Sm0ke, Вы писали:


S>Помнится в колледже я писал библиотеку работы с матрицей, узнал даже про перегрузку операторов, ведь мне нужно было умножение.

S>Про шаблоны не знал, да вроде и не было ещё тогда их.
S>Тогда я думал какой взять тип элемента float или double. И сделал typedef.
S>Потом появилась идея заменить typedef макросом для типа и префикса перед инклюдом библиотеки, чтобы можно было одновременно пользоваться разными матрицами и не писать сто раз одно и тоже. Есть #define, есть #undef — так это можно было сделать. Не очень красиво, зато работает.

S>Когда я узнал про шаблоны и стал их осваивать сам (на уроке про них тогда не рассказывали), то понял — вот оно. Не надо инклюдить несколько раз один файл, а просто подставить нужный тип элемента и всё.


S>И не городить огород инклюдов с передифайнами. 1 строчка на дифайн префикса, 1 строчка на дифайн типа, 1 строчка на каждый инклюд. А если надо больше параметров-типов? И не забыть про андифайны после инклюда!


Так а что мешает сделать макрос, которому передаётся тип, а дальше он всё делает: генерирует фунцкии и структуры данных с нужным типом и всё такое прочее... И не городить огород. Это -- типовое решение, из него и выросли шаблоны.


S>Вы предлагаете вернуться к макросам? Как вы решите такую задачу?


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

Идея такая:

1) существуют какие-то конкретные специфичные типы, весь код для работы с ними дробится на
элементарные операции (из буквально пары строчек кода) и описывается в отдельных функциях
(можно сразу декларировать inline static для удобства);

2) для каждого типа существует что-то вроде "таблицы виртуальных функций", только она не таскается
в самом типе и не вычисляется в рантайме -- это чисто статическая, константная, определяемая в момент
компиляции вещь: в таблице (структура с именованными членами -- указателями на функции) функции из пункта 1;

3) функции из п.1 и сам п.2 могут генерироваться макросом (т.к. их нужно параметризовать конкретным
типом, не известным в момент описания функции), параметром макроса является тип, например;

4) существует аналог std::any<T>, который представляет обобщённый тип (аллоцирует память в своём теле
или динамически, предоставляет ссылку на структуру указателей на функции оперирующих над конкретным
типом хранимым в данном обобщённом типе;

5) существует набор функций выполняемых над обобщённым типом -- фактически прокси, вызывающие операции
из структуры специфичной для данного типа из п.1, с помощью структуры из п.2, ссылка на которую
хранится в п.4.

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

Немного муторно, шаблоны удобней, да.


S>Макросы помогут скажем сделать умножение двух матриц с разными типами элемента? Если да, то покажите как.

S>Да хоть на любой другой задаче...

В целом получится говно... согласен.
Re[7]: Чем современные шаблоны лучше макросов? :)
От: fk0 Россия https://fk0.name
Дата: 30.03.22 11:39
Оценка:
Здравствуйте, удусекшл, Вы писали:

ЕМ>>>Я предлагаю сравнить функциональнось и удобство современных шаблонов с адекватно реализованными макросами. Если Вы никогда не видели макросов, отличных от сишных, то Вам нет смысла и сравнивать.


S>>Конкретные примеры можно? Я же не буду искать все реализации макросов вообще во всех языках ...


У>Я так понимаю, что он хочет что-то типа доступа к AST, чтобы можно было писать простые функции с циклами, набивающие AST дополнительными штуками, и чтобы эти функции писались на том же C++ и исполнялись во время компиляции. Что-то такое есть в C# вроде.


Или в Rust. На мой взгляд такие "макросы" только хуже шаблонов в C++. На них может быть легко сделать какие-то отдельные трюки, которые не сделать в C++, но в целом любая более-менее сложная задача решаемая в шаблонах на C++ с такими императивными макросами заканчивается тем, что нужно для решения задачи вначале на языке этого макропроцессора написать какой-то интерпретатор своего языка, в терминах которого уже и решать задачу. Короче говоря -- ещё сложней. Шаблоны в C++ более-менее хорошо предназначены для решения прикладных задач, а интроспекция в C# и макросы в Rust -- позволяют с одной стороны что угодно, а с другой что-то сложное сделать примерно так же просто, как программировать на ассемблере. Т.е. можно, но оно того не стоит.
Re[10]: Чем современные шаблоны лучше макросов? :)
От: fk0 Россия https://fk0.name
Дата: 30.03.22 11:46
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, ArtDenis, Вы писали:


AD>>Можно пример как это может выглядеть?


ЕМ>Ну вот шаблоны type traits реализованы так, что для определенных типов они явно специализированы с нужными значениями констант, а для остальных выбираются варианты по умолчанию. То есть, это устроено задом наперед, при этом установка и извлечение значений констант работает, по сути, на побочных явлениях. Если бы в языке был способ "интеллектуального" раскрытия хоть макросов, хоть шаблонов, то можно было бы проверять заданный параметром тип обычными условными конструкциями вроде #ifdef.


То получилось бы полное говно. Потому, что специализацию шаблона для нового типа T легко взять и дописать. В сторонке где-то. А твой #ifdef -- получается нужно заранее знать наперёд все возможные типы. И дописать нельзя.

Такое уже сделали в Rust. Нет, сама идея трейтов у них осталась, т.е. с твоей точки зрения всё задом наперёд тоже. Но у них ничего кроме трейтов нет, у них невозможны вычисления зависимые от типа. Т.е. в C++ можно на основе каких-то наперёд не известных свойств неизвесного наперёд типа что-то расчитать и получить новые типы, или константы, или функции и т.п. Зависимые от свойств типа. Вычисляемых в момент компиляции. То в Rust получается нужно заранее для каждого типа наперёд написать Traits<T> с нужными свойствами. Когда тип библиотечный -- фигня вопрос. Когда тип свой -- уже морока. А когда тип сам по себе чужой и тоже наперёд заранее неизвестный -- пиши пропало. Кто-то другой должен это всё расписать, а он ни сном, ни духом, что оно такое нужно. Для каких-то библиотечных трейтов так можно сделать, но в целом когда соединяются множество независимых компонентов -- возникнут проблемы.

ЕМ>А если бы в языке изначально были условные конструкции, работающие на уровне компилятора (вроде __if_exists в MSVC), то из этого естественным образом вытекало бы и наличие встроенных предикатов для типов, переменных, функций, шаблонов и прочего. Вот тогда было бы одновременно и удобно, и красиво, и в реализации недорого.


Ну так эти конструкции и есть в шаблонах. Просто с твоей точки зрения оно "вывернуто наизнанку". Но если вывернуть как хочешь ты получится гораздо хуже по другим причинам.
Re[14]: Чем современные шаблоны лучше макросов? :)
От: fk0 Россия https://fk0.name
Дата: 30.03.22 12:23
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, ArtDenis, Вы писали:


AD>>Не получается. Хочу примеры


ЕМ>Ну вот, например, примитивно, на псевдокоде, максимально приближенном к C/C++:


ЕМ>
ЕМ>define is_signed (expr) {

ЕМ>  return (tostring (typeof (expr)) == "char" || tostring (typeof (expr)) == "int" || tostring (typeof (expr)) == "long" || tostring (typeof (expr)) == "float" || tostring (typeof (expr)) == "double");

ЕМ>}
ЕМ>


О чём я и говорил -- тебе нужно все типы знать наперёд. И char не обязательно signed. А "signed char" вот стопроцентно signed, а у тебя в списке отсутствует. Как и "short", и "long long".

ЕМ>Хотя и это тоже извращение. Для таких вещей любой вменяемый компилятор обязан иметь встроенные предикаты.


std::is_signed...
Re[10]: Чем современные шаблоны лучше макросов? :)
От: fk0 Россия https://fk0.name
Дата: 30.03.22 12:27
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>Здравствуйте, ArtDenis, Вы писали:


AD>>В русте макросы настолько круты, что могут своровать твой закрытый ключ при открытии проекта с макросом: https://github.com/lucky/bad_actor_poc


AD>Раз уж шутка зашла...


AD>В русте макросы настолько круты, что позволяют в коде делать инлайн-вставки кода на си и плюсах с возможностью отладки


Это было в тикле (tcl) 20 лет тому назад...
Re[7]: Чем современные шаблоны лучше макросов? :)
От: fk0 Россия https://fk0.name
Дата: 30.03.22 12:31
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, Sm0ke, Вы писали:


S>>Конкретные примеры можно?


ЕМ>Ну вот один из простейших — у Turbo Assembler (а ему навеяно макроассемблером Macro-11).


ЕМ>Смысл в том, чтобы в макрос можно было включить и условия, и повторы, и преобразования параметров.


Повторы в макросах возможны. Условия тоже в какой-то мере. По крайней мере макрос может или детектировать число аргументов, или что остаток аргументов не пуст, или детектировать некий условный маркер конца. В принципе всё что кроме подсчёта числа аргументов (известным паттерном, все наверное знают) делается через попытку подстановки (не)пустого значения между одним именем макроса и круглыми скобками. Известная же наверное вещь, интуитивно же понятно.
Re[7]: Чем современные шаблоны лучше макросов? :)
От: fk0 Россия https://fk0.name
Дата: 30.03.22 12:32
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, Sm0ke, Вы писали:


S>>Конкретные примеры можно?


ЕМ>Ну вот один из простейших — у Turbo Assembler (а ему навеяно макроассемблером Macro-11).


ЕМ>Смысл в том, чтобы в макрос можно было включить и условия, и повторы, и преобразования параметров.


А что такое вот это, "преобразование параметров"? Откуда и куда их преобразовать нужно?
Re[2]: Чем современные шаблоны лучше макросов? :)
От: fk0 Россия https://fk0.name
Дата: 30.03.22 12:33
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, Евгений Музыченко, Вы писали:


ЕМ>>Вот будь вместо шаблонов приличный макропроцессор, в котором можно и параметры вызова разобрать, и циклические конструкции использовать, и за счет объединения с компилятором использовать в условиях типы, классы и их свойства — какие у шаблонов остались бы преимущества?


AG>Трудно сказать, что было бы, если бы было то, чего нет.


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

AG>С нынешними макро так не работает.
AG>Непонятно, работало бы ли это с гипотетическим макро процессором.

С макросами gdb с -g3 тоже в теории может. Но проблема же в том, что макросы, и шаблоны, могут не только простую подстановку, например, типа делать, но и более сложные вещи. В итоге они управляют генерацией кода, и код может получиться совсем не такой как ожидает программист, и типы данных, да вообще всё. Там уже не до пошаговой отладки будет -- и это в любом более-менее сложном случае.
Re[3]: Чем современные шаблоны лучше макросов? :)
От: fk0 Россия https://fk0.name
Дата: 30.03.22 12:39
Оценка: +1
Здравствуйте, netch80, Вы писали:

N>Я вот тут наблюдаю один вполне себе серьёзный важный проект. Уровень — C с классами. Люди — умеют свою тематику, серьёзный телеком. Геттер вида string getX() { return x_; } где "string x_"; — норма. А рядом вдруг uint8& getY() { return y_; } Const и noexcept, понятно, у обоих не стоит. Впрочем, поскольку это всё в конфигурировании (а не в hot path), всем пофиг.

N>Реально, "широкие народные массы" сейчас в районе C++11, не сильно выше.

Зато на работу пойдёшь трудоустраиваться, сразу спрашивают: "Cколько у вас лет опыта на C++23?"..
Re[2]: Чем современные шаблоны лучше макросов? :)
От: fk0 Россия https://fk0.name
Дата: 30.03.22 12:47
Оценка:
Здравствуйте, reversecode, Вы писали:

R>
R>#define MAX(x,y) (x)>(y)?(x):(y)

R>int val = 1;
R>int get_val()
R>{
R>   return val++;
R>}

R>int main()
R>{
R>#ifdef MAX
R>  printf("max %d\n",MAX(get_val(),get_val()));
R>#else
R>  printf("max %d\n",std::max(get_val(),get_val()));
R>#endif
R>}
R>


Я так тоже умею: https://coliru.stacked-crooked.com/a/ae49e3828093825c
Re: Чем современные шаблоны лучше макросов? :)
От: rg45 СССР  
Дата: 03.04.22 20:48
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Вот будь вместо шаблонов приличный макропроцессор, в котором можно и параметры вызова разобрать, и циклические конструкции использовать, и за счет объединения с компилятором использовать в условиях типы, классы и их свойства — какие у шаблонов остались бы преимущества?


Я не очень понимаю, что делает в профльном форуме эта околонаучная фантастика? Как можно всерьез обсуждать то, чего нет?
--
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.