Деление тоже можно реализовать на циклических сдвигах вправо и вычитаниях. Примеры процедур можно найти в инете.
И разрядность можно сделать любую. Даже если компилятор такую не поддерживает.
Речь про value, но не в том смысле, что нельзя подобную функцию переписать с небольшими изменениями на С, просто эта и множество других функций уже написаны профессионалами и доступны всем желающим, многие из них шаблонные и работают на этапе компиляции, потому на С не могут быть написаны в принципе. А если могут, то сначала нужно написать или найти, в обоих случаях надежность и производительность будет под вопросом.ПростоНуб писал(а):Если же речь про параметр value, то в упор не понимаю, в чем тут разница между передачей указателя по значению в С и передачей ссылки в С++, которая в скомпилированном коде так же будет передаваться по значению адреса (того же значения указателя) в ней содержащегося.
Во-первых, то что там много шаблонного кода(еще и проскакивают constexpr функции) еще не означает, что хоть какой-то код имеющий отношение к парсингу чисел по основанию 36 попадет в бинарник. Во-вторых, from_chars() не бросает исключения, динамически не выделяет память и не работает с локалью, так что в каком-то смысле она эмбедд ориентированнаяПростоНуб писал(а):Другое дело, что при жестких требованиях к производительности и памяти, не возникает никакого желания тащить такого монстра, как from_chars, себе в код. Например, зачем мне куча кода для парсинга чисел по основанию 36, если мне нужен парсинг только целых десятичных чисел? Как это не компилируй, но ворох лишнего кода всегда прибежит.
О чем и речь, к мк все сказанное практически никакого отношения не имеет, тем более официально распространяемый gcc для ARM именуется не иначе как gcc-arm-none-eabiПростоНуб писал(а):Было бы смешно, если не было бы так грустно. Для примера, в MS SQL, PostgreSQL или Oracle подключить скомпилированное расширение в виде so/dll - элементарно, причем динамически без остановки сервиса. Потому что они написаны на C и ABI стандартизирован. А вот к Clickhouse - только с полной перекомпиляцией всего Clickhouse и рестартом сервиса, так как он написан на C++, а ABI в C++ меняется даже от версии к версии одного компилятора, не говоря уже о разных.
Тоже самое можно сказать и про ESP32, и про старшие МК на ARM, где расширения могут быть востребованы. а полная рекомпиляция или не желательна, или даже невозможна, так как все исходники недоступны.
Только не нужно Линуса приплетать, он сам на С++ не пишет и цитата относится к 2010 году, вероятно еще про С++03, по сути совершенно другой язык. А синтаксис у С то заметно проще, но это если брать языки в полном объеме, а если взять С и накатить поверх множество мелких улучшений из С++, то получится некое подмножество С++ с синтаксисом проще, чем у С. Последнее время мне даже попадалась парочка книг с подобным подходом, в одной из них автор называл такой С++ кажется Super C, а в D есть ключ компилятора отключающий часть возможностей и превращающий язык в Better CПростоНуб писал(а):Речь не о простоте для изучения (не думаю, что к C это относится, так же, как, для примера, к Lisp). А о простоте синтакиса.
Код: Выделить всё
import core.std;Уже видно по исходникам, что рассматриваемая from_chars() сделана излишне универсальной и перегруженной.Reflector писал(а):надежность и производительность будет под вопросом.
А как он не попадет, если base будет переменная? Я могу ограничить пользователя, например, base<=10 при вводе, но у меня большие сомнения, что оптимизатор настолько умен, что не только увидит и запомнит это ограничение, но еще и применит его при оптимизации case в __to_chars_i()Reflector писал(а): Во-первых, то что там много шаблонного кода(еще и проскакивают constexpr функции) еще не означает, что хоть какой-то код имеющий отношение к парсингу чисел по основанию 36 попадет в бинарник.
А ребята не знали. что профессионалы пишут только на С++ и их труды доступны всем желающим только на C++. А на остальных языках, включая C, профессионалы не пишут и труды не публикуются? )))Reflector писал(а):эта и множество других функций уже написаны профессионалами и доступны всем желающим
Вас несет. Возьмите и сравните c atof, как по размеру кода, так и по производительности, и уже после этого рассуждайте. А то уж очень демагогией попахивает. Если ничего не делать. то все будет "далеко не факт".Reflector писал(а):В-третьих, далеко не факт, что другие функции, в том числе сишные, лучше справятся с парсингом чисел с плавающей точкой...
Для имеющих проблемы со зрением использовал полужирное начертание )))Reflector писал(а):О чем и речь, к мк все сказанное практически никакого отношения не имеетПростоНуб писал(а):Было бы смешно, если не было бы так грустно. Для примера, в MS SQL, PostgreSQL или Oracle подключить скомпилированное расширение в виде so/dll - элементарно, причем динамически без остановки сервиса. Потому что они написаны на C и ABI стандартизирован. А вот к Clickhouse - только с полной перекомпиляцией всего Clickhouse и рестартом сервиса, так как он написан на C++, а ABI в C++ меняется даже от версии к версии одного компилятора, не говоря уже о разных.
Тоже самое можно сказать и про ESP32, и про старшие МК на ARM, где расширения могут быть востребованы. а полная рекомпиляция или не желательна, или даже невозможна, так как все исходники недоступны.
Почему это не надо? Он достаточно четко выразился, что один и тот же код в C++ может, в зависимости от контекста, выполнять совершенно разные действия. Вы же сами это пропагандируете шаблонами. Вот только это очень удобно при написании программы, но сильно повышает трудоемкость при ее сопровождении, что как раз и подчеркнул Линус. Например, я сам не раз сталкивался с совершенно негуманоидой логикой реализации операций сложения или сравнения для некоторых объектов некоторыми программистами.Reflector писал(а): Только не нужно Линуса приплетать
Ок, можно ведь протестировать... Компилируем следующий код на F7:ПростоНуб писал(а):Уже видно по исходникам, что рассматриваемая from_chars() сделана излишне универсальной и перегруженной.
Код: Выделить всё
PerfCounter perf;
perf.start();
static char arr[] = "1234567890";
volatile int val = atoi(arr);
auto t = perf.getElapsedTicks();
rtt.println(t, val);Специально откопал старенький ноут, создаю в VisualGDB сишный проект на HAL мигающий светодиодом, по умолчанию он компилирует намного больше *.c файлов из HAL, чем нужно для светодиода, но тем не менее, полная пересборка с -O2 -flto занимает 8 сек. Теперь берем эмулятор спектрума на H750 который картину выводит одновременно на дисплей и VGA и где все начиная c пина и заканчивая либами USB/FMC/LTDC/SDMMC/FatFs в виде шаблонный классов и получаем 23 сек. Но зачем после каждого изменения полностью пересобирать проект, если что-то поменять в парочке файлов, то сама компиляция займет секунд 5 и еще 13 сек. линковка и время линковки можно существенно сократить отключив LTO. На нормально железе все будет происходить в разы быстрее и это даже без учета модулей...ПростоНуб писал(а):Во-вторых, плата за это - когда проект собирается даже на выделенном сервере часы. Тогда невольно жалеешь, что это не C, собирающийся по сравнению с C++ моментально, если не были затронуты корневые включаемые файлы, что происходит очень редко. Пробовали сделать крупный проект на QT? Сколько он собирался?
В большинстве случаев парсят десятичные числа, собственно потому у base значение по умолчанию равно 10, так что скорее всего будет константа или base не будет вообще, в таком случае можно изначально попасть в перегруженную функцию принимающую на один параметр меньше.ПростоНуб писал(а):А как он не попадет, если base будет переменная? Я могу ограничить пользователя, например, base<=10 при вводе, но у меня большие сомнения, что оптимизатор настолько умен, что не только увидит и запомнит это ограничение, но еще и применит его при оптимизации case в __to_chars_i()
Так сравнил уже, к сожалению поддержку float для from_chars() добавили только в gcc 11, которого для ARM еще нет, но я изначально ожидал возможный выигрыш именно на float, а оказалось он есть даже для целых чисел.ПростоНуб писал(а):Вас несет. Возьмите и сравните c atof, как по размеру кода, так и по производительности, и уже после этого рассуждайте. А то уж очень демагогией попахивает. Если ничего не делать. то все будет "далеко не факт".
Можно хоть все посты полужирным выделить и третий раз Линуса процитировать, все равно никто не перестанет писать на С++ для Cortex-M потому что возможны какие-то гипотетические проблемы с ABI на Cortex-AПростоНуб писал(а):Для имеющих проблемы со зрением использовал полужирное начертание )))
Распространенный пример из мира эмбедда, пожалуйста. Лично у меня перегружены операторы для строгих перечислений, тут никаких вопросов быть не может, любой гайд по С++ будет рекомендовать не использовать сишные перечисления. Далее перегружен оператор "|" для пинов:ПростоНуб писал(а):Почему это не надо? Он достаточно четко выразился, что один и тот же код в C++ может, в зависимости от контекста, выполнять совершенно разные действия. Вы же сами это пропагандируете шаблонами. Вот только это очень удобно при написании программы, но сильно повышает трудоемкость при ее сопровождении, что как раз и подчеркнул Линус. Например, я сам не раз сталкивался с совершенно негуманоидой логикой реализации операций сложения или сравнения для некоторых объектов некоторыми программистами.
Код: Выделить всё
return sck | miso | mosi | nss;Код: Выделить всё
constexpr auto f1 = sin(1.2345f);
constexpr auto f2 = sin(Fixed<12>(1.2345f));
rtt.println(f1, (float)f2); // 0.94398332, 0.94397926
Код: Выделить всё
template<typename T, std::size_t N>
constexpr std::size_t inline size(const T(&)[N]) { return N; }
int arr[10];
int arr2[size(arr)];
Код: Выделить всё
static inline void clear() requires requires() { base()->BRR; }
{
base()->BRR = pin_mask;
}
static inline void clear()
{
*((volatile uint16_t*)&base()->BSRR + 1) = pin_mask;
}Код: Выделить всё
void foo(auto val) requires requires() { val.brr; } {}
void foo(auto val) {}Код: Выделить всё
static void foo(HasBrr auto val) {}
static void foo(std::integral auto val) {}
static void foo(auto val) {}
Код: Выделить всё
void foo() requires true {} // Error: constraints on a non - templated functionКод: Выделить всё
class Foo
{
public:
void bar()& { rtt.println("foo&"); }
void bar()const & { rtt.println("foo& const"); }
void bar()&& { rtt.println("foo&&"); }
};
Foo foo;
foo.bar(); // "foo&"
constexpr Foo fooc;
fooc.bar(); // "foo& const"
Foo{}.bar(); // "foo&&" (временный объект)Код: Выделить всё
static inline void clear()
{
if constexpr(requires(){ base()->BRR; })
base()->BRR = pin_mask;
else
*((volatile uint16_t*)&base()->BSRR+1)=pin_mask;
}