Комментарии 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, но многие компиляторы их поддерживают.
#define PR(f, ...) printf(f, __VA_ARGS__)
Такой стиль поддерживают более менее все.
#define PR(f, ...) printf(f, ##__VA_ARGS__)
или
#define VA_ARGS(...) , ##__VA_ARGS__
#define PR(f, ...) printf(f, VA_ARGS(__VA_ARGS__))
А потом, как верно указал FlexFerrum, перебирать еще и реализации этих variadic macro, т.к. каждый из компиляторов лепит их реализации кто во что горазд почему то.
По поводу процитированного абзаца скажу что в этом нет ничего страшного, т.к., как я и написал, не вижу никакого преимущества и применения для static_assert(expr) перед static_assert(expr, message), кроме лени написать в чем ошибка то и на что проверяют.
do {} while(false)
А разве нельзя заменить эту конструкцию на просто
{}
? Она тоже выполнится ровно один раз и ограничит область видимости. Или это делается для того, чтобы потребовать у пользующего кода точку с запятой в конце?
Сталкивался в легаси с верхним вариантом, он там был, в том числе, чтобы использовать break для выхода из границ.
Я привел здесь этот кусок кода чтобы акцентировать внимание на том что такой прием есть, но конкретно из этого места его лучше выпилить.
Тяжело читать про чужую боль. Все эти макросы как замедленные бомбы и куча разных стандартов с++ у компиляторов. Мне кажется иногда лучше написать больше кода пусть и не очень изящного основываясь на старлм стагдарте чем делать такого франкенштейна.
А на счет франкенштейна — считаю что по сравнению с boost у меня получилось намного чище и понятней, и все со стандартной функциональностью практически любого C++ компилятора с поддержкой C++98. А вот «некрасивая» часть локализована и возникает только от особенностей несоотвествия конкретного компилятора стандарту.
countof
в стандарте появился в версии C++17 в образе std::size()
Это те самые вещи, когда сначала чешешь голову, думая «что за чертовщина, ведь так не должно быть!», а потом «аааа, ну да...», и понять то ты понял почему оно так, но всеравно остается впечатление какой то бредовости такого поведения.
Что то не понимаю эту функциональную моду в плюсах. Сначала было всё в обычных сишных массивах и структурах и были функции которые первым аргументом принимали те самые структуры. Потом в плюсах сделали ооп и вроде бы всё стало инкапсулировано и тому подобное, а сейчас обратно возвращают обратно обертки типа f(obj)
вместо obj.f()
.
В данном случае, вроде есть наконец-то уже std:array
и можно избежать путаницы с sizeof
.
А вот и сам пропозал от Саттера: 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
Как я стандартную библиотеку C++11 писал или почему boost такой страшный. Глава 2