170 похожих чатов

Есть ли смысл использовать std::optional<std::reference_wrapper<T>> вместо T*?

35 ответов

22 просмотра

спорный вопрос. если кодовая база так устроена, что в ней очевидно, что T* - это optional<T&>, то можно ограничиться и T*.

У них разная семантика. std::shared/unique_ptr – возможно, а std::optional<std::reference_wrapper<T>> довольно неудобная для использования штука

Алиса Кассель-Королёва
чем неудобная?

Например, двойным разыменованием или излишней длиной сигнатур

Ofee Oficsu
Например, двойным разыменованием или излишней длин...

а преимущества перед сырым указателем есть?

Когда речь идет об std::optional - лучше, имхо, посмотреть не в сторону указателей, а каких-нибудь "атомарных" ресурсов, которые могут, например, не поставляться интерфейсу в рамках утвержденного контракта. Ближе всего будут всевозможные handle'ы. Однако, наверное, подобную архитектуру в идеальном случае вообще лучше не иметь. Не припоминается случай, когда handle'ы не являются указателями на агрегаты в не-opaque архитектурах (как какой-нибудь OpenGL, например).

Алиса Кассель-Королёва
а преимущества перед сырым указателем есть?

Надо смотреть есть ли перегрузка у optional для reference_wrapper, не занимает ли больше места для хранения флага

Nikita Khomutov
Это вкусовщина и не более

Ну, двойная абстракция и необходимость двойного разыменования вполне объективно влияют на качество кода – во-первых, больше текста для базовых операций, во-вторых, в голове нужно держать две сущности, а не одну

Алиса Кассель-Королёва
а преимущества перед сырым указателем есть?

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

Ofee Oficsu
Ну, двойная абстракция и необходимость двойного ра...

У тебя в коде могут быть всякие готовые решения для контейнера optional: для сериализации и тд. Может выясниться, что станет только удобнее

Alexander Karaev
специализации точно нет

Значит, вот и ответ, чем сырой указатель лучше

Nikita Khomutov
Значит, вот и ответ, чем сырой указатель лучше

Если нужна явная индикация того, что указатель может быть нулленым - можно, в конце концов, определить соответствующий вербозный alias без каких-либо ресурсовых штрафов.

Sergey Anisimov
Если нужна явная индикация того, что указатель мож...

Указатель и так явно nullable по определению. Для non-nullable есть reference

Nikita Khomutov
Указатель и так явно nullable по определению. Для ...

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

Sergey Anisimov
На это совершенно необязательно так смотреть. Я, н...

Не, лучше именно так и смотреть. C++ Core Guidelines не просто так были написаны. > если будет осуществляться запись Тут уже не понял, не const-ли семантику ли вешаете на поинтер?

Nikita Khomutov
Не, лучше именно так и смотреть. C++ Core Guidelin...

Не понял Вашего непонимания. out-var'ы (в т.ч. POD'ы) могут для записи быть переданы через Lvalue-ссылку или указатель. В этой ситуации я требую указатель, чтобы лишний раз стимулировать понимание записывающей природы вызываемой конструкции. Можно это, конечно, счесть за идиосинкразию, но, имхо, вполне адекватный пример потенциальной семантической разницы. Кроме того, повидал не один проект (в т.ч. весьма большие), в который указатели совершенно не означали допустимость нуллирования.

Sergey Anisimov
Не понял Вашего непонимания. out-var'ы (в т.ч. POD...

Значит я правильно понял, что вместо того, чтобы использовать встроенную в язык const-семантику, вы вместо этого используете поинтеры вместо lvalue reference? Кажется, этот подход изначально ошибочен: в языке уже есть готовый инструмент для этой задачи. А отличие lvalue от pointer только в свойстве nullable

Nikita Khomutov
Значит я правильно понял, что вместо того, чтобы и...

К чему в данной ситуации вообще упоминание const-семантики? auto subA ( Type const& data ) -> /* ... */; auto subB ( Type& data ) -> /* ... */; Для вызывающего контекста вызовы с передачей экземпляра Type будут синтаксически неотличимы. Иными словами, именно вызывающей стороне нужно следить за const-семантикой, чтобы не выстрелить в ногу. Если же мы имеем auto subB ( Type* data ) -> /* ... */; вызывающей стороне потребуется препенднуть амперсанд. Это, конечно, ничего не гарантирует, но в примитивном коде сериализации/десериализации отрезвляет весьма эффективно.

Sergey Anisimov
К чему в данной ситуации вообще упоминание const-с...

Ну как это не отличимы? Для вызова subA гарантируется, что у data вызываются только const-методы (кроме случая const_cast, но это умышленное нарушение контракта). Для subB контракт другой.

Nikita Khomutov
Ну как это не отличимы? Для вызова subA гарантируе...

Абсолютно верно. Однако, неконстантный объект можно отдать в оба. В этом и проблема.

Sergey Anisimov
Абсолютно верно. Однако, неконстантный объект можн...

Так в чём проблема? Пока никакой проблемы нет

Nikita Khomutov
Ну как это не отличимы? Для вызова subA гарантируе...

SomeDamnedFileHeader hdr; doSmthngA(hdr); doSmthngB(hdr); doSmthngC(hdr); После какого вызова hdr изменился? Изменился ли он вообще? Ждали ли Вы изменения в этом месте?

Nikita Khomutov
Так в чём проблема? Пока никакой проблемы нет

Речь о том, что при чтении кода вызывающей стороны, нам неочевидно, модифицируется ли аргумент в то время как с указателем мы можем обнаружить это по взятию адреса

Sergey Anisimov
SomeDamnedFileHeader hdr; doSmthngA(hdr); doSmthng...

Мне IDE подсветит, где hdr был взят как T&, а не как const T&

Nikita Khomutov
Мне IDE подсветит, где hdr был взят как T&, а не к...

А мне компилятор проэррорит, если я сделаю не то, что предполагал. Это все-таки существенная разница.

Sergey Anisimov
А мне компилятор проэррорит, если я сделаю не то, ...

Ну так если явно хочешь это зарестриктить, то проще const auto& chdr = hdr; foo(chdr); bar(chdr); baz(chdr);

Nikita Khomutov
Ну так если явно хочешь это зарестриктить, то прощ...

О чем я и писал несколькими сообщениями выше. Контролировать это придется вызывающему контексту. А если он с головой не дружит в момент вызова - не будет он эти const'ы кругом расставлять. Таким образом я вынуждаю лишний раз подумать со своей стороны (интерфейса вызываемого компонента), а не надеяться, что вызыватель (вполне может статься, что тоже я, только несколькими часами позже) станет во все эти const/non-const всматриваться. Не говоря уже о том, что один и тот же агрегат может потребоваться и с const и с non-const т.з. последовательно.

Sergey Anisimov
О чем я и писал несколькими сообщениями выше. Конт...

Ну и это нормально. Вызываемое API прямо говорит про свои контракты. Вызывающий контекст сам должен решать, какой уровень гарантий ему нужен. Если вызывающий контекст с головой не дружит, боюсь, тут ничто не поможет. Попытка подстелить в конкретном месте другую языковую конструкцию в предположении, что пользователь API плохо знаком с языком — приведёт к тому, в случае если пользователь действительно таков, что в другом месте будет демонстрировать точно такое же непонимание гарантий и контрактов.

Nikita Khomutov
Ну и это нормально. Вызываемое API прямо говорит п...

Вот как раз вот это и поможет. &hdr - пишем, hdr - не пишем. Попытка поменять местами приведет к ошибкам компиляции в обоих случаях. Опять же, я не претендую с этой своей идиосинкразией на статус какого-то стандарта. Речь шла о том, что семантика ссылок и указателей вполне себе кастомизируема, и, имхо, не может однозначно указывать на возможность передачи null'а соответствующим аргументом. На это как раз следует указывать явным способом: alias'ы (NullablePtr<Type>), атрибуты (если/когда будут), контракты (туда же), документация, в конце концов. От того, что некто не передаст null, скорее всего ничего не упадет. А вот в противном случае очень даже может.

Sergey Anisimov
Если нужна явная индикация того, что указатель мож...

Сергей, придумай себе аватарку, поставь... Естественно, это просьба

Ilya Zviagin
Сергей, придумай себе аватарку, поставь... Естеств...

Да, я вижу, так проще людей идентифицировать. Воткнул абстрактщину.

Egor Kulebyakin
где она?

А, извиняюсь, настройки приватности. Исправил.

Похожие вопросы

Обсуждают сегодня

а через ESC-код ?
Alexey Kulakov
29
30500 за редактор? )
Владимир
47
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
13
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
program test; {$mode delphi} procedure proc(v: int32); overload; begin end; procedure proc(v: int64); overload; begin end; var x: uint64; begin proc(x); end. Уж не знаю...
notme
6
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
6
Вот еще странный косяк, подскажите как бороться. Я git clone сделал себе всего embassy и примеры там запускаю. Всё хорошо. Но вот решил в cargo.toml зависимости не как в приме...
Lukutin R2AJP
1
вы делали что-то подобное и как? может есть либы готовые? увидел картинку нокода, где всё линиями соединено и стало интересно попробовать то же в ddl на lua сделать. решил с ч...
Victor
8
Ребят в СИ можно реализовать ООП?
Николай
33
Карта сайта