gsl::not_null has 2 constructors one taking a forwarding reference and another one taking a value type. What is the case where the forwarding constructor alone would not work? Implementation from here
template <class T>
class not_null
{
public:
static_assert(details::is_comparable_to_nullptr<T>::value, "T cannot be compared to nullptr.");
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr not_null(U&& u) : ptr_(std::forward<U>(u))
{
Expects(ptr_ != nullptr);
}
template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
constexpr not_null(T u) : ptr_(std::move(u))
{
Expects(ptr_ != nullptr);
}
...
CodePudding user response:
Commit history gives the answer - https://github.com/microsoft/GSL/commit/cb2d1af89afb76bf50efe8e068c5ea1fc2872274
This allows compilers with c 17 support to infer template instantiation types when calling not_null constructor:
int foo(not_null<const int*> x);
int main()
{
int t = 0;
not_null x{ &t };
return foo(not_null{ &t });
}
i.e. with this constructor you can write just not_null x{ &t }
instead of not_null<int *> x{ &t }
.