1 /////////////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (c) 2015 Microsoft Corporation. All rights reserved. 4 // 5 // This code is licensed under the MIT License (MIT). 6 // 7 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 13 // THE SOFTWARE. 14 // 15 /////////////////////////////////////////////////////////////////////////////// 16 17 #pragma once 18 19 #ifndef GSL_GSL_H 20 #define GSL_GSL_H 21 22 #include "gsl_assert" // Ensures/Expects 23 #include "gsl_util" // finally()/narrow()/narrow_cast()... 24 #include "multi_span" // multi_span, strided_span... 25 #include "span" // span 26 #include "string_span" // zstring, string_span, zstring_builder... 27 #include <memory> 28 29 #ifdef _MSC_VER 30 31 // No MSVC does constexpr fully yet 32 #pragma push_macro("constexpr") 33 #define constexpr /*constexpr*/ 34 35 // MSVC 2013 workarounds 36 #if _MSC_VER <= 1800 37 // noexcept is not understood 38 #pragma push_macro("noexcept") 39 #define noexcept /*noexcept*/ 40 41 // turn off some misguided warnings 42 #pragma warning(push) 43 #pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior 44 45 #endif // _MSC_VER <= 1800 46 47 #endif // _MSC_VER 48 49 namespace gsl 50 { 51 52 // 53 // GSL.owner: ownership pointers 54 // 55 using std::unique_ptr; 56 using std::shared_ptr; 57 58 template <class T> 59 using owner = T; 60 61 // 62 // not_null 63 // 64 // Restricts a pointer or smart pointer to only hold non-null values. 65 // 66 // Has zero size overhead over T. 67 // 68 // If T is a pointer (i.e. T == U*) then 69 // - allow construction from U* or U& 70 // - disallow construction from nullptr_t 71 // - disallow default construction 72 // - ensure construction from U* fails with nullptr 73 // - allow implicit conversion to U* 74 // 75 template <class T> 76 class not_null 77 { 78 static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr."); 79 80 public: 81 not_null(T t) : ptr_(t) { ensure_invariant(); } 82 not_null& operator=(const T& t) 83 { 84 ptr_ = t; 85 ensure_invariant(); 86 return *this; 87 } 88 89 not_null(const not_null& other) = default; 90 not_null& operator=(const not_null& other) = default; 91 92 template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>> 93 not_null(const not_null<U>& other) 94 { 95 *this = other; 96 } 97 98 template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>> 99 not_null& operator=(const not_null<U>& other) 100 { 101 ptr_ = other.get(); 102 return *this; 103 } 104 105 // prevents compilation when someone attempts to assign a nullptr 106 not_null(std::nullptr_t) = delete; 107 not_null(int) = delete; 108 not_null<T>& operator=(std::nullptr_t) = delete; 109 not_null<T>& operator=(int) = delete; 110 111 T get() const 112 { 113 #ifdef _MSC_VER 114 __assume(ptr_ != nullptr); 115 #endif 116 return ptr_; 117 } // the assume() should help the optimizer 118 119 operator T() const { return get(); } 120 T operator->() const { return get(); } 121 122 bool operator==(const T& rhs) const { return ptr_ == rhs; } 123 bool operator!=(const T& rhs) const { return !(*this == rhs); } 124 private: 125 T ptr_; 126 127 // we assume that the compiler can hoist/prove away most of the checks inlined from this 128 // function 129 // if not, we could make them optional via conditional compilation 130 void ensure_invariant() const { Expects(ptr_ != nullptr); } 131 132 // unwanted operators...pointers only point to single objects! 133 // TODO ensure all arithmetic ops on this type are unavailable 134 not_null<T>& operator++() = delete; 135 not_null<T>& operator--() = delete; 136 not_null<T> operator++(int) = delete; 137 not_null<T> operator--(int) = delete; 138 not_null<T>& operator+(size_t) = delete; 139 not_null<T>& operator+=(size_t) = delete; 140 not_null<T>& operator-(size_t) = delete; 141 not_null<T>& operator-=(size_t) = delete; 142 }; 143 144 } // namespace gsl 145 146 namespace std 147 { 148 template <class T> 149 struct hash<gsl::not_null<T>> 150 { 151 size_t operator()(const gsl::not_null<T>& value) const { return hash<T>{}(value); } 152 }; 153 154 } // namespace std 155 156 #ifdef _MSC_VER 157 158 #undef constexpr 159 #pragma pop_macro("constexpr") 160 161 #if _MSC_VER <= 1800 162 163 #undef noexcept 164 #pragma pop_macro("noexcept") 165 166 #pragma warning(pop) 167 168 #endif // _MSC_VER <= 1800 169 170 #endif // _MSC_VER 171 172 #endif // GSL_GSL_H 173