diff --git a/include/gsl/gsl b/include/gsl/gsl index 4cb03c5..4f69bbf 100644 --- a/include/gsl/gsl +++ b/include/gsl/gsl @@ -24,167 +24,6 @@ #include // multi_span, strided_span... #include // span #include // zstring, string_span, zstring_builder... - -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1910 -#pragma push_macro("constexpr") -#define constexpr /*constexpr*/ - -#endif // defined(_MSC_VER) && _MSC_VER < 1910 - -namespace gsl -{ - -// -// GSL.owner: ownership pointers -// -using std::unique_ptr; -using std::shared_ptr; - -// -// owner -// -// owner is designed as a bridge for code that must deal directly with owning pointers for some reason -// -// T must be a pointer type -// - disallow construction from any type other than pointer type -// -template ::value>> -using owner = T; - -// -// not_null -// -// Restricts a pointer or smart pointer to only hold non-null values. -// -// Has zero size overhead over T. -// -// If T is a pointer (i.e. T == U*) then -// - allow construction from U* -// - disallow construction from nullptr_t -// - disallow default construction -// - ensure construction from null U* fails -// - allow implicit conversion to U* -// -template -class not_null -{ -public: - static_assert(std::is_assignable::value, "T cannot be assigned nullptr."); - - template ::value>> - constexpr not_null(U&& u) : ptr_(std::forward(u)) - { - Expects(ptr_ != nullptr); - } - - template ::value>> - constexpr not_null(const not_null& other) : not_null(other.get()) - { - } - - not_null(const not_null& other) = default; - not_null& operator=(const not_null& other) = default; - - constexpr T get() const - { - Ensures(ptr_ != nullptr); - return ptr_; - } - - constexpr operator T() const { return get(); } - constexpr T operator->() const { return get(); } - constexpr decltype(auto) operator*() const { return *get(); } - - // prevents compilation when someone attempts to assign a null pointer constant - not_null(std::nullptr_t) = delete; - not_null& operator=(std::nullptr_t) = delete; - - // unwanted operators...pointers only point to single objects! - not_null& operator++() = delete; - not_null& operator--() = delete; - not_null operator++(int) = delete; - not_null operator--(int) = delete; - not_null& operator+=(std::ptrdiff_t) = delete; - not_null& operator-=(std::ptrdiff_t) = delete; - void operator[](std::ptrdiff_t) const = delete; - -private: - T ptr_; -}; - -template -std::ostream& operator<<(std::ostream& os, const not_null& val) -{ - os << val.get(); - return os; -} - -template -auto operator==(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() == rhs.get()) -{ - return lhs.get() == rhs.get(); -} - -template -auto operator!=(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() != rhs.get()) -{ - return lhs.get() != rhs.get(); -} - -template -auto operator<(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() < rhs.get()) -{ - return lhs.get() < rhs.get(); -} - -template -auto operator<=(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() <= rhs.get()) -{ - return lhs.get() <= rhs.get(); -} - -template -auto operator>(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() > rhs.get()) -{ - return lhs.get() > rhs.get(); -} - -template -auto operator>=(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() >= rhs.get()) -{ - return lhs.get() >= rhs.get(); -} - -// more unwanted operators -template -std::ptrdiff_t operator-(const not_null&, const not_null&) = delete; -template -not_null operator-(const not_null&, std::ptrdiff_t) = delete; -template -not_null operator+(const not_null&, std::ptrdiff_t) = delete; -template -not_null operator+(std::ptrdiff_t, const not_null&) = delete; - -} // namespace gsl - -namespace std -{ -template -struct hash> -{ - std::size_t operator()(const gsl::not_null& value) const { return hash{}(value); } -}; - -} // namespace std - -#if defined(_MSC_VER) && _MSC_VER < 1910 -#undef constexpr -#pragma pop_macro("constexpr") - -#endif // defined(_MSC_VER) && _MSC_VER < 1910 +#include // owner, not_null #endif // GSL_GSL_H diff --git a/include/gsl/pointers b/include/gsl/pointers new file mode 100644 index 0000000..a02d3a9 --- /dev/null +++ b/include/gsl/pointers @@ -0,0 +1,186 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#ifndef GSL_POINTERS_H +#define GSL_POINTERS_H + +#include + +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1910 +#pragma push_macro("constexpr") +#define constexpr /*constexpr*/ + +#endif // defined(_MSC_VER) && _MSC_VER < 1910 + +namespace gsl +{ + +// +// GSL.owner: ownership pointers +// +using std::unique_ptr; +using std::shared_ptr; + +// +// owner +// +// owner is designed as a bridge for code that must deal directly with owning pointers for some reason +// +// T must be a pointer type +// - disallow construction from any type other than pointer type +// +template ::value>> +using owner = T; + +// +// not_null +// +// Restricts a pointer or smart pointer to only hold non-null values. +// +// Has zero size overhead over T. +// +// If T is a pointer (i.e. T == U*) then +// - allow construction from U* +// - disallow construction from nullptr_t +// - disallow default construction +// - ensure construction from null U* fails +// - allow implicit conversion to U* +// +template +class not_null +{ +public: + static_assert(std::is_assignable::value, "T cannot be assigned nullptr."); + + template ::value>> + constexpr not_null(U&& u) : ptr_(std::forward(u)) + { + Expects(ptr_ != nullptr); + } + + template ::value>> + constexpr not_null(const not_null& other) : not_null(other.get()) + { + } + + not_null(const not_null& other) = default; + not_null& operator=(const not_null& other) = default; + + constexpr T get() const + { + Ensures(ptr_ != nullptr); + return ptr_; + } + + constexpr operator T() const { return get(); } + constexpr T operator->() const { return get(); } + constexpr decltype(auto) operator*() const { return *get(); } + + // prevents compilation when someone attempts to assign a null pointer constant + not_null(std::nullptr_t) = delete; + not_null& operator=(std::nullptr_t) = delete; + + // unwanted operators...pointers only point to single objects! + not_null& operator++() = delete; + not_null& operator--() = delete; + not_null operator++(int) = delete; + not_null operator--(int) = delete; + not_null& operator+=(std::ptrdiff_t) = delete; + not_null& operator-=(std::ptrdiff_t) = delete; + void operator[](std::ptrdiff_t) const = delete; + +private: + T ptr_; +}; + +template +std::ostream& operator<<(std::ostream& os, const not_null& val) +{ + os << val.get(); + return os; +} + +template +auto operator==(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() == rhs.get()) +{ + return lhs.get() == rhs.get(); +} + +template +auto operator!=(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() != rhs.get()) +{ + return lhs.get() != rhs.get(); +} + +template +auto operator<(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() < rhs.get()) +{ + return lhs.get() < rhs.get(); +} + +template +auto operator<=(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() <= rhs.get()) +{ + return lhs.get() <= rhs.get(); +} + +template +auto operator>(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() > rhs.get()) +{ + return lhs.get() > rhs.get(); +} + +template +auto operator>=(const not_null& lhs, const not_null& rhs) -> decltype(lhs.get() >= rhs.get()) +{ + return lhs.get() >= rhs.get(); +} + +// more unwanted operators +template +std::ptrdiff_t operator-(const not_null&, const not_null&) = delete; +template +not_null operator-(const not_null&, std::ptrdiff_t) = delete; +template +not_null operator+(const not_null&, std::ptrdiff_t) = delete; +template +not_null operator+(std::ptrdiff_t, const not_null&) = delete; + +} // namespace gsl + +namespace std +{ +template +struct hash> +{ + std::size_t operator()(const gsl::not_null& value) const { return hash{}(value); } +}; + +} // namespace std + +#if defined(_MSC_VER) && _MSC_VER < 1910 +#undef constexpr +#pragma pop_macro("constexpr") + +#endif // defined(_MSC_VER) && _MSC_VER < 1910 + +#endif // GSL_POINTERS_H diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp index 62f1e57..6111553 100644 --- a/tests/notnull_tests.cpp +++ b/tests/notnull_tests.cpp @@ -16,7 +16,7 @@ #include -#include +#include #include #include diff --git a/tests/owner_tests.cpp b/tests/owner_tests.cpp index 9885a68..dbc8d16 100644 --- a/tests/owner_tests.cpp +++ b/tests/owner_tests.cpp @@ -16,10 +16,9 @@ #include -#include +#include #include - #include using namespace gsl;