Pull to refresh

Comments 21

Пара существенных замечаний.
1. Макросы без семантики вызова функций (особенно маленькими буквами) надо выжигать калёным железом. У вас бомба такая же, как min()/max() в заголовках Windows SDK. Достаточно написать где-нибудь:
bool forever = IsForever();

или зацепить заголовок с объявлением:
void Foo(bool forever = false);

И начнётся мат. Сначала компилятора в stderr, потом разработчика в ваш адрес. :)

2. Конструкции типа while(true)/while(false) не проходят через высокий уровень варнингов — компилятор начинает ругаться в стиле «Condition is always true(false)» Если включена опция «варнинги как ошибки», то такая ругань начнёт сильно раздражать. Поэтому лучше такое не использовать, либо сразу включать подавление этих варнингов (что не есть хорошо).

Благодарю за конструктивную критику.
По п.1: полностью согласен, это действительно скорее мое баловство с добавлением "вкусного" лично для моих нужд синтаксического сахара. Это что касается forever. С min()/max() как макросами я тоже уже голову поломал, как раз когда ratio делал и вполне разделяю негодование по поводу лишних макросов. За countof я бы поборолся, т.к. он часто используемый шаблон (и в VS с маленькой определен хоть и с префиксом). Что касается остальных ключевых слов-макросов то думаю здесь ясно почему я вынужден реализовать так и только так.
По п.2: там и так варнинги будут (потом поясню почему), но в целом да — я работаю на их тотальное уничтожение и конкретно этот кусочек думаю можно смело заменить.

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

А использовать variadic macro возможности нет? Я в курсе, что официально они появились только в С++11, но многие компиляторы их поддерживают.
Угу. Поддерживают, только каждый в своём стиле. Даже после официального появления в C++11.
#define PR(f, ...) printf(f, __VA_ARGS__) 

Такой стиль поддерживают более менее все.
Угу. Всё будет хорошо ровно до тех пор, пока в __VA_ARGS__ будет хотя бы один аргумент. Если же он окажется пуст, то начнутся приключения на ровном месте.
Можно же так:

#define PR(f, ...) printf(f, ##__VA_ARGS__)

или

#define VA_ARGS(...) , ##__VA_ARGS__
#define PR(f, ...) printf(f, VA_ARGS(__VA_ARGS__))
Первый вариант — gcc-specific. Второй — не уверен, что вообще будет работать. Только в C++20 появится __VA_OPT__(), который раскрывает аргумент только в случае, если эллипсис — не пустой. Такие дела.
Вы в своем же комментарии ответили на свой вопрос. Возможности проверить поддерживает ли компилятор variadic macro нет, только перебирать конкретные версии конкретных компиляторов макросами, чем занимается boost как раз.
А потом, как верно указал FlexFerrum, перебирать еще и реализации этих variadic macro, т.к. каждый из компиляторов лепит их реализации кто во что горазд почему то.

По поводу процитированного абзаца скажу что в этом нет ничего страшного, т.к., как я и написал, не вижу никакого преимущества и применения для static_assert(expr) перед static_assert(expr, message), кроме лени написать в чем ошибка то и на что проверяют.
do {} while(false)
А разве нельзя заменить эту конструкцию на просто
{}
? Она тоже выполнится ровно один раз и ограничит область видимости. Или это делается для того, чтобы потребовать у пользующего кода точку с запятой в конце?
Сталкивался в легаси с верхним вариантом, он там был, в том числе, чтобы использовать break для выхода из границ.
Все верно, и это как раз те изменения которые нужно сделать как только руки дойдут до этого. По сути данная конструкция полезна в switch case блоках, а здесь она не требуется. Плюс может генерировать warning как справедливо заметили в первом комментарии.

Я привел здесь этот кусок кода чтобы акцентировать внимание на том что такой прием есть, но конкретно из этого места его лучше выпилить.

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

Могу лишь сказать, что разбираться в тонкостях работы стандартной библиотеки довольно увлекательное занятие. Что раздражает, так это несоотвествие компиляторов собственно стандарту.

А на счет франкенштейна — считаю что по сравнению с boost у меня получилось намного чище и понятней, и все со стандартной функциональностью практически любого C++ компилятора с поддержкой C++98. А вот «некрасивая» часть локализована и возникает только от особенностей несоотвествия конкретного компилятора стандарту.
UFO just landed and posted this here
Угу. Но, как всегда, что-то где-то пошло не совсем так… :D
image
Вот я тоже на это дело посмотрел и так и не понял зачем было мешать size() с countof(). Ну то есть понятно почему оно так отрабатывает. Но это как то… не интуитивно чтоли. Примерно как с каноническим примером из Java, где "==" внезапно работает не так как подсказывает здравый смысл.

Это те самые вещи, когда сначала чешешь голову, думая «что за чертовщина, ведь так не должно быть!», а потом «аааа, ну да...», и понять то ты понял почему оно так, но всеравно остается впечатление какой то бредовости такого поведения.

Что то не понимаю эту функциональную моду в плюсах. Сначала было всё в обычных сишных массивах и структурах и были функции которые первым аргументом принимали те самые структуры. Потом в плюсах сделали ооп и вроде бы всё стало инкапсулировано и тому подобное, а сейчас обратно возвращают обратно обертки типа f(obj) вместо obj.f().
В данном случае, вроде есть наконец-то уже std:array и можно избежать путаницы с sizeof.

Полагаю, что это всё из-за того, что далеко не со всеми сущностями в C++ можно работать в объектном стиле. А для функций (шаблонных) легко работает template argument deduction. Да и синтаксис универсален. Тут даже такие размышления есть: A bit of background for the unified call proposal

А вот и сам пропозал от Саттера: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4165.pdf

Подскажите почему в компиляторах не прижились типы с фиксированной запятой, однако повсеместно есть float. В том же avr-gcc есть float, хотя уж на avr следовало бы довольствоваться типами с фиксированной запятой… Не прижились: то есть нет поддержки таких типов в printf и др...


Пример https://trueimpostors.ucoz.ru/publ/gcc_fixed_point_arithmetic/1-1-0-145

Sign up to leave a comment.

Articles