Используйте `not_null<T>` для обозначения того, что `null` является недопустимым значением
Причина
Ясность. Функция с параметром not_null<T> явно указывает, что ответственность за все необходимые проверки nullptr лежит на вызывающем. Аналогично, функция с возвращаемым значением not_null<T> явно указывает, что вызывающему не нужно проверять на nullptr.
Пример
not_null<T*> очевидно показывает читателю (человеку или инструменту), что проверка на nullptr перед разыменованием не нужна. Кроме того, при отладке owner<T*> и not_null<T> могут быть инструментированы для проверки корректности.
Рассмотрим:
int length(Record* p);
Когда я вызываю length(p), нужно ли сначала проверить, что p не равен nullptr? Должна ли реализация length() проверять, что p не равен nullptr?
// на вызывающем лежит ответственность убедиться, что p != nullptr
int length(not_null<Record*> p);
// реализатор length() должен допускать, что p == nullptr возможно
int length(Record* p);
Примечание
Предполагается, что not_null<T*> не равен nullptr; T* может быть nullptr; оба могут быть представлены в памяти как T* (накладные расходы во время выполнения не подразумеваются).
Примечание
not_null не только для встроенных указателей. Он работает с unique_ptr, shared_ptr и другими pointer-подобными типами.
Контроль
- (Простой) Предупреждать, если сырой указатель разыменовывается без предварительной проверки на
nullptr(или эквивалент) внутри функции, предлагать объявить егоnot_null. - (Простой) Ошибка, если сырой указатель иногда разыменовывается после проверки на
nullptr(или эквивалент), а иногда — без такой проверки. - (Простой) Предупреждать, если
not_nullуказатель проверяется наnullptrвнутри функции.