Библиотека поддержки рекомендаций представила 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>
с нулевым значением. Похоже на идеальную ловушку.
Я утверждал, что мы можем законно отказаться от объекта 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?
std::move
является проблемой, сравнитеauto p=f(); auto q=std::move(p);
, где после перемещенияp
не может содержать никакого значимого значения, которое не нарушает инвариант класса, отличный от нуля (нет допустимого значения по умолчанию для установкиp
). - person Werner Henze   schedule 28.02.2020