Как стать автором
Обновить

Комментарии 52

Любой опытный программист знает о разнице в обработке путей между Windows и UNIX-системами:
… а разделителем путей служит обратный слеш “\”

Вында очень давно понимает прямой, так что с этим пунктом можно не морочиться.

Если мне не изменяет память, то это всё-таки работает (работало?) не везде. Возможно, для "путей" реестра, хотя это, конечно, не совсем про filesystem.

Винда, конечно, понимает прямой — но входные данные скорее всего будут с обратным.
шаблонные RAII вида std::lock_guard guard(mutex); станут короче: std::lock_guards guard(mutex);

точно короче?

Спасибо, поправил опечатку! Оба варианта были из C++17

Избегайте вложенности пространств имён
Это почему?

Тоже заинтересовал этот вопрос.

Наверное имелась ввиду не сама вложенность, а «лесенка» в исходниках вида:
namespace foo {
  namespace bar {
    namespace something {
      ...
    }
  }
}
Дабы не заниматься домыслами хотелось бы услышать пояснения от автора статьи. Но их, полагаю, просто не будет.
Это почему?

Мне не хотелось бы, чтобы появление простого синтаксиса вложенных пространств имён привело к росту их числа. По моему опыту программисты часто злоупотребляют: пишут длинный многоуровневый namespace (30-40 символов) там, где конфликтов имён быть не может, и в итоге просто неудобно пользоваться.
Заголовки потом выглядят отвратительно.
При этом я ничего не имею против namespace boost::detail, но даже boost::algorithm::any_of мне уже не нравится.
Но вы можете считать это предвзятым мнением автора =)


P.S. ещё есть отличное правило — каждая строка в коде не длиннее 80 (100, 120) строк. Вложенные пространства имён норовят его нарушить, а вводить постоянно синонимы — в cpp-файлах неудобно, в заголовках неприемлемо.

Но вы можете считать это предвзятым мнением автора =)
Именно таким его и остается считать. Если остальные нововведения вполне хорошо объясняются с технической точки зрения и можно наглядно показать, что это ведет к тем или иным выгодам (как в понятности кода и сокращению пространства для ошибок, так и в его эффективности), то данное утверждение является вкусовщиной, не более того.
а вводить постоянно синонимы — в cpp-файлах неудобно, в заголовках неприемлемо.
Еще одно предвзятое мнение автора.
висячих ссылок (англ. dangling pointers)

Так висячии ссылки или таки висячии указатели?
Вообще-то отсутствие break в некоторых case это такая фича — таким образом можно выполнять несколько case следующих друг за другом (как правило ограничиваются двумя).
В том-то и смысл: явно указать, что это фича (с помощью [[fallthrough]]), а не забытый break.
(Как дополнительные скобки при присваивании в условии.)
Это не фича, а сплошной геморрой. Пользовался я ей два-три раза (и то вставлял комментарий, что break тут не нужен), а вот сколько багов из-за неё огрёб — не сосчитать. Вообще, switch — одна из самых плохо продуманных конструкций в c\c++. Лучше было бы сделать неявный break (ну а если нужно продолжение выполнения на след. ветке, пиши goto) и новый скоуп для каждой ветки. Ну и swich по любым типам (скажем, по строке), но это уже совсем мечты.

А ещё очень странно, что нельзя прыгать на метки case с помощью goto хотя бы внутри switch, хотя это и есть метки для прыжка.

Метка для прыжка - это идентификатор (строка, начинающаяся с буквы или подчёркивания).
Метка switch - числовая константа.
Совсем разное!

Но в C# разрешили ведь.

Неудивительно, что c# перегружен сахаром. Ведь решения принимаются там единоначально, в отличие от c++, где каждое изменение сопровождается дебатами.

Нет никакого смысла вводить в c++ конструкцию goto case и ломать совместимость со множеством компиляторов, когда такое же поведение достигается буквально минимальными затратами

    switch (num) {
        case 1:
        case_1:
            break;
        case 2:
            goto case_1;
    }

Мне буквально так и пришлось сделать, т.к. расположить case 1 под case 2 не позволяла логика кода, но это же уродливо.

for (auto&& [key, value] : map)

Опечатка или какая-то фича, неподдерживаемая MS'ом? webcompiler.cloudapp.net, 19.12.25715.0 (x86). Last updated: Sep 25, 2017:


Compiled with /std:c++17 /EHsc /nologo /W4
main.cpp
main.cpp(18): error C2440: 'initializing': cannot convert from 'std::pair<const _Kty,_Ty>' to 'std::pair<const _Kty,_Ty> &&'
        with
        [
            _Kty=std::string,
            _Ty=std::string
        ]
main.cpp(18): note: You cannot bind an lvalue to an rvalue reference```
На нормальных компиляторах все нормально godbolt.org/g/PsgD4u

А в чем соль использования в этом месте rvalue reference? Почему не const auto &?

НЛО прилетело и опубликовало эту надпись здесь

Да-да, спасибо, ошибся с термином.

НЛО прилетело и опубликовало эту надпись здесь

Спасибо за развернутый ответ

Но есть минус: для string_view не гарантируется наличие нулевого символа на конце

Я так уже и вижу тысячи разных багов, которые тут могут возникнуть.

Так для std::string тоже не гарантируется же. В чём принципиальная разница?

возможность вызвать c_str()?

Ну да, не будет этот класс совместим с частью сишных функций, хотя про тысячи багов это вы, конечно, преувеличили. Плюсовые функции не ожидают 0 в конце строки, проблемы могут возникнуть только с некоторыми сишными функциями, с которыми в любом случае надо быть осторожным, при работе из плюсов. Очевидно, что string_viewпросто абстракция над парой (const char* data, size_t len), так что по другому и быть не могло.

Сама необходимость явно вызывать c_str() означает, что пользователь должен знать об этом ограничении, чтобы его невелировать. Отсутствие c_str() у string_view будет ему намекать, что с этим классом так делать нельзя. В общем, не выглядет для меня серьезной проблемой.

Так у него ещё и c_str() нету? Как им пользоваться вообще? В 9 случаях из 10 получается удобнее иметь const& string.

Вопрос не в удобстве а в быстродействии. Если вы на место std::srting& передадите const char* произойдёт неявное копирование с выделением памяти в хипе. Здесь — не произойдёт. Если вам нужна 0-терминированная строка, вы всегда можете скопировать string_view в string явно.

Получается выбор между быстродействием и удобством+безопасностью. Быстродействие в таком выборе скорее всего проиграет, тем более, что тот, кто во всех этих строках ищет быстродействия — вообще будет использовать голые С-строки без всяких обёрток.

Отдавать сишным функциям указатели на внутренности плюсовых классов всегда было небезопасно, так что тут ничего не поменяется. Что касается того, чтобы писать используя С-строки — это намного менее безопасно и удобно. Пример типичных компонентов, где string_view может дать большой прирост производительности — различные парсеры, которым накладно выделять память, каждый раз, когда они хотят отдать пользователю токен.

У string_view нулевой overhead по отношению к C-строкам
НЛО прилетело и опубликовало эту надпись здесь
Метод data() вернет не то же самое. Он вернет строку без нуля в конце. А это уже совсем другая история.
НЛО прилетело и опубликовало эту надпись здесь
Только у строк, но не у string_view
НЛО прилетело и опубликовало эту надпись здесь
Так у него ещё и c_str() нету? Как им пользоваться вообще? В 9 случаях из 10 получается удобнее иметь const& string.
У меня был один момент, когда я прямо мечтал о string_view.

XML-парсер, который на вход принимает XML в std::string и принимает класс-визитор, который получает оповещения о прохождении нод и атрибутов. Методы класса получали параметр const std::string& с именем/значением ноды/атрибута. Если визитору было интересно значение, он себе его копировал в свой std::string, или парсил в int.

Такое решение требовало создания новых строк на каждом атрибуте, а не каждый атрибут интересовал визиторы. string_view тут был бы очень кстати (визитору всё равно, в каком виде приходят данные — string, char* или string_view).

XML-и были большие, десятки мегабайт.
На самом деле в c++ c_str практически нигде не нужен. Даже в тех местах где он нужен для передачи в C функции можно на входе принять string_view и написать небольшой checker, который, если нуля не будет, скинет всё в буферную строку и добавит его. Тогда заменив все параметры на string_view можно будет упоминание c_str в коде подозревать в преждевременной пессимизации.
Да даже литералы строковые лучше заворачивать в string_view, конструктор от указателя у них constexpr (спасибо char_traits), так что с временем инициализации то же самое, зато гарантирует что strlen более не понадобится (даже для extern литералов). Ещё прекрасный пример, кэширование каких то структур где строки имеют большую вероятность повтора, просто собрать все в какой то словарь (unordered_set) и хранить в виде string_view.
string_view — это просто костыль для изначально ущербного класса string.

Как же надоели чёртовы любители Boost! Варитесь в своём мирке, руки прочь от стандарта!
НЛО прилетело и опубликовало эту надпись здесь
Все сложнее и сложнее, все объемнее и объемнее.
Куча разных подходов, разных стилей, да даже в том, в каком стиле именуют стандартные классы, функции и т.д. разобраться не могут.
Зато модульность и рефлексию добавить уже двадцать лет как не могут.
Сделали бы форк — в одном месте хипстеры и Boost с прочим сахаром, а в другом настоящее расширение языка — в виде тех-же модулей.
Такое ощущение что боятся лезть под капот языку, или уже не знают как.
Взглянул на новые атрибуты в C++17, и у меня возник вопрос, возможно, я слишком туп чтоб понять всю гениальность, возможно у вас есть идеи?
  • maybe_unused
  • nodiscard
  • fallthrough
Мелочь, а глаза мозолит:
maybe_unused — через нижнее подчеркивание, чтобы разделить слова — логично.
nodiscard — одним словом, хотя слова «nodiscard» — не существует, ожидаемо наличие нижнего подчеркивания, но его нет.
Как я понимаю, эти атрибуты одновременно добавили, почему такая неконсистентность, что помешало?
Вопрос, если я не хочу применять эти возможности, не смотря на то, что автор говорит, что я должен их применять, то я что теперь, не разработчик?
Смотря почему Вы не хотите применять эти возможности :)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории