Template rp

  !   Данная информация предназначена только только для IT-специалистов по системной интеграции модулей БИОСОФТ-М. (см. Руководства пользователя к программным продуктам)

rp<> - это ссылка, которая либо хранит объект как ref<>, либо находится в состоянии null().

По умолчанию rp находится в нулевом состоянии. После присваивания ему ссылки ref или ненулевого указателя ptr он хранит в себе объект. Хранит даже если останется его единственным владельцем - аналогично обычной ref. Затем его можно снова обнулить или присвоить другой объект.

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

Префикс переменных: "rp".

Разименование rp

В стиле Islib невозможно использовать потенциально нулевую ссылку rp без явной обязательной проверки ее на ноль. Для rp работают конструкции

  • ifnot_null()
  • rp.AssertNotNull(...)
  • == null(), rp.IsNull(), !rp

точно так же как и для ptr.

Отношения с ptr

Ссылка rp может быть неявно преобразована в совместимый ptr или во избежание неоднозначностей явно с помощью метода rp.GetPtr().

Это в первую очередь ref а не ptr!

Важно понимать и помнить что rp напоминает ptr только поверхностно синтаксически но семантически это strong pointer! Внутри rp хранит собственную ссылку на объект. Он может создавать фатальные циклические зависимости ссылок вместе с ref.

По сути реализации rp это не более чем convenience class объединяющий ref + bool. И никакой существенной логики сверх этого.

Экспозиция

Замещая ref в качестве мембера не нулевой rp экспозируется в формате идентичном аналогичному ref.

В null состоянии rp отражается в экспозицию пустым unidef.

Создание конвертеров форматов в обе стороны предельно тривиально.

Особенности обнуления

Присваивание rp пустого ref или null() имеют совершенно разный эффект:

    rpXxx = null(); // force rpXxx into null state
 
    rpXxx = ref<CXxx>(); // assign empty object

В первом случае if not_null, AssertNotNull, и сравнения с null() будут детектировать нулевую ссылку. Во втором нет, в ней будет хранится изначально пустой объект.

Об этом надо помнить в неявном и сложном коде где вид присваивания может быть не очевиден:

    rpXxx = Func();

Если тип возвращаемого Func(); значения ref то один эффект, а ptr или rp может быть другой.

Еще способы обнулить rp:

    rpXxx = rp<CXxx>(); // same as = null()
 
    rpXxx = ptr<CXxx>(); // same as = null()
Преобразования типов

CastUp(rp) поддерживается.

ASSUME_IMPL_FOR_IFACE - Неявный CastUp в один Impl поддерживается. Но может вносить неоднозначность с неявным преобразованием в ptr и требовать явного, но безопасного приведения типа к базовому. В сложных случаях рекомендуется объявлять локальные переменные и делать все преобразования по шагам. Вникая на каком уровне refcount хранит объект (refrp) а на каком теряет (ptr).

Не злоупотреблять

Всегда когда это возможно следует предпочитать более простые инструменты решающие задачу. Как ref и ptr. Использование rp обосновано только когда к ref меберу приходится прилагать bool-флаг указывающий на его инициализированность. Этот флаг нужно не забывать проверять, отсюда буги...

В ситуациях, когда метод должен вернуть временный объект или null вовсе не обязательно хвататься за rp. Наши итераторы отлично работают возвращаяя bool и out ref&. Это и просто, однозначно и более развиваемо, особенно при увеличении количества возвращаемых параметров.

Тесты

CDebuxTestRpImpl.

Эта категория в данный момент пуста.