Home | History | Annotate | Download | only in gsl
      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