Библиотека поддержки руководства введены 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));
}
Правильно ли мое предположение, что состояние not_null<unique_ptr<int>>
вернувшийся из f () не мог просочиться после перехода от него (только для примера)?
Правильно ли мое предположение, что состояние not_null<unique_ptr<int>>
переданный в g () не может течь после перехода от него (только для примера)?
Можно ли разрешить этот особый вид перемещения, одновременно запрещая общий случай перемещения в C ++ 14/17?
1&2: Игнорирование того факта, что elision сделает вопрос спорным на любом компиляторе, стоит использовать, да. Также игнорируя тот факт, что unique_ptr
не могу «Утечка».
3: Нет.
Это было предметом некоторых дискуссий в списке рассылки предложений ISO C ++. Общая концепция — это «разрушительное движение», когда действие по перемещению от объекта и его уничтожению выполняется в одном вызове. Но это должно быть языковой особенностью; в C ++ 14 нет способа определить, вызывается ли конструктор / присваивание move так, что данный объект наверняка будет уничтожен.
Других решений пока нет …