Russian Qt Forum

Программирование => С/C++ => Тема начата: ViTech от Ноябрь 11, 2019, 19:14



Название: Ненулевые указатели
Отправлено: ViTech от Ноябрь 11, 2019, 19:14
Начало:
А вы пользуетесь этим gsl::not_null? Какие ощущения? И как у него с поддержкой умных указателей (в частности unique_ptr)?

К сожалению, не пользуюсь=( Только недавно перешли на с++17 моими стараниями (был с++11), а gsl хочет с++14 минимум. В ближайших планах есть.
gsl:span юзал, вот это вещь, да.
С умными указателями вроде всё неплохо, почему нет?

Первое, что я попробовал с gsl::not_null, было следующее:
Код
C++ (Qt)
#include <memory>
#include <gsl/pointers>
 
using namespace std;
 
int main()
{
   gsl::not_null<unique_ptr<int>> unique_p{make_unique<int>(42)};
   gsl::not_null<shared_ptr<int>> shared_p{make_shared<int>(42)};
 
   return 0;
}

Строка с unique_ptr компилируется с ошибкой:
Код:
/opt/Library/GSL/include/gsl/pointers:81: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’
   81 |     constexpr not_null(T u) : ptr_(u)
      |                                     ^
Т.е. осуществляется попытка скопировать unique_ptr, а не переместить.

В связи с этим у меня возник вопрос: когда я пишу gsl::not_null<unique_ptr<int>>, то хочу сделать что-то странное? Или я что-то делаю не так?


Название: Re: Ненулевые указатели
Отправлено: Авварон от Ноябрь 11, 2019, 20:04
И правда, с юником оно не работает (https://github.com/microsoft/GSL/issues/89).

Я, кстати, еще наброшу - юник_птр вообще говно, его нельзя сделать объявить константным.
Юзкейз - мочь форвардить его в функции но запретить явно вызывать .release().
"константный" юник_птр бы решил все проблемы=)


Название: Re: Ненулевые указатели
Отправлено: ViTech от Ноябрь 11, 2019, 20:52
И правда, с юником оно не работает (https://github.com/microsoft/GSL/issues/89).

Там вообще много интересного, связанного с умными указателями.
Например:
not_null<shared_ptr> overhead (https://github.com/microsoft/GSL/issues/550)
Цитировать
What is the intended usage of not_null with std::shared_ptr? There is a significant overhead to wrapping std::shared_ptr in not_null because every access results in a costly copy of the shared_ptr. As not_null cannot be used with unique_ptr, it seems that not_null is not really usable with smart pointers in general.

Вот пулл реквест, чтобы можно было перемещать unique_ptr: not_null no longer requires a copyable pointer type (https://github.com/microsoft/GSL/pull/675).
Но, видать, это мало кому нужно :).


Название: Re: Ненулевые указатели
Отправлено: Авварон от Ноябрь 11, 2019, 21:15

Там вообще много интересного, связанного с умными указателями.
Например:
not_null<shared_ptr> overhead (https://github.com/microsoft/GSL/issues/550)


Ну это тоже следствие того что ctor принимает копию указателя а get() возвращает копию.

Но да, с вумными указателями это особо не нужно.
Кроме того, там лезут проблемы, например:
Код:
not_null<unique_ptr<int>> p(make_unique(42));
p.get().release(); // oops контракт нарушен

Конечно, повторный вызов get() выявит нарушение контракта, но хотелось бы запретить такой вызов "на корню", т.е. get() вообще в идеале не должен ничего проверять (контракт был нарушен где-то ДО get() и вот там это и надо проверять - в кторе ли или в операторе=)
Возможно, это можно сделать через частичную специализацию для разных типов - одна для тривиальных T*, вторая для вумных (т.е. get() возвращает всегда T* просто в случаев вумных делает еще один .get()). Короче всё оказалось не так тривиально как я думал=(


Название: Re: Ненулевые указатели
Отправлено: Old от Ноябрь 11, 2019, 21:18
Я, кстати, еще наброшу - юник_птр вообще говно, его нельзя сделать объявить константным.
Юзкейз - мочь форвардить его в функции но запретить явно вызывать .release().
"константный" юник_птр бы решил все проблемы=)
Не очень понятен юзкейс. Можете пример привести.


Название: Re: Ненулевые указатели
Отправлено: Авварон от Ноябрь 11, 2019, 22:07
Я, кстати, еще наброшу - юник_птр вообще говно, его нельзя сделать объявить константным.
Юзкейз - мочь форвардить его в функции но запретить явно вызывать .release().
"константный" юник_птр бы решил все проблемы=)
Не очень понятен юзкейс. Можете пример привести.


Код:
unique_ptr<int> p = foo();
p.release(); // ok
bar(move(p)); // ok

Код:
const unique_ptr<int> p = foo();
p.release(); // !ok, не скомпилится, хорошо
bar(move(p)); // тоже !ok, а вот это было бы неплохо скомпилить

То есть по-хорошему нужен какой-то immutable_unique_ptr который нельзя занулить, но можно мувнуть. Такого нет и сделать стандартными средствами нельзя => возникает нужда в not_null.


Название: Re: Ненулевые указатели
Отправлено: Old от Ноябрь 11, 2019, 22:14
То есть по-хорошему нужен какой-то immutable_unique_ptr который нельзя занулить, но можно мувнуть.
Мувая указател в функцию, вы передаете все права на ресурс этой функции. При выходе из нее он удалится. Так какая разница, что там делает функция с этим ресурсом? Хочет релизить - пусть релизит.

Не хотите передавать права - отдавайте функции указатель по константной ссылке, она не сможет занулить.


Название: Re: Ненулевые указатели
Отправлено: ViTech от Ноябрь 12, 2019, 09:55
Код:
const unique_ptr<int> p = foo();
p.release(); // !ok, не скомпилится, хорошо
bar(move(p)); // тоже !ok, а вот это было бы неплохо скомпилить
То есть по-хорошему нужен какой-то immutable_unique_ptr который нельзя занулить, но можно мувнуть.

Тут попытка изменить константный объект, естественно он сопротивляется. Это ко всем типам относится, не только unique_ptr такой плохой. Если нужно обеспечить, чтобы в указателе всегда был какой-то объект, то это не обязательно связано с иммутабельностью. У него поведение может отличаться (нет release(), reset(nullptr) и прочее). При этом можно заменить управляемый объект на другой, сделать swap с другим указателем и т.д. Т.е. нужен именно какой-то not_null_unique_ptr.

Такого нет и сделать стандартными средствами нельзя => возникает нужда в not_null.
Если такого стандартного нет, значит нужно сделать нестандартный :).


Название: Re: Ненулевые указатели
Отправлено: Old от Ноябрь 12, 2019, 10:02
Т.е. нужен именно какой-то not_null_unique_ptr.
Для чего он нужен? Я не могу придумать юзкейс для него. :)


Название: Re: Ненулевые указатели
Отправлено: ViTech от Ноябрь 12, 2019, 10:49
Для чего он нужен? Я не могу придумать юзкейс для него. :)

Например, когда какой-то объект (составной/composite) уникально владеет точно одним другим объектом (частью/part) и нужно соблюдать целостность этой связи. Чтобы явно сказать, что в этом указателе точно есть объект, и не нужно этот указатель проверять на null, а можно сразу к нему обращаться. В отличие от optional_unique_ptr(std::unique_ptr), где объект может быть, а может и не быть, и тогда перед обращением к указателю его обязательно нужно проверить. Если обратиться к UML, то not_null_unique_ptr может реализовать конец ассоциативной связи с композитной агрегацией и кратностью [1..1], в то время как .  optional_unique_ptr тоже может реализовать композитную агрегацию, но уже с кратностью [0..1]. Как в этом примере (http://www.prog.org.ru/topic_32109_15.html).


Название: Re: Ненулевые указатели
Отправлено: Old от Ноябрь 12, 2019, 11:14
Например, когда какой-то объект (составной/composite) уникально владеет точно одним другим объектом (частью/part) и нужно соблюдать целостность этой связи. Чтобы явно сказать, что в этом указателе точно есть объект, и не нужно этот указатель проверять на null, а можно сразу к нему обращаться. В отличие от optional_unique_ptr(std::unique_ptr), где объект может быть, а может и не быть, и тогда перед обращением к указателю его обязательно нужно проверить. Если обратиться к UML, то not_null_unique_ptr может реализовать конец ассоциативной связи с композитной агрегацией и кратностью [1..1], в то время как .  optional_unique_ptr тоже может реализовать композитную агрегацию, но уже с кратностью [0..1]. Как в этом примере (http://www.prog.org.ru/topic_32109_15.html).
Не, я про перемещение указателя в функцию. Про то, о чем писал Аварон. :)


Название: Re: Ненулевые указатели
Отправлено: ViTech от Ноябрь 12, 2019, 11:41
Не, я про перемещение указателя в функцию. Про то, о чем писал Аварон. :)

А, ну судя по "нельзя занулить, но можно мувнуть", то, возможно, нужно выразить в типе параметра функции, что в этом указателе точно есть объект, можно не проверять на null, нельзя удалять объект из этого указателя (но можно ли заменить на другой?), как-то поработать с этим объектом, передать владеющий указатель дальше (в другую функцию, в поле класса, возможно в очередь команд/событий) и в текущей функции забыть про него. Т.е. функция может и не быть конечной остановкой. Такая у меня версия, но могут быть и другие :).


Название: Re: Ненулевые указатели
Отправлено: Old от Ноябрь 12, 2019, 14:02
Т.е. функция может и не быть конечной остановкой.
Функции отдали во владение объект, сказали делай с ним что хочешь. Выше по стеку этот объект никому не нужен.
Только функции решать, что сделать с этим объектом. Если нужно отдать дальше, то она не будет его удалять.

Кого мы пытаемся ограничить этим функционалом, писателя функции? :)


Название: Re: Ненулевые указатели
Отправлено: Авварон от Ноябрь 12, 2019, 14:05
Кого мы пытаемся ограничить этим функционалом, писателя функции? :)

Кого мы пытаемся ограничить, запрещая писать gsl::not_null<int *> p = nullptr? Писателя функции?


Название: Re: Ненулевые указатели
Отправлено: Old от Ноябрь 12, 2019, 14:12
Кого мы пытаемся ограничить, запрещая писать gsl::not_null<int *> p = nullptr? Писателя функции?
Мы говорим о разном функционале.
Перемещение unique_ptr в функцию != запрету передачи nullptr.
Вы хотели запретив вызов release юника в функции добиться невозможности передачи nullptr в вызове вложенной функции?


Название: Re: Ненулевые указатели
Отправлено: ViTech от Ноябрь 12, 2019, 16:56
Функции отдали во владение объект, сказали делай с ним что хочешь. Выше по стеку этот объект никому не нужен.
Только функции решать, что сделать с этим объектом. Если нужно отдать дальше, то она не будет его удалять.

Кого мы пытаемся ограничить этим функционалом, писателя функции? :)

С точки зрения вызывающей функции да, неважно, что потом произойдёт с этим указателем, раз уж отдали владение объектом. Тут нужно выяснить, что в вызываемой функции будут делать с этим указателем. Запрет на release мне тоже не очень понятен: если можно перемещать указатель, то объект можно удалить раньше времени и без release/reset, переместив во временный указатель not_null_unique_ptr{move(p)}, в той же строке объект и помрёт :). Но это совсем не отменяет полезность not_null указателей :).


Название: Re: Ненулевые указатели
Отправлено: Old от Ноябрь 12, 2019, 17:00
Но это совсем не отменяет полезность not_null указателей :).
А я нигде про не полезность not_null не говорил. :)
Я был не очень согласен с претензиями к перемещаемому юнику.


Название: Re: Ненулевые указатели
Отправлено: Авварон от Ноябрь 12, 2019, 17:42
С перемещаемым юником всё хорошо) проблема с его мутабельностью - либо он мутабельный и перемещаемый, либо немутабельный и неперемещаемый.

На самом деле, с юником проблемы "нулевого" указателя обычно нет - он обычно создается через make_unique и если избегать явных вызовов .reset(), то всё будет хорошо.


Название: Re: Ненулевые указатели
Отправлено: Old от Ноябрь 12, 2019, 18:06
С перемещаемым юником всё хорошо) проблема с его мутабельностью - либо он мутабельный и перемещаемый, либо немутабельный и неперемещаемый.
У меня вызывает большие сомнения потребность в перемещаемом и немутабельном указателе. :)
Я не вижу сферу его применения.

Да и not_null мне будет полезен только с поддержкой компиляторами, когда они будут бесплатными. Сейчас мне приходится писать assert.
А не будет поддержки, ну и ладно, обойдусь без not_null. :)


Название: Re: Ненулевые указатели
Отправлено: ViTech от Ноябрь 12, 2019, 18:35
Да и not_null мне будет полезен только с поддержкой компиляторами, когда они будут бесплатными. Сейчас мне приходится писать assert.

А в чём сейчас платность gsl::not_null для сырых указателей (да и для умных, если его доделать по уму)? И чем not_null_unique_ptr будет платнее текущего std::unique_ptr? И что должно появиться в компиляторе, чтобы избежать этих плат? :)


Название: Re: Ненулевые указатели
Отправлено: Old от Ноябрь 12, 2019, 18:46
А в чём сейчас платность gsl::not_null для сырых указателей (да и для умных, если его доделать по уму)? И чем not_null_unique_ptr будет платнее текущего std::unique_ptr? И что должно появиться в компиляторе, чтобы избежать этих плат? :)
Так сейчас это тот же assert по сути. Платим проверкой. Причем проверка эта на каждое разименование. У меня assert один раз выполняется. :)
А если компилятор будет их выкидывать, то это будет хоть что-то. :)

У меня не стоит остро проблема проверки указателей на nullptr. Я очень активно использую ссылки, стараюсь продумывать владения, время создания и разрушения объектов. Поэтому, как-то для меня это не проблема. :)


Название: Re: Ненулевые указатели
Отправлено: ViTech от Ноябрь 12, 2019, 19:01
Так сейчас это тот же assert по сути. Платим проверкой. :)
А если компилятор будет их выкидывать, то это будет хоть что-то. :)

Дело там не только в assert. Некоторые операции удалены. Например, конструктор по умолчанию, конструктор из nullptr, оператор присваивания из nullptr, и т.п. Т.е. уже на этапе compile-time можно многие вещи уладить, не дожидаясь, когда в run-time assert выбьет. И выразительность кода намного выше, по сигнатуре функции понятно, какая сущность ей нужна, assert'ы внутри функции могут быть и не видны читателю.

Нагрузка на компилятор, скорей всего, возрастёт, но в оптимизированный release run-time может выйти уже без платы.


Название: Re: Ненулевые указатели
Отправлено: Авварон от Ноябрь 12, 2019, 19:14
Ну в .get() проверка не нужна, так как operator= "реализован" через implicit ктор от T и уже там есть проверка, т.е. нельзя nullptr присвоить.
Я так понял, эта проверка там с давних времен и пока не убрана "как бы чего не случилось".
Так как не ясно что этот get() должен возвращать для вумных указателей - ну а вдруг там будет ссылка на вумный указатель и можно сделать .get().release()?
Так-то да, сейчас эта проверка просто оверхед безо всяких бонусов (так как вумные не поддерживаются до конца).


Название: Re: Ненулевые указатели
Отправлено: Old от Ноябрь 12, 2019, 19:20
Т.е. уже на этапе compile-time можно многие вещи уладить, не дожидаясь, когда в run-time assert выбьет.
Я уже и не припомню, когда эти ассерты срабатывали. Ставлю их на автомате.
Вот перебираю в голове свои проекты... в основное массе мест, где точно нужен объект, используются ссылки. А в остальных местах, где используются указатели не представляю, что бы кто-то мог nullptr передать. По именам методов понятно, что например, в append( object_ptr obj ) нет нужды nullptr передавать. :)
А если все таки "талант" найдется, то по стеку возвратов после assert он легко находится и бьется. :)

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


Название: Re: Ненулевые указатели
Отправлено: ViTech от Ноябрь 12, 2019, 19:29
Ну в .get() проверка не нужна, так как operator= "реализован" через implicit ктор от T и уже там есть проверка, т.е. нельзя nullptr присвоить.
Я так понял, эта проверка там с давних времен и пока не убрана "как бы чего не случилось".

Способов сломать not_null не так уж и много. Один из - это разыменование указателя после его перемещения. Второй может связан со swap с перемещённым указателем, но это может быть и валидной операцией, по сути то же перемещение, как посмотреть. Про другие способы посильнее задуматься надо :). Но обращение к объекту после перемещение - это общая проблема, и может решаться статическими анализаторами. Когда такие созреют, assert в get можно и убрать. А сейчас он да, "на всякий случай".

Так как не ясно что этот get() должен возвращать для вумных указателей - ну а вдруг там будет ссылка на вумный указатель и можно сделать .get().release()?
Так-то да, сейчас эта проверка просто оверхед безо всяких бонусов (так как вумные не поддерживаются до конца).

Если честно, этот get() я бы вообще убрал :).


Название: Re: Ненулевые указатели
Отправлено: ViTech от Ноябрь 12, 2019, 19:43
По именам методов понятно, что например, в append( object_ptr obj ) нет нужды nullptr передавать. :)
А если все таки "талант" найдется, то по стеку возвратов после assert он легко находится и бьется. :)

Имя метода, всё таки, слабоватый аргумент, тип параметра выразительнее и может обеспечить больше гарантий. Это не только к входным параметрам относится, но и к результату. Тогда  и по стеку после assert'ов намного меньше придётся лазить. Не все же такие дисциплинированные, как вы :). Да и профи может устать, а компилятор ему сразу подскажет, где он не прав :).


Название: Re: Ненулевые указатели
Отправлено: Old от Ноябрь 12, 2019, 20:01
а компилятор ему сразу подскажет, где он не прав :).
Я только за помощь компилятора + он эти проверки может сделать эффективней меня.
Будет поддержка в компиляторе буду всеми руками использовать. :)


Название: Re: Ненулевые указатели
Отправлено: _Bers от Ноябрь 28, 2019, 22:27
Но это совсем не отменяет полезность not_null указателей :).

и зачем он нужен?





Название: Re: Ненулевые указатели
Отправлено: ViTech от Ноябрь 29, 2019, 11:55
Но это совсем не отменяет полезность not_null указателей :).

и зачем он нужен?

А затем (http://www.prog.org.ru/index.php?topic=32554.msg240547#msg240547).


Название: Re: Ненулевые указатели
Отправлено: _Bers от Ноябрь 29, 2019, 23:43
А затем (http://www.prog.org.ru/index.php?topic=32554.msg240547#msg240547).

ну и зачем нужно такое "затем"?

если ожидается работа с реальным объектом,
тогда нужно использовать ссылку, а не указатель.

зачем изобретать указатель, который делает вид,
что он ссылка?



Название: Re: Ненулевые указатели
Отправлено: ViTech от Ноябрь 30, 2019, 12:55
зачем изобретать указатель, который делает вид,
что он ссылка?

Указателю, после инициализации, можно присваивать другие значения, в отличие от ссылки, которую после инициализации уже нельзя связать с другим объектом. Кроме того, SomeClass&  и, например, not_null<unique_ptr<SomeClass>> выражают совершенно разный тип связи с объектом.


Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 01, 2019, 16:17
Указателю, после инициализации, можно присваивать другие значения, в отличие от ссылки, которую после инициализации уже нельзя связать с другим объектом.

это не проблема,
потому что никак не мешает использовать ссылочную семантику.
ссылочная семантика - связь с априори валидным объектом.

похоже, что ваш not_null - это ещё один способ организации такой связи.

вот только мне не понятно: зачем он нужен то?
всмысле, зачем вообще привлекать ещё какие то дополнительные инструменты,
если желаемое итак можно получить используя обычные ссылки и указатели?


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

тогда:

Код:
struct child
{
    child(parent& object) noexcept
        : m_parent(&object)
    {}

    parent& getParent() noexcept
    {
         return *this->m_parent;
    }

    void setParent(parent& object) noexcept
    {
        this->m_parent = &parent;
    }
    void work()
    {
         // указатель  this->m_parent априори валидный
    }
private:
    parent* m_parent;
};

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


Кроме того, SomeClass&  и, например, not_null<unique_ptr<SomeClass>> выражают совершенно разный тип связи с объектом.

нет, не разный.

SomeClass& - ссылочная семантика
связь с валидным объектом.

not_null<SomeClass>  - тоже ссылочная семантика.
потому что так же подразумевает связь с валидным объектом.


первый вариант простой, понятный и логичный.

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

однако в обоих случаях семантика связи - одинаковая.


Название: Re: Ненулевые указатели
Отправлено: Авварон от Декабрь 02, 2019, 11:52
Ссылка не позволяет реализовать композицию. Композицию позволяет реализовать мембер, но с ним проблемы с присваиванием - надо "писать правильно" и делать мув конструктор. Поди объясни это кутешникам.
Разделяемое владение мембер не позволяет реализовать (потому что нет перегрузки оператора., была бы, сделали бы "шаредную ссылку" и было бы счастье).
Получается что часть объектов по значению и доступ через точку, половина через указатель и доступ через стрелочку.
А когда было уникальное владение через мембер и надо сделать шаредное, начинаются пляски с заменой точки на стрелочку, вот это чем хочется заниматься конечно и ревьювить потом.
Еще у ссылок есть неприятное свойство мимикрировать мод мемберы - я как-то сделал большой патч по передаче объектов черех мув в ктор, а там ВНЕЗАПНО одна мапа объявлена не как мембер, а ссылка (оптимизаторы хреновы). И ни один компилятор мне не сказал мне что я присваиваю временный объект в ссылку и ни один санитайзер это не отловил.
К счастью, clang-tidy подсвечивает как неоптимальное место (типа нафига ты копируешь если в ссылку присваиваешь, передавай ссылку, так быстрее)


Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 02, 2019, 12:13
Ссылка не позволяет реализовать композицию. Композицию позволяет реализовать мембер, но с ним проблемы с присваиванием - надо "писать правильно" и делать мув конструктор. Поди объясни это кутешникам.
Разделяемое владение мембер не позволяет реализовать (потому что нет перегрузки оператора., была бы, сделали бы "шаредную ссылку" и было бы счастье).
Получается что часть объектов по значению и доступ через точку, половина через указатель и доступ через стрелочку.
А когда было уникальное владение через мембер и надо сделать шаредное, начинаются пляски с заменой точки на стрелочку, вот это чем хочется заниматься конечно и ревьювить потом.
Еще у ссылок есть неприятное свойство мимикрировать мод мемберы - я как-то сделал большой патч по передаче объектов черех мув в ктор, а там ВНЕЗАПНО одна мапа объявлена не как мембер, а ссылка (оптимизаторы хреновы). И ни один компилятор мне не сказал мне что я присваиваю временный объект в ссылку и ни один санитайзер это не отловил.
К счастью, clang-tidy подсвечивает как неоптимальное место (типа нафига ты копируешь если в ссылку присваиваешь, передавай ссылку, так быстрее)

не распарсил этот поток сознания.
ты б хоть примеры привел, поясняющие.


Название: Re: Ненулевые указатели
Отправлено: Авварон от Декабрь 02, 2019, 12:30
не распарсил этот поток сознания.
ты б хоть примеры привел, поясняющие.


Меняем юник
Код:
class Foo
{
public:
    using BarPtr = std::unique_ptr<Bar>;
    void setBar(BarPtr bar) { m_bar = std::move(bar); }
    void doBaz() { m_bar->baz(); }

    BarPtr m_bar;
};
на шаред

Код:
class Foo
{
    using BarPtr = std::shared_ptr<Bar>; // поменялось раз
    void setBar(BarPtr bar) { m_bar = std::move(bar); }
    void doBaz() { m_bar->baz(); }

    BarPtr m_bar;
};

Меняем мембер

Код:
class Foo
{
public:
    void setBar(Bar &&bar) { m_bar = std::move(bar); }
    void doBaz() { m_bar.baz(); }
private:
    Bar m_bar;
};

на шаред

Код:
class Foo
{
    using BarPtr = std::shared_ptr<Bar>; // добавилось
    void setBar(BarPtr bar) { m_bar = std::move(bar); } // поменялось раз
    void doBaz() { m_bar->baz(); } // поменялось два (точка на ->)

    BarPtr m_bar; // поменялось три
};

Код приходится перелопачивать полностью тупо чтобы поменять юник на шаред.

Про чудесные ссылки, вот фикс (https://github.com/qbs/qbs/commit/491b293b07e59f69f2c8d9721ac6a098844d590d). Можете, глядя на дифф увидеть в чем была проблема? Нет? Я тоже не увидел. А оно вон оказывается как в хедере объявлено (https://github.com/qbs/qbs/blob/491b293b07e59f69f2c8d9721ac6a098844d590d/src/lib/corelib/buildgraph/rulesapplicator.h#L116)


Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 02, 2019, 13:06
Код приходится перелопачивать полностью тупо чтобы поменять юник на шаред.

я не понял смысла этих примеров.

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

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

Про чудесные ссылки, вот фикс (https://github.com/qbs/qbs/commit/491b293b07e59f69f2c8d9721ac6a098844d590d). Можете, глядя на дифф увидеть в чем была проблема? Нет? Я тоже не увидел. А оно вон оказывается как в хедере объявлено (https://github.com/qbs/qbs/blob/491b293b07e59f69f2c8d9721ac6a098844d590d/src/lib/corelib/buildgraph/rulesapplicator.h#L116)

проблема таких багов не в чудесных ссылках,
а в чудесных программистах.
которые, похоже, не заморачиваются думками о том,
что они делают.









Название: Re: Ненулевые указатели
Отправлено: ViTech от Декабрь 02, 2019, 13:09
это не проблема,
потому что никак не мешает использовать ссылочную семантику.
ссылочная семантика - связь с априори валидным объектом.
...
всмысле, зачем вообще привлекать ещё какие то дополнительные инструменты,
если желаемое итак можно получить используя обычные ссылки и указатели?

Такой вариант имеет право на существование, только, имхо, выворачивает наизнанку реализацию "связь с априори валидным объектом". Вместо того, чтобы один раз при объявлении поля класса указать, что оно не может быть пустым, и пусть компилятор это отслеживает, разработчики сами должны следить, чтобы в это поле не попала пустота. В конструкторах, сеттерах и прочем. Это вы сейчас знаете, что это поле не может быть пустым, а кто-нибудь другой и потом увидит, что тип поля - это простой указатель, и добавит метод, который принимает указатель. И всё, "алгоритм не работает (http://www.prog.org.ru/index.php?topic=32540.msg240631#msg240631)". Что тогда предлагаете делать? Уповать на то, что другие догадаются, что автор задумал поле непустым, хотя там обычный указатель? Или комментарий для поля писать: "The m_parent must be not_null."? :)

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

Давайте рассмотрим немного изменённый пример (https://coliru.stacked-crooked.com/a/9620feab02f424b6):
Код
C++ (Qt)
#include <iostream>
 
struct parent
{
   std::string name;
};
 
struct child
{
   child(const parent& mother, const parent& father) noexcept
       : m_mother{&mother}, m_father{&father}
   {}
 
   const parent& getMother() noexcept { return *this->m_mother; }
   const parent& getFather() noexcept { return *this->m_father; }
 
   void setParents(const parent& mother, const parent& father) noexcept
   {
       this->m_mother = &mother;
       this->m_father = &father;
   }
 
   void work()
   {
       std::cout << "mother: " << getMother().name << std::endl;
       std::cout << "father: " << getFather().name << std::endl;
   }
 
private:
   const parent* m_mother;
   const parent* m_father;
};
 
int main()
{
   parent mother{"Marfa"};
   parent father{"Miron"};
 
   child  son{mother, father};
   son.work();
 
   son.setParents(parent{"Stepanida"}, parent{"Stepan"});
   son.work();
 
   return 0;
}

С этим кодом всё хорошо? Никаких проблем нет?

Кроме того, SomeClass&  и, например, not_null<unique_ptr<SomeClass>> выражают совершенно разный тип связи с объектом.

нет, не разный.

SomeClass& - ссылочная семантика
связь с валидным объектом.

not_null<SomeClass>  - тоже ссылочная семантика.
потому что так же подразумевает связь с валидным объектом.

первый вариант простой, понятный и логичный.

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

однако в обоих случаях семантика связи - одинаковая.

А пошто вы unique_ptr на мороз выставили? :) Я же его специально туда добавил. not_null<unique_ptr<SomeClass>> при инициализации и присваивании должен проверять, что unique_ptr не пустой. И помимо выражения самого факта связи с существующим объектом, выражает ещё семантику владения этим объектом.


Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 02, 2019, 14:17
Такой вариант имеет право на существование, только, имхо, выворачивает наизнанку реализацию "связь с априори валидным объектом". Вместо того, чтобы один раз при объявлении поля класса указать, что оно не может быть пустым, и пусть компилятор это отслеживает,  разработчики сами должны следить, чтобы в это поле не попала пустота.

в том то и дело, что компилятор не сможет отследить.
это технически невозможно.
ты рантайм с компиляцией не перепутал?

Это вы сейчас знаете, что это поле не может быть пустым, а кто-нибудь другой и потом увидит, что тип поля - это простой указатель, и добавит метод, который принимает указатель.
маловероятно.
на каком основании он может захотеть добавить метод,
который принимает указатель, а не ссылку?

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

в первом случае: пьяный проспится, дурак - никогда.

а во втором, класс объективно нужно переписывать, и тестить.
логика должна учитывать, что правила игры изменились.
но даже в этом случае нет ни одной причины использовать указатель в аргументах.

хочешь создать сироту? используй конкструктор вообще без параметров.
хочешь лишить ребенка родителя? используй метод removeParent()

указатели для этого не нужны.

Давайте рассмотрим немного изменённый пример (https://coliru.stacked-crooked.com/a/9620feab02f424b6):
С этим кодом всё хорошо? Никаких проблем нет?
замени ссылки на указатели - получишь те же яйца.
какой тогда смысл обсуждать это?

А пошто вы unique_ptr на мороз выставили? :)

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

если фабрика хочет вернуть объект,
то почему нельзя вернуть просто по значению?

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



Название: Re: Ненулевые указатели
Отправлено: Igors от Декабрь 02, 2019, 15:22
И всё, "алгоритм не работает (http://www.prog.org.ru/index.php?topic=32540.msg240631#msg240631)". Что тогда предлагаете делать? Уповать на то, что другие догадаются, что автор задумал поле непустым, хотя там обычный указатель? Или комментарий для поля писать: "The m_parent must be not_null."? :)
"Почему нет, Леня? (АО МММ)". Ну не догадался (уповал), ну и чем это грозит? Ах, боже мой, получу вылет!!! Да я был бы счастлив иметь такие ошибки :) Здравый коммент Can (not) be NULL никак не хуже очередной лабуды которую надо запоминать. На работу алгоритма это никак не влияет, там вес таких свистелок-перделок даже не 1%.


Название: Re: Ненулевые указатели
Отправлено: Авварон от Декабрь 02, 2019, 15:27
Ах, боже мой, получу вылет!!!

Не получите, разыменование нулевого указателя это UB а не "вылет".


Название: Re: Ненулевые указатели
Отправлено: ViTech от Декабрь 02, 2019, 16:22
в том то и дело, что компилятор не сможет отследить.
это технически невозможно.
ты рантайм с компиляцией не перепутал?

Нет, не перепутал. В случае с not_null на то, что можно выявить в compile-time, будет выведена ошибка компиляции. Для runtime в not_null будут assert'ы или contract conditions (когда их таки добавят в стандарт), а не разработчики сами их будут везде расставлять. Тип not_null даст дополнительную информацию статическим анализаторам для более детальной диагностики, если компилятор себе такое позволить не сможет.

маловероятно.
на каком основании он может захотеть добавить метод,
который принимает указатель, а не ссылку?

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

в первом случае: пьяный проспится, дурак - никогда.

а во втором, класс объективно нужно переписывать, и тестить.
логика должна учитывать, что правила игры изменились.
но даже в этом случае нет ни одной причины использовать указатель в аргументах.

хочешь создать сироту? используй конкструктор вообще без параметров.
хочешь лишить ребенка родителя? используй метод removeParent()

указатели для этого не нужны.

Можно было ответить короче: уповать.

замени ссылки на указатели - получишь те же яйца.
какой тогда смысл обсуждать это?

Так проблем нет, вы про них не знаете, или не хотите озвучивать? Сами сначала замените и посмотрите, получится то же самое или нет. Для начала на обычный указатель, потом на gsl::not_null (https://github.com/microsoft/GSL), хоть и в том состоянии, в котором он находится сейчас.

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

если фабрика хочет вернуть объект,
то почему нельзя вернуть просто по значению?

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

Как предлагаете переписать такую абстрактную фабрику, как например QItemEditorFactory (https://doc.qt.io/qt-5/qitemeditorfactory.html), чтобы она возвращала объекты по значению? Тогда может и найдёте одну из причин существования юника.


Название: Re: Ненулевые указатели
Отправлено: ViTech от Декабрь 02, 2019, 16:34
"Почему нет, Леня? (АО МММ)". Ну не догадался (уповал), ну и чем это грозит? Ах, боже мой, получу вылет!!! Да я был бы счастлив иметь такие ошибки :) Здравый коммент Can (not) be NULL никак не хуже очередной лабуды которую надо запоминать. На работу алгоритма это никак не влияет, там вес таких свистелок-перделок даже не 1%.

Это я в общем про подход, когда один что-то неявно подразумевает, а другие должны об этом догадаться, не обязательно про указатели. У Вас, похоже, случилось то самое "маловероятно", раз Char от бессилия падает на задницу, вместо того, чтобы бодро бегать :).


Название: Re: Ненулевые указатели
Отправлено: Авварон от Декабрь 02, 2019, 16:54
замени ссылки на указатели - получишь те же яйца.
какой тогда смысл обсуждать это?

То есть вы часто пишете код вида?
Код:
son.setParents(&parent{"Stepanida"}, &parent{"Stepan"});

Оно вообще скомпилируется?


Название: Re: Ненулевые указатели
Отправлено: Igors от Декабрь 03, 2019, 14:12
Не получите, разыменование нулевого указателя это UB а не "вылет".
Т.е. будет "принят"(?) какой-то разумный/существующий адрес, а по нему будет сидеть объект именно нужного типа, и все покатится дальше? Вам это не напоминает "сказки про белого бычка"? :)

Это я в общем про подход, когда один что-то неявно подразумевает, а другие должны об этом догадаться, не обязательно про указатели.
Да, и это нормально. См хотя бы std::vector, разве он не предполагает что эл-ты идут подряд, что вставка/удаление может сделать итераторы невалидными и.т.п.? Разве это подтверждается какой-то "семантикой"? Попытки сделать все явным (по объявлению ясно) - в принципе дело хорошее, но в меру, не стоит гнаться за недостижимым. 

У Вас, похоже, случилось то самое "маловероятно", раз Char от бессилия падает на задницу, вместо того, чтобы бодро бегать :).
Поверьте, все эти цацки-пецки к работе не имеют отношения. Ну вот НИКАКОГО. Можно написать все "на голых", можно все "на вумных" - на рез-т это никак не повлияет и ни одного бага не выявит. Будет всего лишь "более или менее удобно" (и то смотря для кого). В расчетных задачах (где тех классов всего лишь десяток-другой) вообще пофиг.

Да, и заниматься такими "общими" (концептуальными) вещами легко м приятно :) Это ж не сидеть неделями в отладчике, не отвечать за рез-т, так... "повышать повышаемость"  :)


Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 03, 2019, 14:26
Нет, не перепутал. В случае с not_null на то, что можно выявить в compile-time, будет выведена ошибка компиляции. Для runtime в not_null будут assert'ы или contract conditions (когда их таки добавят в стандарт), а не разработчики сами их будут везде расставлять. Тип not_null даст дополнительную информацию статическим анализаторам для более детальной диагностики, если компилятор себе такое позволить не сможет.

ты понимаешь, что твоё "то, что можно выявить в compile-time" - это менее 1% всех реальных кейсов использования?
в то время как на долю рантайма придётся больше 99% ?

в этом свете твоё заявление: "пусть компилятор это отслеживает" - звучит как жульнический маркетинг сивой кобылы.

Можно было ответить короче: уповать.
не распарсил эту фразу.

на что уповать? что новенький не окажется балбесом что ли?
для этого человечество изобрело собеседования и code-review.


Так проблем нет, вы про них не знаете, или не хотите озвучивать? Сами сначала замените и посмотрите, получится то же самое или нет. Для начала на обычный указатель, потом на gsl::not_null (https://github.com/microsoft/GSL), хоть и в том состоянии, в котором он находится сейчас.

немножко неочевидна такая твоя реакция.
ты сам то смотрел?

или может ты просто не догоняешь?

в обоих случаях будет взят указатель или ссылка на временный объект.
в обоих случаях ты получишь UB

указатель:
https://rextester.com/KOASHD96152


ссылка:
https://rextester.com/QIPI41754


просто код нужно писать грамотно:
https://rextester.com/LLDG51891

вот ты в качестве примера привел проблему,
которая с твоим not_null вообще никак не коррелирует.


Как предлагаете переписать такую абстрактную фабрику, как например QItemEditorFactory (https://doc.qt.io/qt-5/qitemeditorfactory.html), чтобы она возвращала объекты по значению? Тогда может и найдёте одну из причин существования юника.

нафига????
это - не твоя фабрика.
зачем её переписывать?

Код:
auto* object = api::create();
assert(object);
work(*object);   // <--- это так сложно?




Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 03, 2019, 14:28
То есть вы часто пишете код вида?
Код:
son.setParents(&parent{"Stepanida"}, &parent{"Stepan"});
с чего ты взял своё "то есть" ?

Оно вообще скомпилируется?


https://rextester.com/KOASHD96152


Название: Re: Ненулевые указатели
Отправлено: Old от Декабрь 03, 2019, 14:33
Это ж не сидеть неделями в отладчике
Вот он признак "профессионализма". :)


Название: Re: Ненулевые указатели
Отправлено: ViTech от Декабрь 03, 2019, 15:13
ты понимаешь, что твоё "то, что можно выявить в compile-time" - это менее 1% всех реальных кейсов использования?
в то время как на долю рантайма придётся больше 99% ?

Это вы такое процентное соотношение придумали, зачем мне его понимать? Я считаю, что нормальный компилятор побольше может. По крайней избавит от получения висячего указателя на ровном месте.

Можно было ответить короче: уповать.
не распарсил эту фразу.

Сложности с отслеживанием нити разговора?
Что тогда предлагаете делать? Уповать на то, что другие догадаются, что автор задумал поле непустым, хотя там обычный указатель? Или комментарий для поля писать: "The m_parent must be not_null."? :)

немножко неочевидна такая твоя реакция.
ты сам то смотрел?

или может ты просто не догоняешь?

в обоих случаях будет взят указатель или ссылка на временный объект.
в обоих случаях ты получишь UB

указатель:
https://rextester.com/KOASHD96152

Мда... не зря я недолюбливаю майкрософтовский компилятор  :D. Попробуйте собрать этот код в gcc или clang.

просто код нужно писать грамотно:
https://rextester.com/LLDG51891

Ага, каждый раз писать лабуду типа "static_assert(!::std::is_rvalue_reference<parent&&>::value, "temporary objects prohibited"); это "просто" :).

По публичному интерфейсу:
Код
C++ (Qt)
struct child
{
   template<class parent>
   child(parent&& mother, parent&& father) noexcept;
 
   template<class parent>
   void setParents(parent&& mother, parent&& father) noexcept;
 
   ...
};

пользователи класса подумают, что могут передавать объекты в любом виде (по значению, по lvalue ссылке, по rvalue ссылке), а на деле окажется что не в любом. Откуда они узнают, в каком виде нельзя передавать? Наугад перебирать разные типы и смотреть, скомпилируется или нет? Или придётся лезть в исходники этого "грамотного" кода и разбирать его? Очень "понятно и логично".

вот ты в качестве примера привел проблему,
которая с твоим not_null вообще никак не коррелирует.

Напрямую коррелирует. Вариант с gsl::not_null вы, похоже, так и не пробовали. Даже интересно, как майкрософтовский компилятор там себя поведёт.


Как предлагаете переписать такую абстрактную фабрику, как например QItemEditorFactory (https://doc.qt.io/qt-5/qitemeditorfactory.html), чтобы она возвращала объекты по значению? Тогда может и найдёте одну из причин существования юника.

нафига????
это - не твоя фабрика.
зачем её переписывать?

Чтобы долго не объяснять, что такое "абстрактная фабрика (https://ru.wikipedia.org/wiki/%D0%90%D0%B1%D1%81%D1%82%D1%80%D0%B0%D0%BA%D1%82%D0%BD%D0%B0%D1%8F_%D1%84%D0%B0%D0%B1%D1%80%D0%B8%D0%BA%D0%B0_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F))". Поэтому и написал "такую абстрактную фабрику, как например QItemEditorFactory (https://doc.qt.io/qt-5/qitemeditorfactory.html)". Не именно её, а "такую как", чтобы был наглядный пример перед глазами. Не думал, что с пониманием этого предложения могут возникнуть сложности.


Название: Re: Ненулевые указатели
Отправлено: ViTech от Декабрь 03, 2019, 15:43
То есть вы часто пишете код вида?
Код:
son.setParents(&parent{"Stepanida"}, &parent{"Stepan"});
с чего ты взял своё "то есть" ?

Оно вообще скомпилируется?

https://rextester.com/KOASHD96152

Те не менее, вопрос актуальный. Вы часто берёте адрес временного объекта?


Название: Re: Ненулевые указатели
Отправлено: Авварон от Декабрь 03, 2019, 15:51
пользователи класса подумают, что могут передавать объекты в любом виде (по значению, по lvalue ссылке, по rvalue ссылке), а на деле окажется что не в любом. Откуда они узнают, в каком виде нельзя передавать? Наугад перебирать разные типы и смотреть, скомпилируется или нет? Или придётся лезть в исходники этого "грамотного" кода и разбирать его? Очень "понятно и логично".

Код, блин, у него, грамотный....

https://rextester.com/ISZFW96211


Название: Re: Ненулевые указатели
Отправлено: ViTech от Декабрь 03, 2019, 16:30
Код, блин, у него, грамотный....

https://rextester.com/ISZFW96211

Код
C++ (Qt)
void setParents(parent&& mother, parent&& father) noexcept = delete;

Этого недостаточно, нужно больше "delete" :). А так "просто", да. Никакой лишней писанины :).


Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 07, 2019, 15:30
Это вы такое процентное соотношение придумали, зачем мне его понимать? Я считаю, что нормальный компилятор побольше может. По крайней избавит от получения висячего указателя на ровном месте.

чувак, ты нормальнывй вообще?
99,(9) данных известны только в рантайме.

Сложности с отслеживанием нити разговора?

да. мне сложно отслеживать направление твоей мысли по односложным ответам.
у меня создалось впечатление,
что направление твоей мысли - задом-на-перед.

я предлагаю использовать ссылки там,
где ожидается работа с реальным объектом
и вообще не иметь проблем с невалидными указателями.

ты же считаешь вещь полезной на случай,
если найдется такой идиот, который зачем то сначала решит использовать указатель,
а затем нужно ему помочь не налажать с nullptr

Что тогда предлагаете делать? Уповать на то, что другие догадаются, что автор задумал поле непустым, хотя там обычный указатель? Или комментарий для поля писать: "The m_parent must be not_null."? :)


да.
я уповаю на то, что парень которого я взял в команду
догадается как правильно работать с нашей кодовой базой.

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

в чем ущербность not_nul подхода?
глупо и бессмысленно пытаться делать защиту от идиотов.

Мда... не зря я недолюбливаю майкрософтовский компилятор  :D. Попробуйте собрать этот код в gcc или clang.
суть в том, что на практике в обоих случаях (и с ссылками, и с указателями) можно ничайно допустить ошибку.
суть в том, что есть простой способ превентивно не позволить программисту допустить ошибку.

способ простой и кросс-платформенный.
просто используй ссылки там,
где по смыслу нужно работать с реальным объектом,
и если объект не должен быть временным - просто запрети временные.

обратил внимание: звучит как Капитанство?

Ага, каждый раз писать лабуду типа "static_assert(!::std::is_rvalue_reference<parent&&>::value, "temporary objects prohibited"); это "просто" :).

да. каждый раз.
если ты хочешь писать грамотный, надежный, качественный код.

вот пример из моего реального кода.
он очень простенький, но иллюстрирует идею.

Код:
    namespace detail
    {
        template<class s, dfor_lvalue_string(s&&)>
        constexpr decltype(auto) c_str(s&& text) noexcept
            { return text.c_str(); }

        template<class s, dfor_array_of_symbols(s)>
        constexpr decltype(auto) c_str(const s& arr) noexcept
            { return arr; }

        template<class s, dfor_pointer_to_symbol(s)>
        constexpr auto c_str(const s& ptr) noexcept -> const auto*
        {
            assert(ptr);
            return ptr;
        }

    } //namespace detail

обрати внимание: тут не статик_ассерт,
здесь концепт, основанный на SFINAE

если бы чувак смог ничайно запихать временную строку,
то в результате он бы получил указатель на уже протухший объект.

однако концепт dfor_lvalue_string исключает функцию из компиляции
если ей передать rvalue. ничайная ошибка полностью исключена.

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

это не просто увеличивает читабельность кода.
это позволяет исключить саму возможность ошибки.

концепты позволяют недопустить саму возможность возникновения ошибки.
а не пытаются как твой not_null пытаться бороться с последствиями идиотизма.



По публичному интерфейсу:
Код
C++ (Qt)
struct child
{
   template<class parent>
   child(parent&& mother, parent&& father) noexcept;
 
   template<class parent>
   void setParents(parent&& mother, parent&& father) noexcept;
 
   ...
};

пользователи класса подумают, что могут передавать объекты в любом виде (по значению, по lvalue ссылке, по rvalue ссылке)

нет, не подумают.
если, конечно, у пользователей нет шизофрении,
и они не больны клиническим идиотизмом.

обычно, психически здоровые пользователи класса child знают,
что это за класс, и зачем он нужен.
они осознают, что они пытаются сделать.

вот нафига вообще может понадобится передавать ребенку временный объект родителя???
как такое вообще может прийти в голову?

от ничайных ошибок защитит статик-ассерт.


Напрямую коррелирует. Вариант с gsl::not_null вы, похоже, так и не пробовали. Даже интересно, как майкрософтовский компилятор там себя поведёт.

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

https://rextester.com/DPGZ73051

а поскольку, сейчас мне очевидно, что этот инструмент не нужнен,
то я не стал утруждать себя думками как заставить его работать.

но ты можешь сам продемонстрировать:
предоставить код и ссылку на он-лайн компилятор.

онлайн rextester умеет жоссии, шланг, и студийный каэль.

Чтобы долго не объяснять, что такое "абстрактная фабрика (https://ru.wikipedia.org/wiki/%D0%90%D0%B1%D1%81%D1%82%D1%80%D0%B0%D0%BA%D1%82%D0%BD%D0%B0%D1%8F_%D1%84%D0%B0%D0%B1%D1%80%D0%B8%D0%BA%D0%B0_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F))". Поэтому и написал "такую абстрактную фабрику, как например QItemEditorFactory (https://doc.qt.io/qt-5/qitemeditorfactory.html)". Не именно её, а "такую как", чтобы был наглядный пример перед глазами. Не думал, что с пониманием этого предложения могут возникнуть сложности.

человек, ты идею то вразумел, нет?

тебе не нужен not_null, что бы гарантировать, что выданнный сторонним апи объект валидный.

просто получи его на руки.
тут же проверь валидность.
а дальше используй по обычной схеме: где нужен объект, туда передаём ссылку.

И ФСЁЁЁ.


казадлось бы, и причем тут какие то абстрактные фабрики?


Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 07, 2019, 15:33
Те не менее, вопрос актуальный. Вы часто берёте адрес временного объекта?

не может этот вопрос быть аутальным,
потому что никто в здравом уме не берет адрес временного объекта.


с тобой всё в порядке?
может устал, отдохнуть надо?


Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 07, 2019, 15:35
пользователи класса подумают, что могут передавать объекты в любом виде (по значению, по lvalue ссылке, по rvalue ссылке), а на деле окажется что не в любом. Откуда они узнают, в каком виде нельзя передавать? Наугад перебирать разные типы и смотреть, скомпилируется или нет? Или придётся лезть в исходники этого "грамотного" кода и разбирать его? Очень "понятно и логично".

Код, блин, у него, грамотный....

https://rextester.com/ISZFW96211


и что тебе, блин, не понравилось в моём грамотной подходе?


твой вариант содержит деффект.
он пропустит баг, если скомбинировать rvalue и lvalue

Код:
    son.setParents(mother, parent{"Stepan"}); // <--- rvalue and lvalue


Код:
#include <iostream>
#include <string>

struct parent
{
    parent(const std::string& n)
        : name(n)
    {
        std::cout << "parent(" << name << "): was built\n";
    }
    
    ~parent()
    {
        std::cout << "parent(" << name << "): was destroyed\n";
    }
    std::string name;
};

struct child
{
    
    template<class parent>
    child(parent&& mother, parent&& father) noexcept
        : m_mother(), m_father()
    {
        this->setParents(
            ::std::forward<parent>(mother),
            ::std::forward<parent>(father)
        );
    }

    const parent& getMother() noexcept { return *this->m_mother; }
    const parent& getFather() noexcept { return *this->m_father; }

    void setParents(parent&& mother, parent&& father) noexcept = delete;
    void setParents(const parent& mother, const parent& father) noexcept
    {
        this->m_mother = &mother;
        this->m_father = &father;
    }

    void work()
    {
        std::cout << "mother: " << getMother().name << std::endl;
        std::cout << "father: " << getFather().name << std::endl;
    }

private:
    const parent* m_mother;
    const parent* m_father;
};

int main()
{
    parent mother{"Marfa"};
    parent father{"Miron"};

    child  son{mother, father};
    son.work();

    son.setParents(mother, parent{"Stepan"}); // <--- rvalue and lvalue
    son.work();

    return 0;
}



Название: Re: Ненулевые указатели
Отправлено: Авварон от Декабрь 07, 2019, 16:06

и что тебе, блин, не понравилось в моём грамотной подходе?


твой вариант содержит деффект.
он пропустит баг, если скомбинировать rvalue и rvalue

Да, я был в курсе, когда писал код. Проблема в том, что шаблоны в этой задаче нахрен не нужны, как и статик ассерты.
Как и в последующих примерах.
А потом ноют что код компилируется сто лет и требуют модулей :D

А так, как я уже говорил, пример со ссылками высосан из пальца, он работает в ограниченном числе случаев и ровно никак не решает никаких проблем.

Код:
bool filterFoo(const Foo &foo) { ... } // ну ок, тут ссылка по делу
void processFoo(shared_ptr<Foo> foo)
{
    // вот вы предлагаете перед разыменованием проверять, ну ок, вполне себе подход
    if (!foo)
       return;
    // ну разыменовали, никакого UB, всё круто
    if (filterFoo(*foo))
       return;
    // чтобы понятно, почему нельзя заюзать ссылку изначально, форвардим сигналом дальше, скажем, в иной тред
    // ну или в мапу кладем
    emit fooProcessed(foo);
}

Ну ок, мы решили проблему filterFoo, но processFoo всё равно должен проверять указатель - ведь могут же nullptr передать?

Сравним с
Код:
bool filterFoo(const Foo &foo) { ... }
void processFoo(not_null<shared_ptr<Foo>> foo)
{
    if (filterFoo(*foo)) // оппа, это больше не UB!
       return;
    ....
}

Магия, как же так вышло-то?
UB ушло уровнем выше - там где мы в gsl::not_null<Foo *> положили Foo * не проверив его на 0:
Код:
shared_ptr<Foo> foo = getFoo();
processFoo(foo); // ooops!


Название: Re: Ненулевые указатели
Отправлено: ViTech от Декабрь 07, 2019, 16:30
Ага, каждый раз писать лабуду типа "static_assert(!::std::is_rvalue_reference<parent&&>::value, "temporary objects prohibited"); это "просто" :).

да. каждый раз.
если ты хочешь писать грамотный, надежный, качественный код.

Характеристики варианта "ссылочная семантика" сменились с "простой, понятный и логичный" на "грамотный, надежный, качественный". Ибо, когда в сигнатуре функции из четырёх комбинаций параметров rvalue vs lvalue правильная только одна, а три приводят к ошибке, это не очень "понятно" и "логично". А каждый раз писать проверки - то уже и не "просто". Я вот предпочитаю, чтобы типы были выразительными, чтобы сразу было понятно что туда можно передавать, а что нельзя. И чтобы проверки были зашиты в типе, а не каждый раз их писать.

Кстати, как будете проверять виртуальные методы?
Код
C++ (Qt)
struct child
{
...
   virtual void setParents(not_null<parent> mother, not_null<parent> father) noexcept = 0;
...
};

Если вам лично не нужен unique_ptr, и как следствие not_null<unique_ptr>, это же не значит, что и другим они не нужны.


Название: Re: Ненулевые указатели
Отправлено: Авварон от Декабрь 07, 2019, 17:59
На самом деле, указатели просто более гибкие, чем ссылки. Пока ссылки не допилят до вменяемого уровня, все так и будут юзать указатели.

Вот табличка фич
Код:
# * &
0 + - // перегрузка операторов доступа содержимому объекта
1 + - // "умные" классы (следствие 0)
2 + - // возможность задавать семантику владения (следствие 1)
3 + - // опциональность (занулябельность), решается для ссылок типа optional<ref<T>>
4 - + // занулябельность, решается для указателей типа not_null<smart_ptr<T>>

То есть как видно ссылки проигрывают по фичам из-за отсутствия перегрузки оператора. (и "умных" ссылок со, гм, счетчиком ссылок).
При этом всё равно будут задачи, когда надо уметь положить nullptr, ака опциональная ссылка.
То есть, как ни крути, нужен либо not_null, либо optional_ref, в зависимости от выбранного поведения по умолчанию (разрешать ноль или запрещать).
Проблема в том, что ни того, ни другого в стандарте нет (ну типа можно сделать optional<ref<T>> и not_null<T*>, а что-то "умное" (ссылку/указатель) заюзать уже нельзя)


Название: Re: Ненулевые указатели
Отправлено: ViTech от Декабрь 07, 2019, 19:03
не может этот вопрос быть аутальным,
потому что никто в здравом уме не берет адрес временного объекта.

А вы в каком уме были, когда этот пример (https://rextester.com/KOASHD96152) писали? Зачем добавили операцию взятия адреса временного объекта? Варианты с указателем и gsl::not_null препятствуют передаче временного объекта в функцию. Без всяких статик ассертов, и, что самое удивительное, в compile-time. Да даже с этим взятием адреса, два из трёх компиляторов выдают ошибку. Чтобы добиться такого же поведения с "ссылочной семантикой", необходимо изувечить API класса и вручную понадобавлять проверок. Если для вас "замени ссылки на указатели - получишь те же яйца.", то для меня получаются совсем разные варианты.


Название: Re: Ненулевые указатели
Отправлено: ViTech от Декабрь 07, 2019, 19:35
Пока ссылки не допилят до вменяемого уровня, все так и будут юзать указатели.

С ссылками всё нормально, не надо их допиливать.
What is a reference? (https://isocpp.org/wiki/faq/references#overview-refs)
Цитировать
An alias (an alternate name) for an object.
...
Important note: Even though a reference is often implemented using an address in the underlying assembly language, please do not think of a reference as a funny looking pointer to an object. A reference is the object, just with another name. It is neither a pointer to the object, nor a copy of the object. It is the object. There is no C++ syntax that lets you operate on the reference itself separate from the object to which it refers.

Именно в таком качестве ссылки и нужно использовать. Когда функция принимает аргумент типа const Some&, то ожидается, что она будет "читать" этот объект или сделает его копию. Поэтому можно и временный объект передать, функция его скопирует и будет у неё not_null объект. Многие ли ожидают, что функция возьмёт адрес этого объекта для длительного хранения, чтобы потом к нему обратиться?

В ситуации с parent <-> child происходят несколько другие вещи. child'у не нужен сам объект parent, ему нужна ассоциативная связь с ним. Эту связь нужно отдельно создать. В самом простом случае, это взятие адреса объекта и помещение его в указатель. Так вот, с сигнатурой const Some& передаётся сам объект, и никто не разрешал создавать ассоциативные связи с ним. Впрочем, в текущем С++ никто и запретить не может :). Поэтому и появляются всякие "ссылочные семантики" с "грамотным" кодом.

Так что нужно допиливать именно указатели.


Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 07, 2019, 20:39
Да, я был в курсе, когда писал код. Проблема в том, что шаблоны в этой задаче нахрен не нужны, как и статик ассерты.
Как и в последующих примерах.
А потом ноют что код компилируется сто лет и требуют модулей :D

А так, как я уже говорил, пример со ссылками высосан из пальца, он работает в ограниченном числе случаев и ровно никак не решает никаких проблем.

ничего не понятно.
во-первых, о каком таком нытье идет речь?

во-вторых, что значит пример со ссылками высосан из пальца и работает в ограниченном числе случаев,
и каких таких проблем он ровно никак не решает?

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

человек, ты о чем вообще?



Название: Re: Ненулевые указатели
Отправлено: Авварон от Декабрь 07, 2019, 21:04
О том что ты взял выдуманный из пальца пример и его везде тычешь. Типа вот смотрите всё на ссылках ок. Хорошо, а парентом кто владеет? Мы должны догадаться что где-то есть мапа\вектор которая "овнит" детей и их родителей? Потому что в примере этого нет.
Вот пример ноды дерева понятен и самодостаточен - нода овнит детей. А тут? Привели в пример какой-то синтетический main() который иллюстрирует хрен знает что.
А так я бы посоветовал снизить градус, хуями в интернете я могу долго крыть, но мы же здесь не за этим?


Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 07, 2019, 22:05
Характеристики варианта "ссылочная семантика" сменились с "простой, понятный и логичный" на "грамотный, надежный, качественный".
Ибо, когда в сигнатуре функции из четырёх комбинаций параметров rvalue vs lvalue правильная только одна,
а три приводят к ошибке, это не очень "понятно" и "логично". А каждый раз писать проверки - то уже и не "просто".
Я вот предпочитаю, чтобы типы были выразительными, чтобы сразу было понятно что туда можно передавать, а что нельзя.
И чтобы проверки были зашиты в типе, а не каждый раз их писать.

ничего никуда не сменялось.
само понятие "ссылочная семантика" коррелирует с понятием "инвариант" примерно как "теплое" с "мягким"

судя по выразительному названию not_null,
это - инструмент, который не допустит нулевых указателей.
а вот был ли объект временным, это уже вне его компетенции.

и если ты будешь компилировать каэлем (компилятор Visual Studio)
то получишь адрес временного объекта точно так же,
как если бы это был самый обычный указатель с++.

и если ты хочешь, что бы твой код был не только логичным, но и надежным,
то ты не будешь передавать указатель туда,
где ждут реальный объект, а не его адрес.

и напишешь код, который не допустит rvalue там,
где их быть не должно.

Кстати, как будете проверять виртуальные методы?

не нужно ничего проверять.
на самом деле господин Авварон уже продемонстрировал идею:

Код:
struct base
{
    virtual ~base(){}
    virtual void foo(int&) = 0;
    virtual void foo(int&&) = delete;
};

Если вам лично не нужен unique_ptr, и как следствие not_null<unique_ptr>, это же не значит, что и другим они не нужны.

я не понимаю зачем он нужен другим.

единственное объяснение, которое у меня есть на сегодняшний день:

просто некоторые люди не осилили ссылки.
не понимают, чего они хотят.
склонны сначала создавать себе проблемы,  а потом героически их преодолевать.

А вы в каком уме были, когда этот пример (https://rextester.com/KOASHD96152) писали? Зачем добавили операцию взятия адреса временного объекта?

затем что бы ты наглядно увидел и понял:
технически, использование указателя само по себе никак не защитит тебя от ошибки взятия адреса временного объекта.
указатели в этом смысле так же уязвимы, как и ссылки.

и в обоих случаях в качестве защиты выступает здравый смысл.

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

Варианты с указателем и gsl::not_null препятствуют передаче временного объекта в функцию.

в том то и дело что не припятствует.
ты код самого not_null смотрел? там нет защиты от временных объектов.

если ты ещё не понял: тебя защищает не not_null, а компилятор gcc,
попробуй скомпилировать под visual studio, и осознай это.




Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 07, 2019, 22:14
О том что ты взял выдуманный из пальца пример и его везде тычешь. Типа вот смотрите всё на ссылках ок.

я могу взять любой пример,
где по смыслу требуется работать с реальным объектом,
суть не изменится.

человек захотел пронаблюдать ситуацию,
когда класс должен хранить именно указатель,
что бы иметь возможность связываться с различными объектами.
почему нет?

если тебе что-то не нравится - приведи свой пример.
а я посмотрю, как это у тебя получится.


Хорошо, а парентом кто владеет? Мы должны догадаться что где-то есть мапа\вектор которая "овнит" детей и их родителей? Потому что в примере этого нет.
Вот пример ноды дерева понятен и самодостаточен - нода овнит детей. А тут? Привели в пример какой-то синтетический main() который иллюстрирует хрен знает что.
А так я бы посоветовал снизить градус, хуями в интернете я могу долго крыть, но мы же здесь не за этим?

что за бред ты сейчас несешь?
ты пьяный что ли?



Название: Re: Ненулевые указатели
Отправлено: Авварон от Декабрь 08, 2019, 02:04

я не понимаю зачем он нужен другим.

единственное объяснение, которое у меня есть на сегодняшний день:

просто некоторые люди не осилили ссылки.
не понимают, чего они хотят.
склонны сначала создавать себе проблемы,  а потом героически их преодолевать.

ссылка - это observer_ptr
мембер класса - это аналог unique_ptr
аналога shared_ptr в "мире ссылок" тупо нет.

Ты втираешь какую-то дичь, предлагая заменить unique_ptr на ссылку.
Они вообще решают разные задачи. И кто тут теплое с мягким путает?


Название: Re: Ненулевые указатели
Отправлено: ViTech от Декабрь 08, 2019, 13:01
не нужно ничего проверять.
на самом деле господин Авварон уже продемонстрировал идею:
...

Если вы предлагаете на каждый not_null постоянно писать такое:
Код
C++ (Qt)
   virtual void setParents(const parent& mother, const parent& father) noexcept = 0;
   virtual void setParents(const parent& mother, parent&& father) = delete;
   virtual void setParents(parent&& mother, const parent& father) = delete;
   virtual void setParents(parent&& mother, parent&& father)      = delete;
и называете это "просто, понятно и логично", то у меня вопросов больше нет.

Я предпочитаю работать хотя бы с таким вариантом:
Код
C++ (Qt)
   virtual void setParents(gsl::not_null<const parent*> mother,
                           gsl::not_null<const parent*> father) noexcept = 0;

Остальные пусть сами решают, какой вариант им больше нравится. А может и другой какой предложат.


Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 08, 2019, 14:55
ссылка - это observer_ptr
мембер класса - это аналог unique_ptr
аналога shared_ptr в "мире ссылок" тупо нет.

по-моему, ты сам сейчас втираешь какую то дичь

Ты втираешь какую-то дичь, предлагая заменить unique_ptr на ссылку.
Они вообще решают разные задачи. И кто тут теплое с мягким путает?
я никогда не предлагал заменить юник на ссылку.

думаю, вчера ты был пьян.
иначе как ещё объяснить твоё нецензурно-агрессивное поведение,
и тот факт, что ты увидел того, чего нет?



Название: Re: Ненулевые указатели
Отправлено: Авварон от Декабрь 08, 2019, 15:37
с тобой всё в порядке?
может устал, отдохнуть надо?

То есть начал ты, а агрессивный я?


Название: Re: Ненулевые указатели
Отправлено: Авварон от Декабрь 08, 2019, 15:38

я никогда не предлагал заменить юник на ссылку.

Да, ты просто сказал что он нинужен и начал рассказывать о том как всё прекрасно делается на ссылках


Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 08, 2019, 15:40
Если вы предлагаете на каждый not_null постоянно писать такое:
Код
C++ (Qt)
   virtual void setParents(const parent& mother, const parent& father) noexcept = 0;
   virtual void setParents(const parent& mother, parent&& father) = delete;
   virtual void setParents(parent&& mother, const parent& father) = delete;
   virtual void setParents(parent&& mother, parent&& father)      = delete;
и называете это "просто, понятно и логично", то у меня вопросов больше нет.

не на каждый not_null
not_null вообще не нужен.

я предлагаю простой и логичный дизайн:
Код:
node.setParents(mother, father);

вместо нелогичного:
Код:
node.setParents(&mother, &father);

где ожидается работа с реальным объектом - должны быть реальные объекты,
а не указатели.

и тогда жизнь станет проще.

если тебе так впадлу написать 3 простых записи,
которые простым и понятным для читателя образом запретят rvalue,

ты можешь:
- задействовать шаблон вида:

Код:
#include <iostream>

struct node
{
    virtual ~node(){}
   
    template<class parent1, class parent2>
    void setParents(parent1&& mother, parent2&& father)
    {
        static_assert(
            !::std::is_rvalue_reference<parent1&&>::value,
            "temporary objects 'mother' prohibited"
        );
        static_assert(
            !::std::is_rvalue_reference<parent2&&>::value,
            "temporary objects 'father' prohibited"
        );
        const auto& m = static_cast<const node&>(mother);
        const auto& f = static_cast<const node&>(father);
        this->setParents(m, f);
    }   
    virtual void setParents(const node& mother, const node& father) = 0;
};

struct label: node
{
    virtual void setParents(const node&, const node&){}
};
 
int main()
{
    label mother;
    label father;
    label child;
    node& example = child;
   
    example.setParents(mother, father);
}

- задействовать концепт вида:

Код:
#include <iostream>

struct node
{
    virtual ~node(){}
   
    template<class parent1, class parent2, dfor_lvalue(parent1), dfor_lvalue(parent2) >
    void setParents(parent1&& mother, parent2&& father)
    {
        const auto& m = static_cast<const node&>(mother);
        const auto& f = static_cast<const node&>(father);
        this->setParents(m, f);
    }   
    virtual void setParents(const node& mother, const node& father) = 0;
};

struct label: node
{
    virtual void setParents(const node&, const node&){}
};
 
int main()
{
    label mother;
    label father;
    label child;
    node& example = child;
   
    example.setParents(mother, father);
}



- задействовать вспомогательный инструмент вида:

Код:
#include <iostream>

struct node
{
    virtual ~node(){}
   
    template<class p1, class p2>
    void setParents(lvalue<p1>& mother, lvalue<p2>& father)
    {
        const auto& m = static_cast<const node&>(mother);
        const auto& f = static_cast<const node&>(father);
        this->setParents(m, f);
    }   
    virtual void setParents(const node& mother, const node& father) = 0;
};

struct label: node
{
    virtual void setParents(const node&, const node&){}
};
 
int main()
{
    label mother;
    label father;
    label child;
    node& example = child;
   
    example.setParents(mother, father);
}

где lvalue<p1> - простенькая обертка над ссылками, которая отрезает rvalue

суть в том, что бы один раз по человечески исполнить базовый класс,

что бы в дальнейшем, разработчик наследников имел дело с простым и лаконичным
Код:
virtual void setParents(const node&, const node&){}

что бы пользователем класса было удобно и безопасно.

ты же пихаешь свой неадекватный not_null в любую дырку лишь потому,
что тебе впадлу написать несколько простых строчек.

самое удивительное:
ты так и не понял что ли?
not_null не защитит тебя от ошибок с временными объектами.

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

с таким отношение к разработке можешь сразу написать:

Код:
struct node
{
    virtual ~node(){}
    virtual void setParents(const node& mother, const node& father) = 0;
};

и не заморачиваться.
not_null от временных объектов не защищает.












Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 08, 2019, 15:47

я никогда не предлагал заменить юник на ссылку.

Да, ты просто сказал что он нинужен и начал рассказывать о том как всё прекрасно делается на ссылках

ау, человек!
ты в каких то своих фантазиях витаешь.
спускайся на землю.

мои цитаты о его ненужности были применимы по отношению к конкретным ситуациям.
я не утверждал, что not_null не нужен вообще.

и я нигде и никогда не утверждал, что "всё прекрасно делается на ссылках".
вот ты откуда этот бред взял?

и при чем тут юник то?
у тебя с логикой вообще как?







Название: Re: Ненулевые указатели
Отправлено: _Bers от Декабрь 08, 2019, 15:53
То есть начал ты, а агрессивный я?

эта безобидная реплика вообще не тебе адресованна была.
человек, которому она была адресованна отреагировал адекватно.

ты же ведешь себя как женщина.
или как маленький ребенок.
они такое любят: "он пееееервыыыыый наааачааааал!!!!"



Название: Re: Ненулевые указатели
Отправлено: Авварон от Декабрь 08, 2019, 15:57
То есть начал ты, а агрессивный я?

эта безобидная реплика вообще не тебе адресованна была.
человек, которому она была адресованна отреагировал адекватно.

ты же ведешь себя как женщина.
или как маленький ребенок.
они такое любят: "он пееееервыыыыый наааачааааал!!!!"



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


Название: Re: Ненулевые указатели
Отправлено: ViTech от Декабрь 08, 2019, 17:14
я не утверждал, что not_null не нужен вообще.

not_null вообще не нужен.

Это всё, что нужно знать о нашем грамотее. Сам не может уследить за своими потоками сознания. Наверняка у медиков есть подходящее название для этого.


Название: Re: Ненулевые указатели
Отправлено: Авварон от Декабрь 08, 2019, 17:24
Возвращаясь к теме, я подумал, что в обсуждаемом примере даже с забаненными временными объектами можно накосячить.

Код:
child getChild()
{
    parent mother("ma");
    parent father("pa");
    return child(mother, father);
}

Как viTech писал страницу-две назад, сигнатуры вида foo(const T&), foo(T), template<typename U> foo(U&&) подразумевают, что объект будет скопирован, а не взят его адрес.


Название: Re: Ненулевые указатели
Отправлено: ViTech от Декабрь 08, 2019, 17:53
Ещё нужно понимать разницу между самим объектом, и ассоциативной связью с ним. И что применение инструмента не по назначению (ссылки в "ссылочной семантике"), ведёт к грамотному коду костылестроению. Но не понять это могут не только лишь все :).