From a150aaa4ed355e88834877c9f39eadd4526e3b8f Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Thu, 29 Oct 2020 17:38:48 -0700 Subject: [PATCH] renaming main logic files. Added warning message of the removal and include passthrough. Renamed includes in the source files. Ran Clang-Format (#946) Header rename --- include/gsl/algorithm | 63 ++++++++ include/gsl/assert | 135 ++++++++++++++++ include/gsl/byte | 213 ++++++++++++++++++++++++++ include/gsl/gsl | 18 +-- include/gsl/gsl_algorithm | 64 +------- include/gsl/gsl_assert | 136 +---------------- include/gsl/gsl_byte | 212 +------------------------ include/gsl/gsl_narrow | 55 +------ include/gsl/gsl_util | 132 +--------------- include/gsl/multi_span | 238 +++++++++++++++++++++-------- include/gsl/narrow | 49 ++++++ include/gsl/pointers | 75 +++++---- include/gsl/span | 117 +++++++------- include/gsl/span_ext | 5 +- include/gsl/string_span | 13 +- include/gsl/util | 145 ++++++++++++++++++ tests/algorithm_tests.cpp | 2 +- tests/assertion_tests.cpp | 2 +- tests/at_tests.cpp | 2 +- tests/byte_tests.cpp | 2 +- tests/multi_span_tests.cpp | 4 +- tests/span_compatibility_tests.cpp | 2 +- tests/span_ext_tests.cpp | 2 +- tests/span_tests.cpp | 4 +- tests/strided_span_tests.cpp | 4 +- tests/string_span_tests.cpp | 2 +- tests/utils_tests.cpp | 4 +- 27 files changed, 934 insertions(+), 766 deletions(-) create mode 100644 include/gsl/algorithm create mode 100644 include/gsl/assert create mode 100644 include/gsl/byte create mode 100644 include/gsl/narrow create mode 100644 include/gsl/util diff --git a/include/gsl/algorithm b/include/gsl/algorithm new file mode 100644 index 0000000..b27475d --- /dev/null +++ b/include/gsl/algorithm @@ -0,0 +1,63 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// 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_ALGORITHM_H +#define GSL_ALGORITHM_H + +#include // for Expects +#include // for dynamic_extent, span + +#include // for copy_n +#include // for ptrdiff_t +#include // for is_assignable + +#ifdef _MSC_VER +#pragma warning(push) + +// turn off some warnings that are noisy about our Expects statements +#pragma warning(disable : 4127) // conditional expression is constant +#pragma warning(disable : 4996) // unsafe use of std::copy_n + +#endif // _MSC_VER + +namespace gsl +{ +// Note: this will generate faster code than std::copy using span iterator in older msvc+stl +// not necessary for msvc since VS2017 15.8 (_MSC_VER >= 1915) +template +void copy(span src, span dest) +{ + static_assert(std::is_assignable::value, + "Elements of source span can not be assigned to elements of destination span"); + static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent || + (SrcExtent <= DestExtent), + "Source range is longer than target range"); + + Expects(dest.size() >= src.size()); + // clang-format off + GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute + // clang-format on + std::copy_n(src.data(), src.size(), dest.data()); +} + +} // namespace gsl + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +#endif // GSL_ALGORITHM_H diff --git a/include/gsl/assert b/include/gsl/assert new file mode 100644 index 0000000..0cc54f6 --- /dev/null +++ b/include/gsl/assert @@ -0,0 +1,135 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// 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_CONTRACTS_H +#define GSL_CONTRACTS_H + +// +// Temporary until MSVC STL supports no-exceptions mode. +// Currently terminate is a no-op in this mode, so we add termination behavior back +// +#if defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)) + +#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND +#include +#define RANGE_CHECKS_FAILURE 0 + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Winvalid-noreturn" +#endif // defined(__clang__) + +#else // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && + // !_HAS_EXCEPTIONS)) + +#include + +#endif // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && + // !_HAS_EXCEPTIONS)) + +// +// make suppress attributes parse for some compilers +// Hopefully temporary until suppression standardization occurs +// +#if defined(__clang__) +#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] +#else +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) +#define GSL_SUPPRESS(x) [[gsl::suppress(x)]] +#else +#define GSL_SUPPRESS(x) +#endif // _MSC_VER +#endif // __clang__ + +#define GSL_STRINGIFY_DETAIL(x) #x +#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) + +#if defined(__clang__) || defined(__GNUC__) +#define GSL_LIKELY(x) __builtin_expect(!!(x), 1) +#define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0) + +#else + +#define GSL_LIKELY(x) (!!(x)) +#define GSL_UNLIKELY(x) (!!(x)) +#endif // defined(__clang__) || defined(__GNUC__) + +// +// GSL_ASSUME(cond) +// +// Tell the optimizer that the predicate cond must hold. It is unspecified +// whether or not cond is actually evaluated. +// +#ifdef _MSC_VER +#define GSL_ASSUME(cond) __assume(cond) +#elif defined(__GNUC__) +#define GSL_ASSUME(cond) ((cond) ? static_cast(0) : __builtin_unreachable()) +#else +#define GSL_ASSUME(cond) static_cast((cond) ? 0 : 0) +#endif + +// +// GSL.assert: assertions +// + +namespace gsl +{ + +namespace details +{ +#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + + typedef void(__cdecl* terminate_handler)(); + + // clang-format off + GSL_SUPPRESS(f.6) // NO-FORMAT: attribute + // clang-format on + [[noreturn]] inline void __cdecl default_terminate_handler() + { + __fastfail(RANGE_CHECKS_FAILURE); + } + + inline gsl::details::terminate_handler& get_terminate_handler() noexcept + { + static terminate_handler handler = &default_terminate_handler; + return handler; + } + +#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + + [[noreturn]] inline void terminate() noexcept + { +#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + (*gsl::details::get_terminate_handler())(); +#else + std::terminate(); +#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + } + +} // namespace details +} // namespace gsl + +#define GSL_CONTRACT_CHECK(type, cond) \ + (GSL_LIKELY(cond) ? static_cast(0) : gsl::details::terminate()) + +#define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond) +#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond) + +#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__) +#pragma clang diagnostic pop +#endif + +#endif // GSL_CONTRACTS_H diff --git a/include/gsl/byte b/include/gsl/byte new file mode 100644 index 0000000..9231340 --- /dev/null +++ b/include/gsl/byte @@ -0,0 +1,213 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// 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_BYTE_H +#define GSL_BYTE_H + +// +// make suppress attributes work for some compilers +// Hopefully temporary until suppression standardization occurs +// +#if defined(__clang__) +#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] +#else +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) +#define GSL_SUPPRESS(x) [[gsl::suppress(x)]] +#else +#define GSL_SUPPRESS(x) +#endif // _MSC_VER +#endif // __clang__ + +#include + +// VS2017 15.8 added support for the __cpp_lib_byte definition +// To do: drop _HAS_STD_BYTE when support for pre 15.8 expires +#ifdef _MSC_VER + +#pragma warning(push) + +// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. +#pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates + // does not always work + +#ifndef GSL_USE_STD_BYTE +// this tests if we are under MSVC and the standard lib has std::byte and it is enabled +#if (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || \ + (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603) + +#define GSL_USE_STD_BYTE 1 + +#else // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= + // 201603) + +#define GSL_USE_STD_BYTE 0 + +#endif // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= + // 201603) +#endif // GSL_USE_STD_BYTE + +#else // _MSC_VER + +#ifndef GSL_USE_STD_BYTE +#include /* __cpp_lib_byte */ +// this tests if we are under GCC or Clang with enough -std=c++1z power to get us std::byte +// also check if libc++ version is sufficient (> 5.0) or libstdc++ actually contains std::byte +#if defined(__cplusplus) && (__cplusplus >= 201703L) && \ + (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \ + defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) + +#define GSL_USE_STD_BYTE 1 + +#else // defined(__cplusplus) && (__cplusplus >= 201703L) && + // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || + // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) + +#define GSL_USE_STD_BYTE 0 + +#endif // defined(__cplusplus) && (__cplusplus >= 201703L) && + // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || + // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) +#endif // GSL_USE_STD_BYTE + +#endif // _MSC_VER + +// Use __may_alias__ attribute on gcc and clang +#if defined __clang__ || (defined(__GNUC__) && __GNUC__ > 5) +#define byte_may_alias __attribute__((__may_alias__)) +#else // defined __clang__ || defined __GNUC__ +#define byte_may_alias +#endif // defined __clang__ || defined __GNUC__ + +#if GSL_USE_STD_BYTE +#include +#endif + +namespace gsl +{ +#if GSL_USE_STD_BYTE + +using std::byte; +using std::to_integer; + +#else // GSL_USE_STD_BYTE + +// This is a simple definition for now that allows +// use of byte within span<> to be standards-compliant +enum class byte_may_alias byte : unsigned char +{ +}; + +template ::value>> +constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept +{ + return b = byte(static_cast(b) << shift); +} + +template ::value>> +constexpr byte operator<<(byte b, IntegerType shift) noexcept +{ + return byte(static_cast(b) << shift); +} + +template ::value>> +constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept +{ + return b = byte(static_cast(b) >> shift); +} + +template ::value>> +constexpr byte operator>>(byte b, IntegerType shift) noexcept +{ + return byte(static_cast(b) >> shift); +} + +constexpr byte& operator|=(byte& l, byte r) noexcept +{ + return l = byte(static_cast(l) | static_cast(r)); +} + +constexpr byte operator|(byte l, byte r) noexcept +{ + return byte(static_cast(l) | static_cast(r)); +} + +constexpr byte& operator&=(byte& l, byte r) noexcept +{ + return l = byte(static_cast(l) & static_cast(r)); +} + +constexpr byte operator&(byte l, byte r) noexcept +{ + return byte(static_cast(l) & static_cast(r)); +} + +constexpr byte& operator^=(byte& l, byte r) noexcept +{ + return l = byte(static_cast(l) ^ static_cast(r)); +} + +constexpr byte operator^(byte l, byte r) noexcept +{ + return byte(static_cast(l) ^ static_cast(r)); +} + +constexpr byte operator~(byte b) noexcept { return byte(~static_cast(b)); } + +template ::value>> +constexpr IntegerType to_integer(byte b) noexcept +{ + return static_cast(b); +} + +#endif // GSL_USE_STD_BYTE + +template +constexpr byte to_byte_impl(T t) noexcept +{ + static_assert( + E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. " + "If you are calling to_byte with an integer contant use: gsl::to_byte() version."); + return static_cast(t); +} +template <> +// NOTE: need suppression since c++14 does not allow "return {t}" +// GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: suppression does not work +constexpr byte to_byte_impl(unsigned char t) noexcept +{ + return byte(t); +} + +template +constexpr byte to_byte(T t) noexcept +{ + return to_byte_impl::value, T>(t); +} + +template +constexpr byte to_byte() noexcept +{ + static_assert(I >= 0 && I <= 255, + "gsl::byte only has 8 bits of storage, values must be in range 0-255"); + return static_cast(I); +} + +} // namespace gsl + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +#endif // GSL_BYTE_H diff --git a/include/gsl/gsl b/include/gsl/gsl index 4ce0eb9..2e22c5a 100644 --- a/include/gsl/gsl +++ b/include/gsl/gsl @@ -17,17 +17,17 @@ #ifndef GSL_GSL_H #define GSL_GSL_H -#include // copy -#include // Ensures/Expects -#include // byte -#include // finally()/narrow_cast()... -#include // multi_span, strided_span... -#include // owner, not_null -#include // span -#include // zstring, string_span, zstring_builder... +#include // copy +#include // Ensures/Expects +#include // byte +#include // owner, not_null +#include // multi_span, strided_span... +#include // span +#include // zstring, string_span, zstring_builder... +#include // finally()/narrow_cast()... #ifdef __cpp_exceptions -#include // narrow() +#include // narrow() #endif #endif // GSL_GSL_H diff --git a/include/gsl/gsl_algorithm b/include/gsl/gsl_algorithm index 6813b6c..9f1dd50 100644 --- a/include/gsl/gsl_algorithm +++ b/include/gsl/gsl_algorithm @@ -1,61 +1,3 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// 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_ALGORITHM_H -#define GSL_ALGORITHM_H - -#include // for Expects -#include // for dynamic_extent, span - -#include // for copy_n -#include // for ptrdiff_t -#include // for is_assignable - -#ifdef _MSC_VER -#pragma warning(push) - -// turn off some warnings that are noisy about our Expects statements -#pragma warning(disable : 4127) // conditional expression is constant -#pragma warning(disable : 4996) // unsafe use of std::copy_n - -#endif // _MSC_VER - -namespace gsl -{ -// Note: this will generate faster code than std::copy using span iterator in older msvc+stl -// not necessary for msvc since VS2017 15.8 (_MSC_VER >= 1915) -template -void copy(span src, span dest) -{ - static_assert(std::is_assignable::value, - "Elements of source span can not be assigned to elements of destination span"); - static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent || - (SrcExtent <= DestExtent), - "Source range is longer than target range"); - - Expects(dest.size() >= src.size()); - GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute - std::copy_n(src.data(), src.size(), dest.data()); -} - -} // namespace gsl - -#ifdef _MSC_VER -#pragma warning(pop) -#endif // _MSC_VER - -#endif // GSL_ALGORITHM_H +#pragma once +#pragma message("This header will soon be removed. Use instead of ") +#include diff --git a/include/gsl/gsl_assert b/include/gsl/gsl_assert index 3b96117..b83a772 100644 --- a/include/gsl/gsl_assert +++ b/include/gsl/gsl_assert @@ -1,133 +1,3 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// 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_CONTRACTS_H -#define GSL_CONTRACTS_H - -// -// Temporary until MSVC STL supports no-exceptions mode. -// Currently terminate is a no-op in this mode, so we add termination behavior back -// -#if defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)) - -#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND -#include -#define RANGE_CHECKS_FAILURE 0 - -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Winvalid-noreturn" -#endif // defined(__clang__) - -#else // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)) - -#include - -#endif // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)) - -// -// make suppress attributes parse for some compilers -// Hopefully temporary until suppression standardization occurs -// -#if defined(__clang__) -#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] -#else -#if defined(_MSC_VER) && ! defined(__INTEL_COMPILER) -#define GSL_SUPPRESS(x) [[gsl::suppress(x)]] -#else -#define GSL_SUPPRESS(x) -#endif // _MSC_VER -#endif // __clang__ - -#define GSL_STRINGIFY_DETAIL(x) #x -#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) - -#if defined(__clang__) || defined(__GNUC__) -#define GSL_LIKELY(x) __builtin_expect(!!(x), 1) -#define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0) - -#else - -#define GSL_LIKELY(x) (!!(x)) -#define GSL_UNLIKELY(x) (!!(x)) -#endif // defined(__clang__) || defined(__GNUC__) - -// -// GSL_ASSUME(cond) -// -// Tell the optimizer that the predicate cond must hold. It is unspecified -// whether or not cond is actually evaluated. -// -#ifdef _MSC_VER -#define GSL_ASSUME(cond) __assume(cond) -#elif defined(__GNUC__) -#define GSL_ASSUME(cond) ((cond) ? static_cast(0) : __builtin_unreachable()) -#else -#define GSL_ASSUME(cond) static_cast((cond) ? 0 : 0) -#endif - -// -// GSL.assert: assertions -// - -namespace gsl -{ - -namespace details -{ -#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) - - typedef void(__cdecl* terminate_handler)(); - - // clang-format off - GSL_SUPPRESS(f.6) // NO-FORMAT: attribute - // clang-format on - [[noreturn]] inline void __cdecl default_terminate_handler() - { - __fastfail(RANGE_CHECKS_FAILURE); - } - - inline gsl::details::terminate_handler& get_terminate_handler() noexcept - { - static terminate_handler handler = &default_terminate_handler; - return handler; - } - -#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) - - [[noreturn]] inline void terminate() noexcept - { -#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) - (*gsl::details::get_terminate_handler())(); -#else - std::terminate(); -#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) - } - -} // namespace details -} // namespace gsl - -#define GSL_CONTRACT_CHECK(type, cond) \ - (GSL_LIKELY(cond) ? static_cast(0) : gsl::details::terminate()) - -#define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond) -#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond) - -#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__) -#pragma clang diagnostic pop -#endif - -#endif // GSL_CONTRACTS_H +#pragma once +#pragma message("This header will soon be removed. Use instead of ") +#include diff --git a/include/gsl/gsl_byte b/include/gsl/gsl_byte index 0d74b13..4f198ce 100644 --- a/include/gsl/gsl_byte +++ b/include/gsl/gsl_byte @@ -1,209 +1,3 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// 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_BYTE_H -#define GSL_BYTE_H - -// -// make suppress attributes work for some compilers -// Hopefully temporary until suppression standardization occurs -// -#if defined(__clang__) -#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] -#else -#if defined(_MSC_VER) && ! defined(__INTEL_COMPILER) -#define GSL_SUPPRESS(x) [[gsl::suppress(x)]] -#else -#define GSL_SUPPRESS(x) -#endif // _MSC_VER -#endif // __clang__ - -#include - -// VS2017 15.8 added support for the __cpp_lib_byte definition -// To do: drop _HAS_STD_BYTE when support for pre 15.8 expires -#ifdef _MSC_VER - -#pragma warning(push) - -// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. -#pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates does not always work - -#ifndef GSL_USE_STD_BYTE -// this tests if we are under MSVC and the standard lib has std::byte and it is enabled -#if (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603) - -#define GSL_USE_STD_BYTE 1 - -#else // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603) - -#define GSL_USE_STD_BYTE 0 - -#endif // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603) -#endif // GSL_USE_STD_BYTE - -#else // _MSC_VER - -#ifndef GSL_USE_STD_BYTE -#include /* __cpp_lib_byte */ -// this tests if we are under GCC or Clang with enough -std=c++1z power to get us std::byte -// also check if libc++ version is sufficient (> 5.0) or libstdc++ actually contains std::byte -#if defined(__cplusplus) && (__cplusplus >= 201703L) && \ - (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \ - defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) - -#define GSL_USE_STD_BYTE 1 - -#else // defined(__cplusplus) && (__cplusplus >= 201703L) && - // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || - // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) - -#define GSL_USE_STD_BYTE 0 - -#endif //defined(__cplusplus) && (__cplusplus >= 201703L) && - // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || - // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) -#endif // GSL_USE_STD_BYTE - -#endif // _MSC_VER - -// Use __may_alias__ attribute on gcc and clang -#if defined __clang__ || (defined(__GNUC__) && __GNUC__ > 5) -#define byte_may_alias __attribute__((__may_alias__)) -#else // defined __clang__ || defined __GNUC__ -#define byte_may_alias -#endif // defined __clang__ || defined __GNUC__ - -#if GSL_USE_STD_BYTE -#include -#endif - -namespace gsl -{ -#if GSL_USE_STD_BYTE - -using std::byte; -using std::to_integer; - -#else // GSL_USE_STD_BYTE - -// This is a simple definition for now that allows -// use of byte within span<> to be standards-compliant -enum class byte_may_alias byte : unsigned char -{ -}; - -template ::value>> -constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept -{ - return b = byte(static_cast(b) << shift); -} - -template ::value>> -constexpr byte operator<<(byte b, IntegerType shift) noexcept -{ - return byte(static_cast(b) << shift); -} - -template ::value>> -constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept -{ - return b = byte(static_cast(b) >> shift); -} - -template ::value>> -constexpr byte operator>>(byte b, IntegerType shift) noexcept -{ - return byte(static_cast(b) >> shift); -} - -constexpr byte& operator|=(byte& l, byte r) noexcept -{ - return l = byte(static_cast(l) | static_cast(r)); -} - -constexpr byte operator|(byte l, byte r) noexcept -{ - return byte(static_cast(l) | static_cast(r)); -} - -constexpr byte& operator&=(byte& l, byte r) noexcept -{ - return l = byte(static_cast(l) & static_cast(r)); -} - -constexpr byte operator&(byte l, byte r) noexcept -{ - return byte(static_cast(l) & static_cast(r)); -} - -constexpr byte& operator^=(byte& l, byte r) noexcept -{ - return l = byte(static_cast(l) ^ static_cast(r)); -} - -constexpr byte operator^(byte l, byte r) noexcept -{ - return byte(static_cast(l) ^ static_cast(r)); -} - -constexpr byte operator~(byte b) noexcept { return byte(~static_cast(b)); } - -template ::value>> -constexpr IntegerType to_integer(byte b) noexcept -{ - return static_cast(b); -} - -#endif // GSL_USE_STD_BYTE - -template -constexpr byte to_byte_impl(T t) noexcept -{ - static_assert( - E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. " - "If you are calling to_byte with an integer contant use: gsl::to_byte() version."); - return static_cast(t); -} -template <> -// NOTE: need suppression since c++14 does not allow "return {t}" -// GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: suppression does not work -constexpr byte to_byte_impl(unsigned char t) noexcept -{ - return byte(t); -} - -template -constexpr byte to_byte(T t) noexcept -{ - return to_byte_impl::value, T>(t); -} - -template -constexpr byte to_byte() noexcept -{ - static_assert(I >= 0 && I <= 255, - "gsl::byte only has 8 bits of storage, values must be in range 0-255"); - return static_cast(I); -} - -} // namespace gsl - -#ifdef _MSC_VER -#pragma warning(pop) -#endif // _MSC_VER - -#endif // GSL_BYTE_H +#pragma once +#pragma message("This header will soon be removed. Use instead of ") +#include diff --git a/include/gsl/gsl_narrow b/include/gsl/gsl_narrow index cec25a1..6c2cd10 100644 --- a/include/gsl/gsl_narrow +++ b/include/gsl/gsl_narrow @@ -1,52 +1,3 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// 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_NARROW_H -#define GSL_NARROW_H -#include // for Expects -#include // for narrow_cast -namespace gsl -{ -struct narrowing_error : public std::exception -{ - const char* what() const noexcept override - { - return "narrowing_error"; - } -}; - -// narrow() : a checked version of narrow_cast() that throws if the cast changed the value -template -GSL_SUPPRESS(type.1) // NO-FORMAT: attribute -GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false) -constexpr -T narrow(U u) noexcept(false) -{ - constexpr const bool is_different_signedness = (std::is_signed::value != std::is_signed::value); - - const T t = narrow_cast(u); - - if (static_cast(t) != u - || (is_different_signedness - && ((t < T{}) != (u < U{})))) - { - throw narrowing_error{}; - } - - return t; -} -} -#endif // GSL_NARROW_H +#pragma once +#pragma message("This header will soon be removed. Use instead of ") +#include diff --git a/include/gsl/gsl_util b/include/gsl/gsl_util index ca733ac..6a6d77e 100644 --- a/include/gsl/gsl_util +++ b/include/gsl/gsl_util @@ -1,129 +1,3 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// 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_UTIL_H -#define GSL_UTIL_H - -#include // for Expects - -#include -#include // for ptrdiff_t, size_t -#include // for initializer_list -#include // for is_signed, integral_constant -#include // for exchange, forward - -#if defined(_MSC_VER) && !defined(__clang__) - -#pragma warning(push) -#pragma warning(disable : 4127) // conditional expression is constant - -#endif // _MSC_VER - -#if defined(__cplusplus) && (__cplusplus >= 201703L) -#define GSL_NODISCARD [[nodiscard]] -#else -#define GSL_NODISCARD -#endif // defined(__cplusplus) && (__cplusplus >= 201703L) - -namespace gsl -{ -// -// GSL.util: utilities -// - -// index type for all container indexes/subscripts/sizes -using index = std::ptrdiff_t; - -// final_action allows you to ensure something gets run at the end of a scope -template -class final_action -{ -public: - static_assert(!std::is_reference::value && !std::is_const::value && !std::is_volatile::value, "Final_action should store its callable by value"); - - explicit final_action(F f) noexcept : f_(std::move(f)) {} - - final_action(final_action&& other) noexcept : f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false)) {} - - final_action(const final_action&) = delete; - final_action& operator=(const final_action&) = delete; - final_action& operator=(final_action&&) = delete; - - GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws - ~final_action() noexcept - { - if (invoke_) f_(); - } - -private: - F f_; - bool invoke_{true}; -}; - -// finally() - convenience function to generate a final_action -template -GSL_NODISCARD final_action::type>::type> finally(F&& f) noexcept -{ - return final_action::type>::type>(std::forward(f)); -} - -// narrow_cast(): a searchable way to do narrowing casts of values -template -GSL_SUPPRESS(type.1) // NO-FORMAT: attribute -constexpr T narrow_cast(U&& u) noexcept -{ - return static_cast(std::forward(u)); -} - -// -// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector -// -template -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute -constexpr T& at(T (&arr)[N], const index i) -{ - Expects(i >= 0 && i < narrow_cast(N)); - return arr[narrow_cast(i)]; -} - -template -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute -constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()]) -{ - Expects(i >= 0 && i < narrow_cast(cont.size())); - using size_type = decltype(cont.size()); - return cont[narrow_cast(i)]; -} - -template -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute -constexpr T at(const std::initializer_list cont, const index i) -{ - Expects(i >= 0 && i < narrow_cast(cont.size())); - return *(cont.begin() + i); -} - -} // namespace gsl - -#if defined(_MSC_VER) && !defined(__clang__) - -#pragma warning(pop) - -#endif // _MSC_VER - -#endif // GSL_UTIL_H +#pragma once +#pragma message("This header will soon be removed. Use instead of ") +#include diff --git a/include/gsl/multi_span b/include/gsl/multi_span index 120b0c5..14b86b3 100644 --- a/include/gsl/multi_span +++ b/include/gsl/multi_span @@ -17,12 +17,12 @@ #ifndef GSL_MULTI_SPAN_H #define GSL_MULTI_SPAN_H -#include // for Expects -#include // for byte -#include // for narrow_cast +#include // for Expects +#include // for byte +#include // for narrow_cast -#include // for transform, lexicographical_compare -#include // for array +#include // for transform, lexicographical_compare +#include // for array #include // for std::ptrdiff_t, size_t, nullptr_t #include // for PTRDIFF_MAX #include // for divides, multiplies, minus, negate, plus @@ -95,7 +95,8 @@ namespace details } // namespace details template -class [[deprecated]] multi_span_index final { +class [[deprecated]] multi_span_index final +{ static_assert(Rank > 0, "Rank must be greater than 0!"); template @@ -110,10 +111,12 @@ public: constexpr multi_span_index() noexcept {} - constexpr multi_span_index(const value_type(&values)[Rank]) noexcept + constexpr multi_span_index(const value_type (&values)[Rank]) noexcept { + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute + // clang-format on std::copy(values, values + Rank, elems); } @@ -127,8 +130,10 @@ public: constexpr multi_span_index& operator=(const multi_span_index& rhs) noexcept = default; // Preconditions: component_idx < rank + // clang-format off GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on constexpr reference operator[](std::size_t component_idx) { Expects(component_idx < Rank); // Component index must be less than rank @@ -136,16 +141,20 @@ public: } // Preconditions: component_idx < rank + // clang-format off GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on constexpr const_reference operator[](std::size_t component_idx) const { Expects(component_idx < Rank); // Component index must be less than rank return elems[component_idx]; } + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute + // clang-format on constexpr bool operator==(const multi_span_index& rhs) const { return std::equal(elems, elems + rank, rhs.elems); @@ -178,16 +187,20 @@ public: constexpr multi_span_index& operator+=(const multi_span_index& rhs) { + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute + // clang-format on std::transform(elems, elems + rank, rhs.elems, elems, std::plus{}); return *this; } constexpr multi_span_index& operator-=(const multi_span_index& rhs) { + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute + // clang-format on std::transform(elems, elems + rank, rhs.elems, elems, std::minus{}); return *this; } @@ -213,8 +226,10 @@ public: constexpr multi_span_index& operator*=(value_type v) { + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute + // clang-format on std::transform(elems, elems + rank, elems, [v](value_type x) { return std::multiplies{}(x, v); }); return *this; @@ -222,8 +237,10 @@ public: constexpr multi_span_index& operator/=(value_type v) { + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute + // clang-format on std::transform(elems, elems + rank, elems, [v](value_type x) { return std::divides{}(x, v); }); return *this; @@ -286,7 +303,9 @@ const std::ptrdiff_t dynamic_range = -1; struct [[deprecated]] generalized_mapping_tag { }; -struct[[deprecated]] contiguous_mapping_tag : generalized_mapping_tag{}; +struct [[deprecated]] contiguous_mapping_tag : generalized_mapping_tag +{ +}; namespace details { @@ -298,7 +317,8 @@ namespace details }; template - struct [[deprecated]] BoundsRanges { + struct [[deprecated]] BoundsRanges + { using size_type = std::ptrdiff_t; static const size_type Depth = 0; static const size_type DynamicNum = 0; @@ -337,7 +357,7 @@ namespace details }; template - struct[[deprecated]] BoundsRanges : BoundsRanges + struct [[deprecated]] BoundsRanges : BoundsRanges { using Base = BoundsRanges; using size_type = std::ptrdiff_t; @@ -350,9 +370,10 @@ namespace details size_type m_bound; public: - GSL_SUPPRESS( - f.23) // NO-FORMAT: attribute // this pointer type is cannot be assigned nullptr - issue in not_null - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format off + GSL_SUPPRESS(f.23) // NO-FORMAT: attribute // this pointer type is cannot be assigned nullptr - issue in not_null + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on constexpr BoundsRanges(const std::ptrdiff_t* const arr) : Base(arr + 1), m_bound(*arr * this->Base::totalSize()) { @@ -369,14 +390,16 @@ namespace details {} template - constexpr void serialize(T & arr) const + constexpr void serialize(T& arr) const { arr[Dim] = elementNum(); this->Base::template serialize(arr); } template + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on constexpr size_type linearize(const T& arr) const { const size_type index = this->Base::totalSize() * arr[Dim]; @@ -393,19 +416,22 @@ namespace details return cur < m_bound ? cur + last : -1; } - GSL_SUPPRESS( - c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + // clang-format off + GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + // clang-format on constexpr size_type totalSize() const noexcept { return m_bound; } - GSL_SUPPRESS( - c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + // clang-format off + GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + // clang-format on constexpr size_type elementNum() const noexcept { return totalSize() / this->Base::totalSize(); } - GSL_SUPPRESS( - c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + // clang-format off + GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + // clang-format on constexpr size_type elementNum(std::size_t dim) const noexcept { if (dim > 0) @@ -422,7 +448,7 @@ namespace details }; template - struct[[deprecated]] BoundsRanges : BoundsRanges + struct [[deprecated]] BoundsRanges : BoundsRanges { using Base = BoundsRanges; using size_type = std::ptrdiff_t; @@ -440,12 +466,14 @@ namespace details bool firstLevel = true) : Base(static_cast&>(other), false) { + // clang-format off GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive + // clang-format on (void) firstLevel; } template - constexpr void serialize(T & arr) const + constexpr void serialize(T& arr) const { arr[Dim] = elementNum(); this->Base::template serialize(arr); @@ -454,9 +482,13 @@ namespace details template constexpr size_type linearize(const T& arr) const { + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on Expects(arr[Dim] >= 0 && arr[Dim] < CurrentRange); // Index is out of range + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on const std::ptrdiff_t d = arr[Dim]; return this->Base::totalSize() * d + this->Base::template linearize(arr); } @@ -470,19 +502,22 @@ namespace details return this->Base::totalSize() * arr[Dim] + last; } - GSL_SUPPRESS( - c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + // clang-format off + GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + // clang-format on constexpr size_type totalSize() const noexcept { return CurrentRange * this->Base::totalSize(); } - GSL_SUPPRESS( - c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + // clang-format off + GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + // clang-format on constexpr size_type elementNum() const noexcept { return CurrentRange; } - GSL_SUPPRESS( - c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + // clang-format off + GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + // clang-format on constexpr size_type elementNum(std::size_t dim) const noexcept { if (dim > 0) @@ -498,14 +533,17 @@ namespace details }; template - struct[[deprecated]] BoundsRangeConvertible + struct [[deprecated]] BoundsRangeConvertible : public std::integral_constant= TargetType::TotalSize || TargetType::TotalSize == dynamic_range || SourceType::TotalSize == dynamic_range || - TargetType::TotalSize == 0)>{}; + TargetType::TotalSize == 0)> + { + }; template - struct [[deprecated]] TypeListIndexer { + struct [[deprecated]] TypeListIndexer + { const TypeChain& obj_; constexpr TypeListIndexer(const TypeChain& obj) : obj_(obj) {} @@ -518,13 +556,13 @@ namespace details template constexpr auto getObj(std::false_type) - ->decltype(TypeListIndexer(static_cast(obj_)).template get()) + -> decltype(TypeListIndexer(static_cast(obj_)).template get()) { return TypeListIndexer(static_cast(obj_)).template get(); } template - constexpr auto get()->decltype(getObj(std::integral_constant())) + constexpr auto get() -> decltype(getObj(std::integral_constant())) { return getObj(std::integral_constant()); } @@ -543,7 +581,9 @@ namespace details Ret ret{}; for (std::size_t i = 0; i < Rank - 1; ++i) { + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on ret[i] = other[i + 1]; } return ret; @@ -554,13 +594,14 @@ template class [[deprecated]] bounds_iterator; template -class [[deprecated]] static_bounds { +class [[deprecated]] static_bounds +{ public: static_bounds(const details::BoundsRanges&) {} }; template -class[[deprecated]] static_bounds +class [[deprecated]] static_bounds { using MyRanges = details::BoundsRanges; @@ -592,10 +633,10 @@ public: template > - static auto helpBoundsRangeConvertible(SourceType, TargetType, std::true_type)->Ret; + static auto helpBoundsRangeConvertible(SourceType, TargetType, std::true_type) -> Ret; template - static auto helpBoundsRangeConvertible(SourceType, TargetType, ...)->std::false_type; + static auto helpBoundsRangeConvertible(SourceType, TargetType, ...) -> std::false_type; template struct BoundsRangeConvertible2 @@ -721,7 +762,8 @@ public: }; template -class [[deprecated]] strided_bounds { +class [[deprecated]] strided_bounds +{ template friend class strided_bounds; @@ -745,7 +787,7 @@ public: constexpr strided_bounds& operator=(const strided_bounds&) noexcept = default; - constexpr strided_bounds(const value_type(&values)[rank], index_type strides) + constexpr strided_bounds(const value_type (&values)[rank], index_type strides) : m_extents(values), m_strides(std::move(strides)) {} @@ -755,7 +797,9 @@ public: constexpr index_type strides() const noexcept { return m_strides; } + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on constexpr size_type total_size() const noexcept { size_type ret = 0; @@ -763,7 +807,9 @@ public: return ret + 1; } + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on constexpr size_type size() const noexcept { size_type ret = 1; @@ -780,7 +826,9 @@ public: return true; } + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on constexpr size_type linearize(const index_type& idx) const { size_type ret = 0; @@ -792,7 +840,9 @@ public: return ret; } + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on constexpr size_type stride() const noexcept { return m_strides[0]; } template 1), typename Ret = std::enable_if_t> @@ -803,7 +853,9 @@ public: template + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on constexpr size_type extent() const noexcept { static_assert(Dim < Rank, @@ -823,14 +875,21 @@ private: }; template -struct[[deprecated]] is_bounds : std::integral_constant{}; +struct [[deprecated]] is_bounds : std::integral_constant +{ +}; template -struct[[deprecated]] is_bounds> : std::integral_constant{}; +struct [[deprecated]] is_bounds> : std::integral_constant +{ +}; template -struct[[deprecated]] is_bounds> : std::integral_constant{}; +struct [[deprecated]] is_bounds> : std::integral_constant +{ +}; template -class [[deprecated]] bounds_iterator { +class [[deprecated]] bounds_iterator +{ public: static const std::size_t rank = IndexType::rank; using iterator_category = std::random_access_iterator_tag; @@ -851,8 +910,10 @@ public: constexpr pointer operator->() const noexcept { return &curr_; } + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute + // clang-format on constexpr bounds_iterator& operator++() noexcept { @@ -877,7 +938,9 @@ public: return ret; } + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on constexpr bounds_iterator& operator--() { if (!less(curr_, boundary_)) @@ -914,7 +977,9 @@ public: return ret += n; } + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on constexpr bounds_iterator& operator+=(difference_type n) { auto linear_idx = linearize(curr_) + n; @@ -964,15 +1029,17 @@ public: constexpr bool operator>=(const bounds_iterator& rhs) const noexcept { return !(rhs > *this); } - void swap(bounds_iterator & rhs) noexcept + void swap(bounds_iterator& rhs) noexcept { std::swap(boundary_, rhs.boundary_); std::swap(curr_, rhs.curr_); } private: + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute - constexpr bool less(index_type & one, index_type & other) const noexcept + // clang-format on + constexpr bool less(index_type& one, index_type& other) const noexcept { for (std::size_t i = 0; i < rank; ++i) { @@ -981,7 +1048,9 @@ private: return false; } + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on constexpr index_size_type linearize(const value_type& idx) const noexcept { // TODO: Smarter impl. @@ -1043,8 +1112,10 @@ namespace details stride[Bounds::rank - 1] = 1; for (std::size_t i = 1; i < Bounds::rank; ++i) { + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute + // clang-format on stride[Bounds::rank - i - 1] = stride[Bounds::rank - i] * extents[Bounds::rank - i]; } return {stride}; @@ -1098,10 +1169,12 @@ constexpr dim_t dim(std::ptrdiff_t n) noexcept template -class [[deprecated("gsl::multi_span is deprecated because it is not in the C++ Core Guidelines")]] multi_span; +class [[deprecated( + "gsl::multi_span is deprecated because it is not in the C++ Core Guidelines")]] multi_span; template -class [[deprecated("gsl::strided_span is deprecated because it is not in the C++ Core Guidelines")]] strided_span; +class [[deprecated( + "gsl::strided_span is deprecated because it is not in the C++ Core Guidelines")]] strided_span; namespace details { @@ -1188,8 +1261,8 @@ namespace details }; template - struct [[deprecated]] is_multi_span_oracle> - : std::true_type + struct [[deprecated]] is_multi_span_oracle< + multi_span> : std::true_type { }; @@ -1205,7 +1278,9 @@ namespace details } // namespace details template -class [[deprecated("gsl::multi_span is deprecated because it is not in the C++ Core Guidelines")]] multi_span { +class [[deprecated( + "gsl::multi_span is deprecated because it is not in the C++ Core Guidelines")]] multi_span +{ // TODO do we still need this? template @@ -1237,7 +1312,9 @@ private: public: // default constructor - same as constructing from nullptr_t + // clang-format off GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive + // clang-format on constexpr multi_span() noexcept : multi_span(nullptr, bounds_type{}) { static_assert(bounds_type::dynamic_rank != 0 || @@ -1247,7 +1324,9 @@ public: } // construct from nullptr - get an empty multi_span + // clang-format off GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive + // clang-format on constexpr multi_span(std::nullptr_t) noexcept : multi_span(nullptr, bounds_type{}) { static_assert(bounds_type::dynamic_rank != 0 || @@ -1271,7 +1350,9 @@ public: // construct from a single element + // clang-format off GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive + // clang-format on constexpr multi_span(reference data) noexcept : multi_span(&data, bounds_type{1}) { static_assert(bounds_type::dynamic_rank > 0 || bounds_type::static_size == 0 || @@ -1284,7 +1365,9 @@ public: constexpr multi_span(value_type &&) = delete; // construct from pointer + length + // clang-format off GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive + // clang-format on constexpr multi_span(pointer ptr, size_type size) : multi_span(ptr, bounds_type{size}) {} // construct from pointer + length - multidimensional @@ -1521,7 +1604,9 @@ public: return this->operator[](idx); } + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on constexpr reference operator[](const index_type& idx) const { return data_[bounds_.linearize(idx)]; @@ -1529,7 +1614,9 @@ public: template 1), typename Ret = std::enable_if_t> + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on constexpr Ret operator[](size_type idx) const { Expects(idx >= 0 && idx < bounds_.size()); // index is out of bounds of the array @@ -1544,7 +1631,9 @@ public: constexpr iterator end() const noexcept { return iterator{this, false}; } + // clang-format off GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on constexpr const_iterator cbegin() const noexcept { return const_iterator{reinterpret_cast(this), true}; @@ -1642,8 +1731,7 @@ constexpr auto as_multi_span(SpanType s, Dimensions2... dims) // convert a multi_span to a multi_span template -multi_span -as_bytes(multi_span s) noexcept +multi_span as_bytes(multi_span s) noexcept { static_assert(std::is_trivial>::value, "The value_type of multi_span must be a trivial type."); @@ -1729,8 +1817,7 @@ constexpr auto as_multi_span(T* arr, std::ptrdiff_t len) -> } template -constexpr auto as_multi_span(T (&arr)[N]) -> - typename details::SpanArrayTraits::type +constexpr auto as_multi_span(T (&arr)[N]) -> typename details::SpanArrayTraits::type { return {arr}; } @@ -1772,7 +1859,9 @@ constexpr auto as_multi_span(Cont&& arr) -> std::enable_if_t< // from basic_string which doesn't have nonconst .data() member like other contiguous containers template +// clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute +// clang-format on constexpr auto as_multi_span(std::basic_string& str) -> multi_span { @@ -1783,7 +1872,8 @@ constexpr auto as_multi_span(std::basic_string& str) // strided_span is an extension that is not strictly part of the GSL at this time. // It is kept here while the multidimensional interface is still being defined. template -class [[deprecated("gsl::strided_span is deprecated because it is not in the C++ Core Guidelines")]] strided_span +class [[deprecated( + "gsl::strided_span is deprecated because it is not in the C++ Core Guidelines")]] strided_span { public: using bounds_type = strided_bounds; @@ -1818,13 +1908,15 @@ public: Expects((bounds_.size() > 0 && ptr != nullptr) || bounds_.size() == 0); // Bounds cross data boundaries Expects(this->bounds().total_size() <= size); + // clang-format off GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive + // clang-format on (void) size; } // from static array of size N template - constexpr strided_span(value_type (&values)[N], bounds_type bounds) + constexpr strided_span(value_type(&values)[N], bounds_type bounds) : strided_span(values, N, std::move(bounds)) {} @@ -1839,7 +1931,7 @@ public: // convertible template ::value>> + OtherValueType(*)[], value_type(*)[]>::value>> constexpr strided_span(const strided_span& other) : data_(other.data_), bounds_(other.bounds_) {} @@ -1858,7 +1950,9 @@ public: const size_type size = this->bounds().total_size() / d; + // clang-format off GSL_SUPPRESS(type.3) // NO-FORMAT: attribute + // clang-format on return {const_cast(reinterpret_cast(this->data())), size, bounds_type{resize_extent(this->bounds().index_bounds(), d), @@ -1872,14 +1966,18 @@ public: bounds_type{extents, details::make_stride(bounds())}}; } + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on constexpr reference operator[](const index_type& idx) const { return data_[bounds_.linearize(idx)]; } template 1), typename Ret = std::enable_if_t> + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on constexpr Ret operator[](size_type idx) const { Expects(idx < bounds_.size()); // index is out of bounds of the array @@ -1983,7 +2081,9 @@ private: static index_type resize_extent(const index_type& extent, std::ptrdiff_t d) { // The last dimension of the array needs to contain a multiple of new type elements + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on Expects(extent[Rank - 1] >= d && (extent[Rank - 1] % d == 0)); index_type ret = extent; @@ -1996,14 +2096,18 @@ private: static index_type resize_stride(const index_type& strides, std::ptrdiff_t, void* = nullptr) { // Only strided arrays with regular strides can be resized + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on Expects(strides[Rank - 1] == 1); return strides; } template 1), typename = std::enable_if_t> + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on static index_type resize_stride(const index_type& strides, std::ptrdiff_t d) { // Only strided arrays with regular strides can be resized @@ -2026,7 +2130,8 @@ private: }; template -class [[deprecated]] contiguous_span_iterator { +class [[deprecated]] contiguous_span_iterator +{ public: using iterator_category = std::random_access_iterator_tag; using value_type = typename Span::value_type; @@ -2041,14 +2146,18 @@ private: pointer data_; const Span* m_validator; + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on void validateThis() const { // iterator is out of range of the array Expects(data_ >= m_validator->data_ && data_ < m_validator->data_ + m_validator->size()); } + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on contiguous_span_iterator(const Span* container, bool isbegin) : data_(isbegin ? container->data_ : container->data_ + container->size()) , m_validator(container) @@ -2066,7 +2175,9 @@ public: return data_; } + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on contiguous_span_iterator& operator++() noexcept { ++data_; @@ -2079,7 +2190,9 @@ public: return ret; } + // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on contiguous_span_iterator& operator--() noexcept { --data_; @@ -2132,7 +2245,7 @@ public: bool operator>(const contiguous_span_iterator& rhs) const { return rhs < *this; } bool operator>=(const contiguous_span_iterator& rhs) const { return !(rhs > *this); } - void swap(contiguous_span_iterator & rhs) noexcept + void swap(contiguous_span_iterator& rhs) noexcept { std::swap(data_, rhs.data_); std::swap(m_validator, rhs.m_validator); @@ -2147,7 +2260,8 @@ contiguous_span_iterator operator+(typename contiguous_span_iterator } template -class [[deprecated]] general_span_iterator { +class [[deprecated]] general_span_iterator +{ public: using iterator_category = std::random_access_iterator_tag; using value_type = typename Span::value_type; @@ -2213,7 +2327,9 @@ public: return m_itr - rhs.m_itr; } + // clang-format off GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + // clang-format on value_type operator[](difference_type n) const { return (*m_container)[m_itr[n]]; } bool operator==(const general_span_iterator& rhs) const @@ -2230,7 +2346,7 @@ public: bool operator<=(const general_span_iterator& rhs) const { return !(rhs < *this); } bool operator>(const general_span_iterator& rhs) const { return rhs < *this; } bool operator>=(const general_span_iterator& rhs) const { return !(rhs > *this); } - void swap(general_span_iterator & rhs) noexcept + void swap(general_span_iterator& rhs) noexcept { std::swap(m_itr, rhs.m_itr); std::swap(m_container, rhs.m_container); diff --git a/include/gsl/narrow b/include/gsl/narrow new file mode 100644 index 0000000..d47d9fd --- /dev/null +++ b/include/gsl/narrow @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// 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_NARROW_H +#define GSL_NARROW_H +#include // for Expects +#include // for narrow_cast +namespace gsl +{ +struct narrowing_error : public std::exception +{ + const char* what() const noexcept override { return "narrowing_error"; } +}; + +// narrow() : a checked version of narrow_cast() that throws if the cast changed the value +template +// clang-format off +GSL_SUPPRESS(type.1) // NO-FORMAT: attribute +GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false) +// clang-format on + constexpr T narrow(U u) noexcept(false) +{ + constexpr const bool is_different_signedness = + (std::is_signed::value != std::is_signed::value); + + const T t = narrow_cast(u); + + if (static_cast(t) != u || (is_different_signedness && ((t < T{}) != (u < U{})))) + { + throw narrowing_error{}; + } + + return t; +} +} // namespace gsl +#endif // GSL_NARROW_H diff --git a/include/gsl/pointers b/include/gsl/pointers index f7c3885..42e8c09 100644 --- a/include/gsl/pointers +++ b/include/gsl/pointers @@ -17,7 +17,7 @@ #ifndef GSL_POINTERS_H #define GSL_POINTERS_H -#include // for Ensures, Expects +#include // for Ensures, Expects #include // for forward #include // for ptrdiff_t, nullptr_t, size_t @@ -26,8 +26,8 @@ #include // for enable_if_t, is_convertible, is_assignable #if !defined(GSL_NO_IOSTREAMS) -#include // for ostream -#endif // !defined(GSL_NO_IOSTREAMS) +#include // for ostream +#endif // !defined(GSL_NO_IOSTREAMS) namespace gsl { @@ -35,13 +35,14 @@ namespace gsl // // GSL.owner: ownership pointers // -using std::unique_ptr; using std::shared_ptr; +using std::unique_ptr; // // owner // -// owner is designed as a bridge for code that must deal directly with owning pointers for some reason +// 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 @@ -67,7 +68,8 @@ template class not_null { public: - static_assert(std::is_convertible() != nullptr), bool>::value, "T cannot be compared to nullptr."); + static_assert(std::is_convertible() != nullptr), bool>::value, + "T cannot be compared to nullptr."); template ::value>> constexpr not_null(U&& u) : ptr_(std::forward(u)) @@ -83,8 +85,7 @@ public: 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; @@ -116,7 +117,8 @@ private: }; template -auto make_not_null(T&& t) noexcept { +auto make_not_null(T&& t) noexcept +{ return not_null>>{std::forward(t)}; } @@ -130,37 +132,49 @@ std::ostream& operator<<(std::ostream& os, const not_null& val) #endif // !defined(GSL_NO_IOSTREAMS) template -auto operator==(const not_null& lhs, const not_null& rhs) noexcept(noexcept(lhs.get() == rhs.get())) -> decltype(lhs.get() == rhs.get()) +auto operator==(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(lhs.get() == rhs.get())) + -> decltype(lhs.get() == rhs.get()) { return lhs.get() == rhs.get(); } template -auto operator!=(const not_null& lhs, const not_null& rhs) noexcept(noexcept(lhs.get() != rhs.get())) -> decltype(lhs.get() != rhs.get()) +auto operator!=(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(lhs.get() != rhs.get())) + -> decltype(lhs.get() != rhs.get()) { return lhs.get() != rhs.get(); } template -auto operator<(const not_null& lhs, const not_null& rhs) noexcept(noexcept(lhs.get() < rhs.get())) -> decltype(lhs.get() < rhs.get()) +auto operator<(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(lhs.get() < rhs.get())) + -> decltype(lhs.get() < rhs.get()) { return lhs.get() < rhs.get(); } template -auto operator<=(const not_null& lhs, const not_null& rhs) noexcept(noexcept(lhs.get() <= rhs.get())) -> decltype(lhs.get() <= rhs.get()) +auto operator<=(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(lhs.get() <= rhs.get())) + -> decltype(lhs.get() <= rhs.get()) { return lhs.get() <= rhs.get(); } template -auto operator>(const not_null& lhs, const not_null& rhs) noexcept(noexcept(lhs.get() > rhs.get())) -> decltype(lhs.get() > rhs.get()) +auto operator>(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(lhs.get() > rhs.get())) + -> decltype(lhs.get() > rhs.get()) { return lhs.get() > rhs.get(); } template -auto operator>=(const not_null& lhs, const not_null& rhs) noexcept(noexcept(lhs.get() >= rhs.get())) -> decltype(lhs.get() >= rhs.get()) +auto operator>=(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(lhs.get() >= rhs.get())) + -> decltype(lhs.get() >= rhs.get()) { return lhs.get() >= rhs.get(); } @@ -208,28 +222,23 @@ namespace gsl // - remove unnecessary asserts // template -class strict_not_null: public not_null +class strict_not_null : public not_null { public: - template ::value>> - constexpr explicit strict_not_null(U&& u) : - not_null(std::forward(u)) + constexpr explicit strict_not_null(U&& u) : not_null(std::forward(u)) {} template ::value>> - constexpr explicit strict_not_null(T u) : - not_null(u) + constexpr explicit strict_not_null(T u) : not_null(u) {} template ::value>> - constexpr strict_not_null(const not_null& other) : - not_null(other) + constexpr strict_not_null(const not_null& other) : not_null(other) {} template ::value>> - constexpr strict_not_null(const strict_not_null& other) : - not_null(other) + constexpr strict_not_null(const strict_not_null& other) : not_null(other) {} strict_not_null(strict_not_null&& other) = default; @@ -266,15 +275,18 @@ template strict_not_null operator+(std::ptrdiff_t, const strict_not_null&) = delete; template -auto make_strict_not_null(T&& t) noexcept { +auto make_strict_not_null(T&& t) noexcept +{ return strict_not_null>>{std::forward(t)}; } -#if ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) ) +#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) // deduction guides to prevent the ctad-maybe-unsupported warning -template not_null(T) -> not_null; -template strict_not_null(T) -> strict_not_null; +template +not_null(T) -> not_null; +template +strict_not_null(T) -> strict_not_null; #endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) ) @@ -285,7 +297,10 @@ namespace std template struct hash> { - std::size_t operator()(const gsl::strict_not_null& value) const { return hash{}(value.get()); } + std::size_t operator()(const gsl::strict_not_null& value) const + { + return hash{}(value.get()); + } }; } // namespace std diff --git a/include/gsl/span b/include/gsl/span index 73a4d96..0f567df 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -17,9 +17,9 @@ #ifndef GSL_SPAN_H #define GSL_SPAN_H -#include // for Expects -#include // for byte -#include // for narrow_cast +#include // for Expects +#include // for byte +#include // for narrow_cast #include // for array #include // for ptrdiff_t, size_t, nullptr_t @@ -472,66 +472,70 @@ public: // requirement on Container to be a contiguous sequence container. template ::value && !details::is_std_array::value && - std::is_pointer().data())>::value && - std::is_convertible< - std::remove_pointer_t().data())> (*)[], - element_type (*)[]>::value, int> = 0> + MyExtent != dynamic_extent && !details::is_span::value && + !details::is_std_array::value && + std::is_pointer().data())>::value && + std::is_convertible< + std::remove_pointer_t().data())> (*)[], + element_type (*)[]>::value, + int> = 0> constexpr explicit span(Container& cont) noexcept : span(cont.data(), cont.size()) {} template ::value && !details::is_std_array::value && - std::is_pointer().data())>::value && - std::is_convertible< - std::remove_pointer_t().data())> (*)[], - element_type (*)[]>::value, int> = 0> + MyExtent == dynamic_extent && !details::is_span::value && + !details::is_std_array::value && + std::is_pointer().data())>::value && + std::is_convertible< + std::remove_pointer_t().data())> (*)[], + element_type (*)[]>::value, + int> = 0> constexpr span(Container& cont) noexcept : span(cont.data(), cont.size()) {} - template ::value && !details::is_span::value && - !details::is_std_array::value && - std::is_pointer().data())>::value && - std::is_convertible().data())> (*)[], - element_type (*)[]>::value, int> = 0> + template < + std::size_t MyExtent = Extent, class Container, + std::enable_if_t< + MyExtent != dynamic_extent && std::is_const::value && + !details::is_span::value && !details::is_std_array::value && + std::is_pointer().data())>::value && + std::is_convertible< + std::remove_pointer_t().data())> (*)[], + element_type (*)[]>::value, + int> = 0> constexpr explicit span(const Container& cont) noexcept : span(cont.data(), cont.size()) {} - template ::value && !details::is_span::value && - !details::is_std_array::value && - std::is_pointer().data())>::value && - std::is_convertible().data())> (*)[], - element_type (*)[]>::value, int> = 0> + template < + std::size_t MyExtent = Extent, class Container, + std::enable_if_t< + MyExtent == dynamic_extent && std::is_const::value && + !details::is_span::value && !details::is_std_array::value && + std::is_pointer().data())>::value && + std::is_convertible< + std::remove_pointer_t().data())> (*)[], + element_type (*)[]>::value, + int> = 0> constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size()) {} constexpr span(const span& other) noexcept = default; - template < - class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent, - std::enable_if_t< - (MyExtent == dynamic_extent || MyExtent == OtherExtent) && - details::is_allowed_element_type_conversion::value, int> = 0> + template ::value, + int> = 0> constexpr span(const span& other) noexcept : storage_(other.data(), details::extent_type(other.size())) {} - template < - class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent, - std::enable_if_t< - MyExtent != dynamic_extent && OtherExtent == dynamic_extent && - details::is_allowed_element_type_conversion::value, int> = 0> + template ::value, + int> = 0> constexpr explicit span(const span& other) noexcept : storage_(other.data(), details::extent_type(other.size())) {} @@ -565,7 +569,8 @@ public: typename details::calculate_subspan_type::type { Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset))); - using type = typename details::calculate_subspan_type::type; + using type = + typename details::calculate_subspan_type::type; return type{data() + Offset, Count == dynamic_extent ? size() - Offset : Count}; } @@ -581,9 +586,8 @@ public: return make_subspan(size() - count, dynamic_extent, subspan_selector{}); } - constexpr span subspan(size_type offset, - size_type count = dynamic_extent) const - noexcept + constexpr span + subspan(size_type offset, size_type count = dynamic_extent) const noexcept { return make_subspan(offset, count, subspan_selector{}); } @@ -706,9 +710,8 @@ private: }; template - constexpr span make_subspan(size_type offset, size_type count, - subspan_selector) const - noexcept + constexpr span + make_subspan(size_type offset, size_type count, subspan_selector) const noexcept { const span tmp(*this); return tmp.subspan(offset, count); @@ -733,21 +736,21 @@ private: // Deduction Guides template -span(Type (&)[Extent])->span; +span(Type (&)[Extent]) -> span; template -span(std::array&)->span; +span(std::array&) -> span; template -span(const std::array&)->span; +span(const std::array&) -> span; template ().data())>> -span(Container&)->span; + class Element = std::remove_pointer_t().data())>> +span(Container&) -> span; template ().data())>> -span(const Container&)->span; + class Element = std::remove_pointer_t().data())>> +span(const Container&) -> span; #endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) ) diff --git a/include/gsl/span_ext b/include/gsl/span_ext index 1d375fd..b7c12cf 100644 --- a/include/gsl/span_ext +++ b/include/gsl/span_ext @@ -27,9 +27,8 @@ // /////////////////////////////////////////////////////////////////////////////// - -#include // for narrow_cast, narrow -#include // for span +#include // for span +#include // for narrow_cast, narrow #include // for lexicographical_compare #include // for ptrdiff_t, size_t diff --git a/include/gsl/string_span b/include/gsl/string_span index 2c11228..a76236d 100644 --- a/include/gsl/string_span +++ b/include/gsl/string_span @@ -17,9 +17,9 @@ #ifndef GSL_STRING_SPAN_H #define GSL_STRING_SPAN_H -#include // for Ensures, Expects -#include // for narrow_cast -#include // for operator!=, operator==, dynamic_extent +#include // for Ensures, Expects +#include // for operator!=, operator==, dynamic_extent +#include // for narrow_cast #include // for equal, lexicographical_compare #include // for array @@ -167,10 +167,9 @@ class [[deprecated("string_span was removed from the C++ Core Guidelines. For mo namespace details { template - struct [ - [deprecated("string_span was removed from the C++ Core Guidelines. For more information, " - "see isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span_oracle - : std::false_type{}; + struct [[deprecated( + "string_span was removed from the C++ Core Guidelines. For more information, " + "see isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span_oracle : std::false_type{}; template struct [[deprecated( diff --git a/include/gsl/util b/include/gsl/util new file mode 100644 index 0000000..2d67b7f --- /dev/null +++ b/include/gsl/util @@ -0,0 +1,145 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// 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_UTIL_H +#define GSL_UTIL_H + +#include // for Expects + +#include +#include // for ptrdiff_t, size_t +#include // for initializer_list +#include // for is_signed, integral_constant +#include // for exchange, forward + +#if defined(_MSC_VER) && !defined(__clang__) + +#pragma warning(push) +#pragma warning(disable : 4127) // conditional expression is constant + +#endif // _MSC_VER + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +#define GSL_NODISCARD [[nodiscard]] +#else +#define GSL_NODISCARD +#endif // defined(__cplusplus) && (__cplusplus >= 201703L) + +namespace gsl +{ +// +// GSL.util: utilities +// + +// index type for all container indexes/subscripts/sizes +using index = std::ptrdiff_t; + +// final_action allows you to ensure something gets run at the end of a scope +template +class final_action +{ +public: + static_assert(!std::is_reference::value && !std::is_const::value && + !std::is_volatile::value, + "Final_action should store its callable by value"); + + explicit final_action(F f) noexcept : f_(std::move(f)) {} + + final_action(final_action&& other) noexcept + : f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false)) + {} + + final_action(const final_action&) = delete; + final_action& operator=(const final_action&) = delete; + final_action& operator=(final_action&&) = delete; + + // clang-format off + GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws + // clang-format on + ~final_action() noexcept + { + if (invoke_) f_(); + } + +private: + F f_; + bool invoke_{true}; +}; + +// finally() - convenience function to generate a final_action +template +GSL_NODISCARD final_action::type>::type> +finally(F&& f) noexcept +{ + return final_action::type>::type>( + std::forward(f)); +} + +// narrow_cast(): a searchable way to do narrowing casts of values +template +// clang-format off +GSL_SUPPRESS(type.1) // NO-FORMAT: attribute +// clang-format on +constexpr T narrow_cast(U&& u) noexcept +{ + return static_cast(std::forward(u)); +} + +// +// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector +// +template +// clang-format off +GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute +GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute +// clang-format on + constexpr T& at(T (&arr)[N], const index i) +{ + Expects(i >= 0 && i < narrow_cast(N)); + return arr[narrow_cast(i)]; +} + +template +// clang-format off +GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute +GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute +// clang-format on + constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()]) +{ + Expects(i >= 0 && i < narrow_cast(cont.size())); + using size_type = decltype(cont.size()); + return cont[narrow_cast(i)]; +} + +template +// clang-format off +GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute +// clang-format on +constexpr T at(const std::initializer_list cont, const index i) +{ + Expects(i >= 0 && i < narrow_cast(cont.size())); + return *(cont.begin() + i); +} + +} // namespace gsl + +#if defined(_MSC_VER) && !defined(__clang__) + +#pragma warning(pop) + +#endif // _MSC_VER + +#endif // GSL_UTIL_H diff --git a/tests/algorithm_tests.cpp b/tests/algorithm_tests.cpp index ec9b2d1..0f209ac 100644 --- a/tests/algorithm_tests.cpp +++ b/tests/algorithm_tests.cpp @@ -15,7 +15,7 @@ /////////////////////////////////////////////////////////////////////////////// #include -#include // for copy +#include // for copy #include // for span #include // for array #include // for size_t diff --git a/tests/assertion_tests.cpp b/tests/assertion_tests.cpp index c45b00c..6b5fb0b 100644 --- a/tests/assertion_tests.cpp +++ b/tests/assertion_tests.cpp @@ -15,7 +15,7 @@ /////////////////////////////////////////////////////////////////////////////// #include -#include // for fail_fast (ptr only), Ensures, Expects +#include // for fail_fast (ptr only), Ensures, Expects using namespace gsl; diff --git a/tests/at_tests.cpp b/tests/at_tests.cpp index be2c7b8..1285139 100644 --- a/tests/at_tests.cpp +++ b/tests/at_tests.cpp @@ -16,7 +16,7 @@ #include -#include // for at +#include // for at #include // for array #include // for size_t diff --git a/tests/byte_tests.cpp b/tests/byte_tests.cpp index f2850ad..2a86cac 100644 --- a/tests/byte_tests.cpp +++ b/tests/byte_tests.cpp @@ -16,7 +16,7 @@ #include -#include // for to_byte, to_integer, byte, operator&, ope... +#include // for to_byte, to_integer, byte, operator&, ope... using namespace std; using namespace gsl; diff --git a/tests/multi_span_tests.cpp b/tests/multi_span_tests.cpp index 32dbf94..9f93315 100644 --- a/tests/multi_span_tests.cpp +++ b/tests/multi_span_tests.cpp @@ -16,8 +16,8 @@ #include -#include // for byte -#include // for narrow_cast +#include // for byte +#include // for narrow_cast #include // for multi_span, contiguous_span_iterator, dim #include // for fill, for_each diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index 5035687..361db84 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -16,7 +16,7 @@ #include -#include // for byte +#include // for byte #include // for span, span_iterator, operator==, operator!= #include // for array diff --git a/tests/span_ext_tests.cpp b/tests/span_ext_tests.cpp index d413e03..4f07188 100644 --- a/tests/span_ext_tests.cpp +++ b/tests/span_ext_tests.cpp @@ -16,7 +16,7 @@ #include -#include // for narrow_cast, at +#include // for narrow_cast, at #include // for operator==, operator!=, make_span #include // for array diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 6caaeea..b845d07 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -16,8 +16,8 @@ #include -#include // for byte -#include // for narrow_cast, at +#include // for byte +#include // for narrow_cast, at #include // for span, span_iterator, operator==, operator!= #include // for array diff --git a/tests/strided_span_tests.cpp b/tests/strided_span_tests.cpp index 5a18f1b..67b23eb 100644 --- a/tests/strided_span_tests.cpp +++ b/tests/strided_span_tests.cpp @@ -15,8 +15,8 @@ /////////////////////////////////////////////////////////////////////////////// #include -#include // for byte -#include // for narrow_cast +#include // for byte +#include // for narrow_cast #include // for strided_span, index, multi_span, strided_... #include // for size_t diff --git a/tests/string_span_tests.cpp b/tests/string_span_tests.cpp index 7a9f7fb..3c919d0 100644 --- a/tests/string_span_tests.cpp +++ b/tests/string_span_tests.cpp @@ -16,7 +16,7 @@ #include -#include // for Expects, fail_fast (ptr only) +#include // for Expects, fail_fast (ptr only) #include // for owner #include // for span, dynamic_extent #include // for basic_string_span, operator==, ensure_z diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp index 430788e..74dc990 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -16,8 +16,8 @@ #include -#include // finally, narrow_cast -#include // for narrow, narrowing_error +#include // finally, narrow_cast +#include // for narrow, narrowing_error #include // for move #include // for reference_wrapper, _Bind_helper<>::type #include // for numeric_limits