Почему gsl :: not_null гарантирует, что ptr не является нулем при get ()? - PullRequest
0 голосов
/ 03 июля 2018

В Microsoft реализации библиотеки поддержки рекомендаций я вижу следующий фрагмент кода:

template<class T>
class not_null {
    ...
    template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
    constexpr explicit not_null(U&& u) : ptr_(std::forward<U>(u)) {
        Expects(ptr_ != nullptr);
    }
    ...
    constexpr T get() const {
        Ensures(ptr_);
        return ptr_;
    }
    ...
    T ptr_;
}

Все конструкторы gsl::not_null, которые принимают, возможно, указатели, проверяют, что эти указатели не равны NULL, но мы по-прежнему проверяем сохраненное значение указателя (ptr_) и NULL при каждом разыменовании. Почему у нас есть эта проверка, учитывая, что в C ++ мы обычно не платим за то, что нам не нужно?

UP : обеспечивает реализацию следующим образом (с флагами по умолчанию):

#define GSL_LIKELY(x) (!!(x))
...
#define GSL_CONTRACT_CHECK(type, cond)                         \
(GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate())
...
#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)

1 Ответ

0 голосов
/ 04 июля 2018

Комментарии уже дают представление о том, почему удаление нулевой проверки из not_null::get() нежелательно. Основная проблема заключается в том, что изменение позволяет разыменовать умный указатель после перемещения.

Например, см. Следующее обсуждение по PR, который позволяет использовать not_null<unique_ptr> и как изменение несовместимо с удалением нулевой проверки из not_null::get()

https://github.com/Microsoft/GSL/pull/675

Что касается проблем с производительностью, оптимизатор компилятора должен быть в состоянии удалить многие из нулевых проверок, но не все, конечно. Если некоторые проверки не удалены, но кажутся съемными, мы должны исправить оптимизацию компилятора.

...