/////////////////////////////////////////////////////////////////////////////// // // 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. // /////////////////////////////////////////////////////////////////////////////// #ifndef GSL_TRANSITION_H #define GSL_TRANSITION_H #include <gsl/gsl_assert> // for Ensures, Expects #include <gsl/pointers> // for gsl::not_null #if defined(_MSC_VER) && _MSC_VER < 1910 #pragma push_macro("constexpr") #define constexpr /*constexpr*/ #endif // defined(_MSC_VER) && _MSC_VER < 1910 namespace gsl_helpers { // // sloppy_not_null // // Restricts a pointer or smart pointer to only hold non-null values, // // - provides a sloppy (i.e. no explicit contructor from T) wrapper of gsl::not_null // - is temporary, only to be used to incrementally transition of code // using older version of gsl::not_null to the new one that made the constructor explicit // // To make the transition: // // - replace all occurences of gsl::not_null in your code by sloppy_not_null // variant: rename gsl::not_null by NotNull by including the following in your code, // foe example, in a common include file: // // template<typename T> // using NotNull = gsl::not_null<T>; // // compile using old version of GSL // change GSL version and replace gsl::not_null by gsl_helpers::sloppy_not_null // in the added code lines above // // - compile - compilation should be successful // - replace some sloppy_not_nulls by gsl::not_null, fix compilation erros, // redesign as needed, compile and test // - repeat until no sloppy_not_nulls remain // template <class T> class sloppy_not_null: public gsl::not_null<T> { public: template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>> constexpr sloppy_not_null(U&& u) : gsl::not_null<T>(std::forward<U>(u)) {} template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>> constexpr sloppy_not_null(T u) : gsl::not_null<T>(u) {} template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>> constexpr sloppy_not_null(const gsl::not_null<U>& other) : gsl::not_null<T>(other) {} sloppy_not_null(sloppy_not_null&& other) = default; sloppy_not_null(const sloppy_not_null& other) = default; sloppy_not_null& operator=(const sloppy_not_null& other) = default; sloppy_not_null& operator=(const gsl::not_null<T>& other) { gsl::not_null<T>::operator=(other); return *this; } // prevents compilation when someone attempts to assign a null pointer constant sloppy_not_null(std::nullptr_t) = delete; sloppy_not_null& operator=(std::nullptr_t) = delete; // unwanted operators...pointers only point to single objects! sloppy_not_null& operator++() = delete; sloppy_not_null& operator--() = delete; sloppy_not_null operator++(int) = delete; sloppy_not_null operator--(int) = delete; sloppy_not_null& operator+=(std::ptrdiff_t) = delete; sloppy_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 sloppy_not_null<T>&, const sloppy_not_null<U>&) = delete; template <class T> sloppy_not_null<T> operator-(const sloppy_not_null<T>&, std::ptrdiff_t) = delete; template <class T> sloppy_not_null<T> operator+(const sloppy_not_null<T>&, std::ptrdiff_t) = delete; template <class T> sloppy_not_null<T> operator+(std::ptrdiff_t, const sloppy_not_null<T>&) = delete; } // namespace gsl namespace std { template <class T> struct hash<gsl_helpers::sloppy_not_null<T>> { std::size_t operator()(const gsl_helpers::sloppy_not_null<T>& value) const { return hash<T>{}(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_TRANSITION_H