Есть ли законный способ перейти от gsl:: not_null<T>?

Введена библиотека поддержки рекомендаций not_null<T> кто имеет целью принудительное применение инварианта для типов, похожих на указатели, а также для интеллектуальных указателей. Однако это известная проблема, not_null<unique_ptr<T>> не работает

Насколько я понимаю, причина в том, что unique_ptr<T> не копируемо и not_null<T> не имеет конструктора, который переместился бы из его T. not_null<T> не может быть конструируемым по умолчанию, потому что это нарушит его инвариант. Даже если бы мы могли построить not_null<unique_ptr<T>>было бы невозможно осмысленно достичь unique_ptr внутри, потому что мы не могли скопировать unique_ptr и двигаясь это уйдет not_null<T> с nullptr. Это похоже на идеальную ловушку.

Я утверждал, что мы могли бы на законных основаниях перейти от not_null<T> объект в определенном контексте: непосредственно перед тем, как он выходит из области видимости. Другими словами, выход из него должен быть последним доступом перед уничтожением. Таким образом, объект с нарушенным инвариантом не будет заметен для остальной части программы. (Это было бы заметно для not_nullтолько собственный код.)

В следующих примерах предположим, что мы можем перейти от not_null<T>,

not_null<unique_ptr<int>> f()
{
    return make_unique<int>(1);
}

void g(not_null<unique_ptr<int>> p)
{
    ...
}

void h()
{
    auto p = f();
    g(make_unique<int>(2));
}
  1. Правильно ли мое предположение, что состояние not_null<unique_ptr<int>> вернувшийся из f() не мог просочиться после перехода от него (только для примера)?

  2. Правильно ли мое предположение, что состояние not_null<unique_ptr<int>> переданный в g() не может течь после перехода от него (только для примера)?

  3. Можно ли разрешить этот особый вид перемещения, одновременно запрещая общий случай перемещения в C++14/17?

1 ответ

Решение

1 и 2: игнорирование того факта, что elision сделает вопрос спорным о любом компиляторе, который стоит использовать, да. Также игнорируя тот факт, что unique_ptr не может "утечка".

3: Нет.

Это было предметом некоторых дискуссий в списке рассылки предложений ISO C++. Общая концепция - это "разрушительное движение", когда действие по перемещению от объекта и его уничтожению выполняется в одном вызове. Но это должно быть языковой особенностью; в C++14 нет способа определить, вызывается ли конструктор / присваивание move так, что данный объект наверняка будет уничтожен.

Другие вопросы по тегам