In the Microsoft implementation of guidelines support library I see the following piece of code:
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_;
}
All the constructors of gsl::not_null
which take possibly pointers check these pointers are not null, but we still check stored value of pointer (ptr_
) against null on each dereference. Why do we have this check, given that in C++ we typically don't pay for what we don't need?
UP: Ensures is implemented as follows (with default flags):
#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)
std::unique_ptr
specialization to make sure the not nullstd::unique_ptr
isn't dereferenced after being moved from. I still don't like it though tbh. – ComplectEnsures
. Actually, it depends on flags, I attached the default one. As far as I understand, it actually costs something in run-time – Nightwalkernot_null(not_null&& other) = default;
is the reason. Maybe it should be non-moveable "not_null" - or some more sophisticated solution - because, as it is implemented right now - I doubt I am going to use it – Choreography