Комментарии 36
Ок, аргумент в пользу Haskell принят.
НЛО прилетело и опубликовало эту надпись здесь
А почему нельзя сделать подобный код:
Я правда не уверен, что все правильно написал, но смысл в том, чтобы вместо макроса шаблонную функцию сделать.
template< class T >
constexpr inline auto GET_Nth_CHAR_SPEC(N, const T (&LIT)[] ) -> decltype(T)
{ return N < sizeof_literal(LIT) ? LIT[N] : '\0'; }
Я правда не уверен, что все правильно написал, но смысл в том, чтобы вместо макроса шаблонную функцию сделать.
Конечно можно, это даже лучше будет, поскольку литерал не будет копироваться еще раз.
Ладно, а почему вы так тогда не сделали? Вариант — для облегчения читабельности кода не прокатит, этому коду уже ничем не поможешь :)
Просто интересно, в контексте бурных холиваров о вреде макросов.
Просто интересно, в контексте бурных холиваров о вреде макросов.
Что-то на волне с макросами забыл о существовании функций))) Может по-этому они зло
Странно, я как посмотрел на этот фрагмент кода:
Так у меня возник некий дискомфорт, в связи с неединообразностью стиля очень похожих вещей.
Но вообще бывает, я сам помню generic контейнеры на пуре си на макросах писал, знаю, как оно увлекает :)
template< class T, std::size_t N >
constexpr inline std::size_t sizeof_literal( const T (&)[N] )
{ return N; }
// макросы для взятия N-ого элемента литерала
#define GET_Nth_CHAR_SPEC(N, LIT) (N < sizeof_literal(LIT) ? LIT[N] : '\0')
Так у меня возник некий дискомфорт, в связи с неединообразностью стиля очень похожих вещей.
Но вообще бывает, я сам помню generic контейнеры на пуре си на макросах писал, знаю, как оно увлекает :)
Отвратительное решение проблемы. Всё делается гораздо проще, берётся исходники printf из CRT и уже прямо в ней (на чистом C) добавляются небольшие проверки валидности аргументов, на всё уйдёт пару часов с тестированием (моё время). Причём можно сразу решить, что делать, например, если кл-во аргументов не соответствует кол-ву спецификаторов: ошибку возвращать, игнорировать, пропускать неподходящие/лишние и т.п.
я примерно понял о чем речь, но по-моему вы имеете ввиду рантайм
А вы уверены, что лицензия вам позволяет «берётся исходники printf из CRT»?
Неговоря уже о том, что в статье речь идет о времени компиляции.
Неговоря уже о том, что в статье речь идет о времени компиляции.
Да, лицензия GPL позволяет это делать.
Да, в статье идёт речь немного о другом, но вариант с правкой библиотечной printf гораздо эффективнее и универсальнее. Представь, что форматирующая строка не может быть заранее задана, до компиляции программы, а может меняться значительно позже релиза, например, это часть пользовательской локализации интерфейса.
Да, в статье идёт речь немного о другом, но вариант с правкой библиотечной printf гораздо эффективнее и универсальнее. Представь, что форматирующая строка не может быть заранее задана, до компиляции программы, а может меняться значительно позже релиза, например, это часть пользовательской локализации интерфейса.
Сначала про эффективнее. Разработка? Исполнение-то явно замедлится.
Потом про «форматирующая строка не может быть заранее задана».
Если кратко, то так делать нельзя.
Если не сильно кратко, то во-первых пример плохой, т.к. при локализации часто требуется переставлять аргументы местами, чего с printf сделать не получится. Тогда уж boost::format.
Во-вторых, это же классическая атака на программы на Си. Как только у вас появляется printf(format, args), вы можете сделать дамп памяти, подсунув в format (пользовательскую локализацию, ок) длинную строку с одними только "%s".
Потом про «форматирующая строка не может быть заранее задана».
Если кратко, то так делать нельзя.
Если не сильно кратко, то во-первых пример плохой, т.к. при локализации часто требуется переставлять аргументы местами, чего с printf сделать не получится. Тогда уж boost::format.
Во-вторых, это же классическая атака на программы на Си. Как только у вас появляется printf(format, args), вы можете сделать дамп памяти, подсунув в format (пользовательскую локализацию, ок) длинную строку с одними только "%s".
Не очень понял комментарий, это вопрос или нет, мне или нет? :-\
Но, в общем случае, если уж решили модить printf, то естественно "%s" делается безопасным. Собственно, если касается дело локализации, то изменяемый снаружи только «format», а «args» скомпилирован жёстко.
Но, в общем случае, если уж решили модить printf, то естественно "%s" делается безопасным. Собственно, если касается дело локализации, то изменяемый снаружи только «format», а «args» скомпилирован жёстко.
Про эффективнее — вопрос, остальное — возражение.
О том и речь, что скомпилированные args — это не гибко, а задавать формат опасно в принципе при использовании printf. Что касается, «сделаем printf безопасным и потом будем локализовывать именно так», то это странно, т.к. есть более правильные способы.
Ну и модят printf на этапе компиляции, иначе он будет медленно работать.
О том и речь, что скомпилированные args — это не гибко, а задавать формат опасно в принципе при использовании printf. Что касается, «сделаем printf безопасным и потом будем локализовывать именно так», то это странно, т.к. есть более правильные способы.
Ну и модят printf на этапе компиляции, иначе он будет медленно работать.
Компилятор gcc умеет статически проверять соответствие форматной строки и аргументов в printf.
Не только gcc, есть еще много утилит для статического анализа кода, но это совсем не то, это другой уровень абстракции: код проверяют снаружи, этот же подход разрешает делать это изнутри.
Не знаком с этим новым значением слова «абстракция» :)
Подход как подход кстати — свои достоинства есть что у статического анализа что у подобных проверок во время компиляции.
Но честно говоря к специализированным инструментам у меня доверия больше.
Подход как подход кстати — свои достоинства есть что у статического анализа что у подобных проверок во время компиляции.
Но честно говоря к специализированным инструментам у меня доверия больше.
Как же вы живёте-то? Вам за что зарплату платят?
Я никогда не в восторге от кода, который выглядит сложным более чем для 50% программистов.
И реализация, и использование — усложнено.
Больше сложности — больше места для ошибки.
Но как разминку для ума — одобряю :-)
И реализация, и использование — усложнено.
Больше сложности — больше места для ошибки.
Но как разминку для ума — одобряю :-)
Для меня этот код не сложен, поэтому ошибок там нет=)
С использованием согласен: вариант с шаблонизацией литерала в случае неправильного использования из-за препроцессинга дает далеко-не-сразу-понятные ошибки.
Ну а все остальное, а особенно кортежи, по моему проще пареной репы.
С использованием согласен: вариант с шаблонизацией литерала в случае неправильного использования из-за препроцессинга дает далеко-не-сразу-понятные ошибки.
Ну а все остальное, а особенно кортежи, по моему проще пареной репы.
Вы не с той стороны смотрите на проблему. Написать код — это 10% работы.
Остальные 90% — поддерживать его на протяжении следующих 20 лет, когда вам лично уже будет не до него.
Остальные 90% — поддерживать его на протяжении следующих 20 лет, когда вам лично уже будет не до него.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Даже в текущем виде constexpr — головная боль для создателей компилятора. По словам разработчиков Clang это самая сложная для реализации часть C++11, и просили ни в коем случае не расширять эту функциональность.
Ну как же нельзя, я же уже писал об этом. Создаем pack длинны кортежа, а далее подставляем в функцию взятия элемента:
Примерно так.
template<int... INDXs>
T apply(FuncType f, tuple t)
{
return f(get<INDXs>(t)...);
}
Примерно так.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Самый правильный безопасный printf