спорный вопрос. если кодовая база так устроена, что в ней очевидно, что T* - это optional<T&>, то можно ограничиться и T*.
У них разная семантика. std::shared/unique_ptr – возможно, а std::optional<std::reference_wrapper<T>> довольно неудобная для использования штука
Например, двойным разыменованием или излишней длиной сигнатур
а преимущества перед сырым указателем есть?
Это вкусовщина и не более
Когда речь идет об std::optional - лучше, имхо, посмотреть не в сторону указателей, а каких-нибудь "атомарных" ресурсов, которые могут, например, не поставляться интерфейсу в рамках утвержденного контракта. Ближе всего будут всевозможные handle'ы. Однако, наверное, подобную архитектуру в идеальном случае вообще лучше не иметь. Не припоминается случай, когда handle'ы не являются указателями на агрегаты в не-opaque архитектурах (как какой-нибудь OpenGL, например).
Надо смотреть есть ли перегрузка у optional для reference_wrapper, не занимает ли больше места для хранения флага
Ну, двойная абстракция и необходимость двойного разыменования вполне объективно влияют на качество кода – во-первых, больше текста для базовых операций, во-вторых, в голове нужно держать две сущности, а не одну
Не могу их назвать с учётом разницы в семантике. Я бы упомянул про владение, но тогда было бы логичнее сравнивать сырой указатель с умными
У тебя в коде могут быть всякие готовые решения для контейнера optional: для сериализации и тд. Может выясниться, что станет только удобнее
специализации точно нет
Значит, вот и ответ, чем сырой указатель лучше
Если нужна явная индикация того, что указатель может быть нулленым - можно, в конце концов, определить соответствующий вербозный alias без каких-либо ресурсовых штрафов.
Указатель и так явно nullable по определению. Для non-nullable есть reference
На это совершенно необязательно так смотреть. Я, например, использую указатели в том случае, если по нему будет запись осуществляться. Так вызывающей стороне придется воспользоваться амперсандом и лишний раз посмотреть на сигнатуру потенциально.
Не, лучше именно так и смотреть. C++ Core Guidelines не просто так были написаны. > если будет осуществляться запись Тут уже не понял, не const-ли семантику ли вешаете на поинтер?
Не понял Вашего непонимания. out-var'ы (в т.ч. POD'ы) могут для записи быть переданы через Lvalue-ссылку или указатель. В этой ситуации я требую указатель, чтобы лишний раз стимулировать понимание записывающей природы вызываемой конструкции. Можно это, конечно, счесть за идиосинкразию, но, имхо, вполне адекватный пример потенциальной семантической разницы. Кроме того, повидал не один проект (в т.ч. весьма большие), в который указатели совершенно не означали допустимость нуллирования.
Значит я правильно понял, что вместо того, чтобы использовать встроенную в язык const-семантику, вы вместо этого используете поинтеры вместо lvalue reference? Кажется, этот подход изначально ошибочен: в языке уже есть готовый инструмент для этой задачи. А отличие lvalue от pointer только в свойстве nullable
К чему в данной ситуации вообще упоминание const-семантики? auto subA ( Type const& data ) -> /* ... */; auto subB ( Type& data ) -> /* ... */; Для вызывающего контекста вызовы с передачей экземпляра Type будут синтаксически неотличимы. Иными словами, именно вызывающей стороне нужно следить за const-семантикой, чтобы не выстрелить в ногу. Если же мы имеем auto subB ( Type* data ) -> /* ... */; вызывающей стороне потребуется препенднуть амперсанд. Это, конечно, ничего не гарантирует, но в примитивном коде сериализации/десериализации отрезвляет весьма эффективно.
Ну как это не отличимы? Для вызова subA гарантируется, что у data вызываются только const-методы (кроме случая const_cast, но это умышленное нарушение контракта). Для subB контракт другой.
Абсолютно верно. Однако, неконстантный объект можно отдать в оба. В этом и проблема.
Так в чём проблема? Пока никакой проблемы нет
SomeDamnedFileHeader hdr; doSmthngA(hdr); doSmthngB(hdr); doSmthngC(hdr); После какого вызова hdr изменился? Изменился ли он вообще? Ждали ли Вы изменения в этом месте?
Речь о том, что при чтении кода вызывающей стороны, нам неочевидно, модифицируется ли аргумент в то время как с указателем мы можем обнаружить это по взятию адреса
Мне IDE подсветит, где hdr был взят как T&, а не как const T&
А мне компилятор проэррорит, если я сделаю не то, что предполагал. Это все-таки существенная разница.
Ну так если явно хочешь это зарестриктить, то проще const auto& chdr = hdr; foo(chdr); bar(chdr); baz(chdr);
О чем я и писал несколькими сообщениями выше. Контролировать это придется вызывающему контексту. А если он с головой не дружит в момент вызова - не будет он эти const'ы кругом расставлять. Таким образом я вынуждаю лишний раз подумать со своей стороны (интерфейса вызываемого компонента), а не надеяться, что вызыватель (вполне может статься, что тоже я, только несколькими часами позже) станет во все эти const/non-const всматриваться. Не говоря уже о том, что один и тот же агрегат может потребоваться и с const и с non-const т.з. последовательно.
Ну и это нормально. Вызываемое API прямо говорит про свои контракты. Вызывающий контекст сам должен решать, какой уровень гарантий ему нужен. Если вызывающий контекст с головой не дружит, боюсь, тут ничто не поможет. Попытка подстелить в конкретном месте другую языковую конструкцию в предположении, что пользователь API плохо знаком с языком — приведёт к тому, в случае если пользователь действительно таков, что в другом месте будет демонстрировать точно такое же непонимание гарантий и контрактов.
Вот как раз вот это и поможет. &hdr - пишем, hdr - не пишем. Попытка поменять местами приведет к ошибкам компиляции в обоих случаях. Опять же, я не претендую с этой своей идиосинкразией на статус какого-то стандарта. Речь шла о том, что семантика ссылок и указателей вполне себе кастомизируема, и, имхо, не может однозначно указывать на возможность передачи null'а соответствующим аргументом. На это как раз следует указывать явным способом: alias'ы (NullablePtr<Type>), атрибуты (если/когда будут), контракты (туда же), документация, в конце концов. От того, что некто не передаст null, скорее всего ничего не упадет. А вот в противном случае очень даже может.
Сергей, придумай себе аватарку, поставь... Естественно, это просьба
Да, я вижу, так проще людей идентифицировать. Воткнул абстрактщину.
А, извиняюсь, настройки приватности. Исправил.
Обсуждают сегодня