aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorAnna Gringauze <annagrin@microsoft.com>2019-01-14 16:45:47 -0800
committerGitHub <noreply@github.com>2019-01-14 16:45:47 -0800
commit9ff6e19ea9e2ecf48488c0865be85bb1ca183279 (patch)
treed3dedf87591378b590cd3c5243390b30be489049 /include
parent7a7d025ffa99d8602ace633793bc909ce47a8dd7 (diff)
downloadplatform_external_Microsoft-GSL-9ff6e19ea9e2ecf48488c0865be85bb1ca183279.tar.gz
platform_external_Microsoft-GSL-9ff6e19ea9e2ecf48488c0865be85bb1ca183279.tar.bz2
platform_external_Microsoft-GSL-9ff6e19ea9e2ecf48488c0865be85bb1ca183279.zip
Dev/annagrin/remove explicit not null constructor (#743)
* Added c++17 test configurations for clang5.0 and clang6.0 * Removed explicit not_null constructor, sloppy_not_null, added strict_not_null We added explicit not_null constructor in version 2.0.0. It proved very difficult to switch to the new version for large code bases that adopted previous versions of gsl, due to not_null used extensively in the code. Still, using explicit constructor is very benefitial for new code, since it encorages better API design and make null checks intentional. To resolve the issue, this change: - removes explicit keyword from not_null constructor - removes unneded sloppy_not_null type - adds strict_not_null type to behave the same way as v2 not_null - updates tests * Removed explicit not_null constructor, sloppy_not_null, added strict_not_null We added explicit not_null constructor in version 2.0.0. It proved very difficult to switch to the new version for large code bases that adopted previous versions of gsl, due to not_null used extensively in the code. Still, using explicit constructor is very benefitial for new code, since it encorages better API design and make null checks intentional. To resolve the issue, this change: - removes explicit keyword from not_null constructor - removes unneded sloppy_not_null type - adds strict_not_null type to behave the same way as v2 not_null - updates tests * fixed build break for gcc7 * added more tests * added more non-compiling tests * Addressed PR comments and suppressed a code analysis warning * Fixed test failure in not_null tests
Diffstat (limited to 'include')
-rw-r--r--include/gsl/multi_span1
-rw-r--r--include/gsl/pointers100
2 files changed, 98 insertions, 3 deletions
diff --git a/include/gsl/multi_span b/include/gsl/multi_span
index dbfff92..9995808 100644
--- a/include/gsl/multi_span
+++ b/include/gsl/multi_span
@@ -412,6 +412,7 @@ namespace details
return totalSize() / this->Base::totalSize();
}
+ GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
constexpr size_type elementNum(std::size_t dim) const noexcept
{
if (dim > 0)
diff --git a/include/gsl/pointers b/include/gsl/pointers
index a338856..52c2bfd 100644
--- a/include/gsl/pointers
+++ b/include/gsl/pointers
@@ -72,13 +72,13 @@ public:
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
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))
+ 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 explicit not_null(T u) : ptr_(u)
+ constexpr not_null(T u) : ptr_(u)
{
Expects(ptr_ != nullptr);
}
@@ -121,7 +121,7 @@ private:
template <class T>
auto make_not_null(T&& t) {
- return gsl::not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
+ return not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
}
template <class T>
@@ -189,6 +189,100 @@ struct hash<gsl::not_null<T>>
} // namespace std
+namespace gsl
+{
+
+//
+// strict_not_null
+//
+// Restricts a pointer or smart pointer to only hold non-null values,
+//
+// - provides a strict (i.e. explicit contructor from T) wrapper of not_null
+// - to be used for new code that wishes the design to be cleaner and make not_null
+// checks intentional, or in old code that would like to make the transition.
+//
+// To make the transition from not_null, incrementally replace not_null
+// by strict_not_null and fix compilation errors
+//
+// Expect to
+// - remove all unneded conversions from raw pointer to not_null and back
+// - make API clear by specifyning not_null in parameters where needed
+// - remove unnesessary asserts
+//
+template <class T>
+class strict_not_null: public not_null<T>
+{
+public:
+
+ template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
+ constexpr explicit strict_not_null(U&& u) :
+ not_null<T>(std::forward<U>(u))
+ {}
+
+ template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
+ constexpr explicit strict_not_null(T u) :
+ not_null<T>(u)
+ {}
+
+ template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
+ constexpr strict_not_null(const not_null<U>& other) :
+ not_null<T>(other)
+ {}
+
+ template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
+ constexpr strict_not_null(const strict_not_null<U>& other) :
+ not_null<T>(other)
+ {}
+
+ strict_not_null(strict_not_null&& other) = default;
+ strict_not_null(const strict_not_null& other) = default;
+ strict_not_null& operator=(const strict_not_null& other) = default;
+ strict_not_null& operator=(const not_null<T>& other)
+ {
+ not_null<T>::operator=(other);
+ return *this;
+ }
+
+ // prevents compilation when someone attempts to assign a null pointer constant
+ strict_not_null(std::nullptr_t) = delete;
+ strict_not_null& operator=(std::nullptr_t) = delete;
+
+ // unwanted operators...pointers only point to single objects!
+ strict_not_null& operator++() = delete;
+ strict_not_null& operator--() = delete;
+ strict_not_null operator++(int) = delete;
+ strict_not_null operator--(int) = delete;
+ strict_not_null& operator+=(std::ptrdiff_t) = delete;
+ strict_not_null& operator-=(std::ptrdiff_t) = delete;
+ void operator[](std::ptrdiff_t) const = delete;
+};
+
+// more unwanted operators
+template <class T, class U>
+std::ptrdiff_t operator-(const strict_not_null<T>&, const strict_not_null<U>&) = delete;
+template <class T>
+strict_not_null<T> operator-(const strict_not_null<T>&, std::ptrdiff_t) = delete;
+template <class T>
+strict_not_null<T> operator+(const strict_not_null<T>&, std::ptrdiff_t) = delete;
+template <class T>
+strict_not_null<T> operator+(std::ptrdiff_t, const strict_not_null<T>&) = delete;
+
+template <class T>
+auto make_strict_not_null(T&& t) {
+ return strict_not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
+}
+
+} // namespace gsl
+
+namespace std
+{
+template <class T>
+struct hash<gsl::strict_not_null<T>>
+{
+ std::size_t operator()(const gsl::strict_not_null<T>& value) const { return hash<T>{}(value); }
+};
+
+} // namespace std
#if defined(_MSC_VER) && _MSC_VER < 1910
#undef constexpr
#pragma pop_macro("constexpr")