Compile time рефлексия С++26 не имеет ничего общего с рантайм рефлексией UE.
Первая нужна для генерации кода во время компиляции и обход полей класса "по порядку" не зная ничего о самом классе. Вторая для создания объектов "на лету" по их строковому описанию.
С++26 рефлексия полезна для замены сишных макросов и всякой ерунды, вроде обобщенного кода для сериализации/десериализации.
Абсолютно бессмысленно в рантайме, ведь после компиляции сгенерированные типы точно также ничего о себе не знают в рантайме.
Причин несколько, но все они сводятся к одному: "чертова физика, бессердечная ты с*ка".
Доступ к L1 кэшу должен быть мгновенный (1-5 тактов), иначе теряется смысл и можно ходить в память. Но чтобы доступ был мгновенный, нужно:
Иметь быстрый lookup (при увеличении размера - увеличивается время на поиск очевидно
Иметь физически короткие контакты (дорожки). Иначе на частотах 4-5 ГГц, сигнал тупо не дойдёт за 1 такт, а это увеличивает latency. Речь о расстоянии в миллиметры и меньше, но можете сами посчитать сколько сигнал успеет пройти на такой частоте.
Иметь разумное энергопотребление, и что важнее, тепловыделение, т.е. нельзя располагать память слишком плотно. Косвенно опять же связано с размером самой дорожки.
Плюс всё это не должно стоить слишком дорого. Некоторое время, на заре времён, экспериментировали с размерами L1 кэша, его ассоциативностью и прочим. Выяснилось, что 16кб - слишком мало. 64кб - слишком долгий доступ и греется зараза.
32-48 кб - оптимально. Так и повелось. По крайней мере для x86_64. Впрочем, и сейчас есть чипы с бОльшим количеством L1 кэша, у тех же Apple M-серии вроде что-то порядка 192 КБ. Если честно не вникал как они этого достигли, но вон чатгпт говорит что latency там все равно большой, физически архитектура сильно сложнее получилась, а компенсируется latency большим пайплайном исполнения.
если ваш шебанг вдруг окажется ... #!/bin/sh вместо #!/bin/bash
Ну... если вы пишете bash-скрипт, то и shebang надо указывать правильный)
А ещё нередко встречается busybox в эмбеде, там тоже ash
Да, это возможный сценарий, но том эмбеде, в котором нет bash, на шелл-скриптах особо и не пишут ничего большого.
А ещё нередко в прод ставят контейнеры, в которых до предела минимизируют окружение.
В таких контейнерах никогда шелл-скрипты и не запускают. В них упаковывают одну программу на каком-нибудь go и её же и запускают.
А иногда даже бывает нужна совместимость с zsh
Проще написать две версии скриптов автокомплита, т.к. у zsh вообще своя магия для комплита.
Это не всегда решает автор скрипта
Автору ничего решать и не надо) Автор пишет в шебанге условный #!/usr/bin/env bash, а остальное - проблемы пользователя)
Я не буду отрицать - сценарии где bash недоступен - существуют. Я лишь хочу сказать, что я с такими не сталкивался за 20 лет ни разу. Да, наверное в initramfs нет bash, но если мне придётся там много скриптовать - я просто его туда упакую.
именно поэтому доступ к нему требует координации через протокол когерентности
Доступ к L3 не требует никакой координации. Но L3 выступает той самой шиной, по которой эта когерентность обеспечивается, да. Но когерентность обеспечивается между L1, L2 кэшами, при этом сам L3 кэш точно такая же коробка с игрушками. С той лишь разницей, что рядом стоит дядя с журналом и записывает кто и что оттуда взял/положил.
Однажды на одном из собеседований, меня спросили, ключевые отличия между new и malloc, вопрос интересный, так что я также хотел бы затронуть его в этой статье.
Ключевое отличие new от malloc в том, что new начинает object lifetime, а malloc нет. И reinterpret_cast тоже не начинает. Рекомендую копнуть в такие чудесные вещи как std::launder и std::start_lifetime_as.
Также new, помимо прочего, гарантирует корректное выравнивание для аллоцируемой памяти под объект, в обычный malloc - нет (но у него есть aligned версия).
Отчего, кстати, примерно все касты в ваших примерах и последующая запись в кастуемую память - UB.
Я не шибко активно слежу за развитием Rust, но насколько мне известно в stable ветке нет поддержки per-container аллокаторов (в стандартной библиотеке). ChatGPT тоже не может дать примеров.
ИМХО, главная проблема C++ных исключений в их высокой стоимости
А вы хоть раз измеряли? На практике, до момента срабатывания они не стоят ничего. Но... Они ведь на то и исключения)
Я бы сказал, что коды возврата даже подороже будут, ибо из-за постоянных проверок на каждом уровне вложенности дают погрустить предсказателю переходов.
Следом за этим еще и перегрузка операторов идет в пешее эротическое.
И часто она вам нужна, для не арифметических типов (или обертами над ними)? Ну сделайте MyType::ToString и живите щастливо. Современные стандартные API для печати один хрен не требуют перегрузки операторов.
Если в середине бизнес-логики есть какой-нибудь условный vector::push_back
А если нет? Оч странный у вас контраргумент. Да, в каких-то местах оно работает, в каких-то нет.
Бездумное обмазывание noexcept -- прямой путь к внезапным падениям, а не к плюсам в производительности.
Не, ну если бездумное, то конечно, но если ваш код не бросает исключений, то как бы... Вы уже подумали?) А если не подумали, то кто соббсно виноват?)
Остается пожелать самому себе никогда не иметь дело с кодом, написанным такими экспертами.
Chromium собирается без поддержки исключений и вполне себе популярен) Вроде нормальный код.
Впрочем, с вами бы я тоже не сработался) Вы какой-то очень эмоциональный)
Та в чем проблема-то? Исключения, в сущности, ничем не лучше и не хуже кодов возвратов (std::expected если угодно).
Разницы-то никакой по сути.
Ну, да, придется вместо MyType(...) писать MyType::Create(...). Велика ли потеря?
В остальном тож самое) Я бы даже сказал, есть много плюсов. Если ничего не может внезапно сломаться в середине бизнес логики, потребителю библиотеки надо меньше думать.
Плюсом можно обмазаться в API слое всякими noexcept и получить какие-никакие плюсы к производительности)
Compile time рефлексия С++26 не имеет ничего общего с рантайм рефлексией UE.
Первая нужна для генерации кода во время компиляции и обход полей класса "по порядку" не зная ничего о самом классе. Вторая для создания объектов "на лету" по их строковому описанию.
С++26 рефлексия полезна для замены сишных макросов и всякой ерунды, вроде обобщенного кода для сериализации/десериализации.
Абсолютно бессмысленно в рантайме, ведь после компиляции сгенерированные типы точно также ничего о себе не знают в рантайме.
Причин несколько, но все они сводятся к одному: "чертова физика, бессердечная ты с*ка".
Доступ к L1 кэшу должен быть мгновенный (1-5 тактов), иначе теряется смысл и можно ходить в память. Но чтобы доступ был мгновенный, нужно:
Иметь быстрый lookup (при увеличении размера - увеличивается время на поиск очевидно
Иметь физически короткие контакты (дорожки). Иначе на частотах 4-5 ГГц, сигнал тупо не дойдёт за 1 такт, а это увеличивает latency. Речь о расстоянии в миллиметры и меньше, но можете сами посчитать сколько сигнал успеет пройти на такой частоте.
Иметь разумное энергопотребление, и что важнее, тепловыделение, т.е. нельзя располагать память слишком плотно. Косвенно опять же связано с размером самой дорожки.
Плюс всё это не должно стоить слишком дорого. Некоторое время, на заре времён, экспериментировали с размерами L1 кэша, его ассоциативностью и прочим. Выяснилось, что 16кб - слишком мало. 64кб - слишком долгий доступ и греется зараза.
32-48 кб - оптимально. Так и повелось. По крайней мере для x86_64. Впрочем, и сейчас есть чипы с бОльшим количеством L1 кэша, у тех же Apple M-серии вроде что-то порядка 192 КБ. Если честно не вникал как они этого достигли, но вон чатгпт говорит что latency там все равно большой, физически архитектура сильно сложнее получилась, а компенсируется latency большим пайплайном исполнения.
Исключение вполне себе может вылететь при рядовых операциях)
Ну... если вы пишете bash-скрипт, то и shebang надо указывать правильный)
Да, это возможный сценарий, но том эмбеде, в котором нет bash, на шелл-скриптах особо и не пишут ничего большого.
В таких контейнерах никогда шелл-скрипты и не запускают. В них упаковывают одну программу на каком-нибудь go и её же и запускают.
Проще написать две версии скриптов автокомплита, т.к. у zsh вообще своя магия для комплита.
Автору ничего решать и не надо) Автор пишет в шебанге условный
#!/usr/bin/env bash, а остальное - проблемы пользователя)Я не буду отрицать - сценарии где bash недоступен - существуют. Я лишь хочу сказать, что я с такими не сталкивался за 20 лет ни разу. Да, наверное в initramfs нет bash, но если мне придётся там много скриптовать - я просто его туда упакую.
Q-синтаксис работает и с массивами. Примерно так
Сработает как надо, но синтаксис получается немножко инопланетный, да
Доступ к L3 не требует никакой координации. Но L3 выступает той самой шиной, по которой эта когерентность обеспечивается, да. Но когерентность обеспечивается между L1, L2 кэшами, при этом сам L3 кэш точно такая же коробка с игрушками. С той лишь разницей, что рядом стоит дядя с журналом и записывает кто и что оттуда взял/положил.
За последние 20 лет я не видел ни одного реального окружения, где бы отсутствовал bash. Буквально ни одного случая.
Да меня всякий шелл - это bash, а там где не bash - всегда можно вызвать `bash - c`
Не делайте так! Не надо! А bash есть массивы, используйте их!
Эту буквально единственный вменяемый способ передачи флагов. Всё остальное - отлукавого
Вообще ещё есть capabilities :)
Ключевое отличие new от malloc в том, что new начинает object lifetime, а malloc нет. И reinterpret_cast тоже не начинает. Рекомендую копнуть в такие чудесные вещи как std::launder и std::start_lifetime_as.
Также new, помимо прочего, гарантирует корректное выравнивание для аллоцируемой памяти под объект, в обычный malloc - нет (но у него есть aligned версия).
Отчего, кстати, примерно все касты в ваших примерах и последующая запись в кастуемую память - UB.
Я не шибко активно слежу за развитием Rust, но насколько мне известно в stable ветке нет поддержки per-container аллокаторов (в стандартной библиотеке). ChatGPT тоже не может дать примеров.
Если я ошибаюсь, дайте пример на https://play.rust-lang.org
Я со временем пришел к тому, что если я делаю что-то третий раз - пора писать скрипт.
По моему личному опыту - все что делалось больше 2-3 лет назад по большей части не имеет никакого значения.
Ну, кроме совсем фундаментальных знаний конечно, но их одних недостаточно, чтобы получить приличную работу.
А вы хоть раз измеряли? На практике, до момента срабатывания они не стоят ничего. Но... Они ведь на то и исключения)
Я бы сказал, что коды возврата даже подороже будут, ибо из-за постоянных проверок на каждом уровне вложенности дают погрустить предсказателю переходов.
И часто она вам нужна, для не арифметических типов (или обертами над ними)? Ну сделайте MyType::ToString и живите щастливо. Современные стандартные API для печати один хрен не требуют перегрузки операторов.
А если нет? Оч странный у вас контраргумент. Да, в каких-то местах оно работает, в каких-то нет.
Не, ну если бездумное, то конечно, но если ваш код не бросает исключений, то как бы... Вы уже подумали?) А если не подумали, то кто соббсно виноват?)
Chromium собирается без поддержки исключений и вполне себе популярен) Вроде нормальный код.
Впрочем, с вами бы я тоже не сработался) Вы какой-то очень эмоциональный)
Та в чем проблема-то? Исключения, в сущности, ничем не лучше и не хуже кодов возвратов (std::expected если угодно).
Разницы-то никакой по сути.
Ну, да, придется вместо MyType(...) писать MyType::Create(...). Велика ли потеря?
В остальном тож самое) Я бы даже сказал, есть много плюсов. Если ничего не может внезапно сломаться в середине бизнес логики, потребителю библиотеки надо меньше думать.
Плюсом можно обмазаться в API слое всякими noexcept и получить какие-никакие плюсы к производительности)
Оч странно применять логику русского языка к жаргонизмам, которые ещё и калька с английского)
Мне вот слух не режут оба варианта) Что много фичей, что много фич)
Какой гемморой? Просто пиши без исключений и... Всё?
Хтож embedded разработкой из-под винды занимается)
Травма
Яндекс священный.
Подорожали тарифы. Раньше 5 тыщ было