From ad64a1759a506bb0761c7b20c40da8c91865f50e Mon Sep 17 00:00:00 2001 From: ThePhD Date: Thu, 2 Nov 2023 18:20:59 -0400 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Complete=20rewrite=20internal=20spa?= =?UTF-8?q?n=20to=20use=20own=20personal=20implementation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/ztd/idk/assert.h | 6 +- include/ztd/idk/assert.hpp | 168 ++ .../ztd/idk/detail/span.implementation.hpp | 1990 +++-------------- include/ztd/idk/explicit.hpp | 61 + include/ztd/idk/is_array.hpp | 70 + include/ztd/idk/span.hpp | 29 +- include/ztd/idk/type_traits.hpp | 20 + include/ztd/ranges/adl.hpp | 242 +- include/ztd/ranges/range.hpp | 120 +- include/ztd/ranges/reconstruct.hpp | 196 +- include/ztd/version/detail/is.h | 2 +- include/ztd/version/detail/version.c++.hpp | 75 +- include/ztd/version/detail/version.c.h | 22 +- 13 files changed, 1182 insertions(+), 1819 deletions(-) create mode 100644 include/ztd/idk/explicit.hpp create mode 100644 include/ztd/idk/is_array.hpp diff --git a/include/ztd/idk/assert.h b/include/ztd/idk/assert.h index 9d99434..791411c 100644 --- a/include/ztd/idk/assert.h +++ b/include/ztd/idk/assert.h @@ -66,7 +66,7 @@ do { \ if (!(__VA_ARGS__)) { \ fprintf(stderr, "Assertion `%s` failed in " __FILE__ " line " \ - ZTD_TOKEN_TO_STRING_I_(__LINE__) "\n", \ + ZTD_TOKEN_TO_STRING(__LINE__) "\n", \ #__VA_ARGS__ ); \ exit(0xBF); \ } \ @@ -105,7 +105,7 @@ do { \ if (!(__VA_ARGS__)) { \ fprintf(stderr, "Assertion `%s` failed in " __FILE__ " line " \ - ZTD_TOKEN_TO_STRING_I_(__LINE__) ": %s\n", \ + ZTD_TOKEN_TO_STRING(__LINE__) ": %s\n", \ #__VA_ARGS__ , _MESSAGE); \ exit(0xBF); \ } \ @@ -147,6 +147,4 @@ /// terminate/exit (not abort). #define ZTD_ASSERT_MESSAGE(_MESSAGE, ...) ZTD_ASSERT_MESSAGE_I_(_MESSAGE, __VA_ARGS__) -#include - #endif diff --git a/include/ztd/idk/assert.hpp b/include/ztd/idk/assert.hpp index e47c060..87cf45e 100644 --- a/include/ztd/idk/assert.hpp +++ b/include/ztd/idk/assert.hpp @@ -37,4 +37,172 @@ #include +// clang-format off +#if defined(ZTD_CONSTEXPR_ASSERT_USER) + #define ZTD_CONSTEXPR_ASSERT_I_(...) ZTD_CONSTEXPR_ASSERT_USER(__VA_ARGS__) +#else + #if ZTD_IS_ON(ZTD_CONSTEXPR_ASSERT_CHECKS) + #if ZTD_IS_ON(ZTD_STD_LIBRARY_IS_CONSTANT_EVALUATED) + #if ZTD_IS_ON(ZTD_EXCEPTIONS) + #include + #include + #include + #include + + #define ZTD_CONSTEXPR_ASSERT_I_(...) \ + do { \ + if (!(__VA_ARGS__)) { \ + if (::std::is_constant_evaluated()) { \ + throw "Assertion " #__VA_ARGS__ "failed in " __FILE__ " line " ZTD_TOKEN_TO_STRING(__LINE__);\ + } \ + else { \ + ::std::cerr << "Assertion `" #__VA_ARGS__ "` failed in `" __FILE__ "` line " << \ + __LINE__ << ::std::endl; \ + ::std::terminate(); \ + } \ + } \ + } while (false) + #else + #include + #include + #include + #include + + #define ZTD_CONSTEXPR_ASSERT_I_(...) \ + do { \ + if (!(__VA_ARGS__)) { \ + if (::std::is_constant_evaluated()) { \ + /* ?????*/; \ + } \ + else { \ + ::std::cerr << "Assertion `" #__VA_ARGS__ "` failed in `" __FILE__ "` line " << \ + __LINE__ << ::std::endl; \ + ::std::terminate(); \ + } \ + } \ + } while (false) + #endif + #else + #if ZTD_IS_ON(ZTD_EXCEPTIONS) + #include + + #define ZTD_CONSTEXPR_ASSERT_I_(...) \ + do { \ + if (!(__VA_ARGS__)) { \ + throw "Assertion `" #__VA_ARGS__ "` failed in `" __FILE__ "` line " ZTD_TOKEN_TO_STRING(__LINE__);\ + \ + } \ + } while (false) + #else + #include + + #define ZTD_CONSTEXPR_ASSERT_I_(...) \ + do { \ + if (!(__VA_ARGS__)) { \ + /* ????? */; \ + } \ + } while (false) + #endif + #endif + #else + #define ZTD_CONSTEXPR_ASSERT_I_(...) \ + do { \ + if (false) { \ + (void)(__VA_ARGS__); \ + } \ + } while (false) + #endif +#endif + +#if defined(ZTD_CONSTEXPR_ASSERT_MESSAGE_USER) + #define ZTD_CONSTEXPR_ASSERT_MESSAGE_I_(...) ZTD_CONSTEXPR_ASSERT_MESSAGE_USER(__VA_ARGS__) +#else + #if ZTD_IS_ON(ZTD_CONSTEXPR_ASSERT_CHECKS) + #if ZTD_IS_ON(ZTD_STD_LIBRARY_IS_CONSTANT_EVALUATED) + #if ZTD_IS_ON(ZTD_EXCEPTIONS) + #include + #include + #include + #include + + #define ZTD_CONSTEXPR_ASSERT_MESSAGE_I_(_MESSAGE, ...) \ + do { \ + if (!(__VA_ARGS__)) { \ + if (::std::is_constant_evaluated()) { \ + throw "Assertion `" #__VA_ARGS__ "1 failed in `" __FILE__ "` line " ZTD_TOKEN_TO_STRING(__LINE__) ": " _MESSAGE;\ + } \ + else { \ + ::std::cerr << "Assertion `" #__VA_ARGS__ "` failed in `" __FILE__ "` line " << __LINE__ << ": " \ + << _MESSAGE << ::std::endl; \ + ::std::terminate(); \ + } \ + } \ + } while (false) + #else + #include + #include + #include + + #define ZTD_CONSTEXPR_ASSERT_MESSAGE_I_(_MESSAGE, ...) \ + do { \ + if (!(__VA_ARGS__)) { \ + if (::std::is_constant_evaluated()) { \ + /* ????? */ \ + } \ + else { \ + ::std::cerr << "Assertion `" #__VA_ARGS__ "` failed in `" __FILE__ "` line " << __LINE__ << ": " \ + << _MESSAGE << ::std::endl; \ + ::std::terminate(); \ + } \ + } \ + } while (false) + #endif + #endif + #else + #if ZTD_IS_ON(ZTD_EXCEPTIONS) + #define ZTD_CONSTEXPR_ASSERT_MESSAGE_I_(_MESSAGE, ...) \ + do { \ + if (!(__VA_ARGS__)) { \ + throw "Assertion `" #__VA_ARGS__ "` failed in `" __FILE__ "` line " ZTD_TOKEN_TO_STRING(__LINE__) ": " _MESSAGE;\ + } \ + } while (false) + #else + #include + + #define ZTD_CONSTEXPR_ASSERT_MESSAGE_I_(_MESSAGE, ...) \ + do { \ + if (!(__VA_ARGS__)) { \ + /* ???? */ \ + (void)sizeof(_MESSAGE); \ + } \ + } while (false) + #endif + #endif +#endif + +// clang-format on + +////// +/// @brief A macro for asserting over a given (set of) conditions. +/// +/// @param[in] ... The conditional expressions to check against. +/// +/// @remarks The conditions must result in a value that is convertible to a boolean in a boolean context. This macro +/// does nothing when `ZTD_CONSTEXPR_ASSERT_CHECKS` is not detected. (It will still (void)-cast the used items, to prevent unused +/// warnings.) If the condition is not reached, this function will perform either a user-defined action or +/// terminate/exit (not abort). +#define ZTD_CONSTEXPR_ASSERT(...) ZTD_CONSTEXPR_ASSERT_I_(__VA_ARGS__) + +////// +/// @brief A macro for asserting over a given (set of) conditions. +/// +/// @param[in] _MESSAGE The message to pass through. +/// @param[in] ... The conditional expressions to check against. +/// +/// @remarks The conditions must result in a value that is convertible to a boolean in a boolean context. This macro +/// does nothing when `ZTD_CONSTEXPR_ASSERT_CHECKS` is not detected. (It will still (void)-cast the used items, to prevent unused +/// warnings.) If the condition is not reached, this function will perform either a user-defined action or +/// terminate/exit (not abort). +#define ZTD_CONSTEXPR_ASSERT_MESSAGE(_MESSAGE, ...) ZTD_CONSTEXPR_ASSERT_MESSAGE_I_(_MESSAGE, __VA_ARGS__) + #endif diff --git a/include/ztd/idk/detail/span.implementation.hpp b/include/ztd/idk/detail/span.implementation.hpp index 5b6c2ec..4187f68 100644 --- a/include/ztd/idk/detail/span.implementation.hpp +++ b/include/ztd/idk/detail/span.implementation.hpp @@ -1,1794 +1,502 @@ +// ============================================================================= // -// span for C++98 and later. -// Based on http://wg21.link/p0122r7 -// For more information see https://github.com/martinmoene/span-lite +// ztd.idk +// Copyright © 2022-2023 JeanHeyd "ThePhD" Meneide and Shepherd's Oasis, LLC +// Contact: opensource@soasis.org // -// Copyright 2018-2020 Martin Moene +// Commercial License Usage +// Licensees holding valid commercial ztd.idk licenses may use this file in +// accordance with the commercial license agreement provided with the +// Software or, alternatively, in accordance with the terms contained in +// a written agreement between you and Shepherd's Oasis, LLC. +// For licensing terms and conditions see your agreement. For +// further information contact opensource@soasis.org. // -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef NONSTD_SPAN_HPP_INCLUDED -#define NONSTD_SPAN_HPP_INCLUDED - -#include - -#define span_lite_MAJOR 0 -#define span_lite_MINOR 9 -#define span_lite_PATCH 2 - -#define span_lite_VERSION \ - span_STRINGIFY(span_lite_MAJOR) "." span_STRINGIFY(span_lite_MINOR) "." span_STRINGIFY(span_lite_PATCH) - -#define span_STRINGIFY(x) span_STRINGIFY_(x) -#define span_STRINGIFY_(x) #x - -// span configuration: - -#define span_SPAN_DEFAULT 0 -#define span_SPAN_NONSTD 1 -#define span_SPAN_STD 2 - -// tweak header support: - -#ifdef __has_include -#if __has_include() -#include -#endif -#define span_HAVE_TWEAK_HEADER 1 -#else -#define span_HAVE_TWEAK_HEADER 0 -// # pragma message("span.hpp: Note: Tweak header not supported.") -#endif - -// span selection and configuration: - -#define span_HAVE(feature) (span_HAVE_##feature) - -#ifndef span_CONFIG_SELECT_SPAN -#define span_CONFIG_SELECT_SPAN (span_HAVE_STD_SPAN ? span_SPAN_STD : span_SPAN_NONSTD) -#endif - -#ifndef span_CONFIG_EXTENT_TYPE -#define span_CONFIG_EXTENT_TYPE std::size_t -#endif - -#ifndef span_CONFIG_SIZE_TYPE -#define span_CONFIG_SIZE_TYPE std::size_t -#endif - -#ifdef span_CONFIG_INDEX_TYPE -#error `span_CONFIG_INDEX_TYPE` is deprecated since v0.7.0; it is replaced by `span_CONFIG_SIZE_TYPE`. -#endif - -// span configuration (features): - -#ifndef span_FEATURE_WITH_CONTAINER -#ifdef span_FEATURE_WITH_CONTAINER_TO_STD -#define span_FEATURE_WITH_CONTAINER span_IN_STD(span_FEATURE_WITH_CONTAINER_TO_STD) -#else -#define span_FEATURE_WITH_CONTAINER 0 -#endif -#endif - -#ifndef span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE -#define span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE 0 -#endif - -#ifndef span_FEATURE_MEMBER_AT -#define span_FEATURE_MEMBER_AT 0 -#endif - -#ifndef span_FEATURE_MEMBER_BACK_FRONT -#define span_FEATURE_MEMBER_BACK_FRONT 1 -#endif - -#ifndef span_FEATURE_MEMBER_CALL_OPERATOR -#define span_FEATURE_MEMBER_CALL_OPERATOR 0 -#endif - -#ifndef span_FEATURE_MEMBER_SWAP -#define span_FEATURE_MEMBER_SWAP 0 -#endif - -#ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB -#define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB 0 -#elif span_FEATURE_NON_MEMBER_FIRST_LAST_SUB -#define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN 1 -#define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER 1 -#endif - -#ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN -#define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN 0 -#endif - -#ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER -#define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER 0 -#endif - -#ifndef span_FEATURE_COMPARISON -#define span_FEATURE_COMPARISON 1 // Note: C++20 does not provide comparison -#endif - -#ifndef span_FEATURE_SAME -#define span_FEATURE_SAME 0 -#endif - -#if span_FEATURE_SAME && !span_FEATURE_COMPARISON -#error `span_FEATURE_SAME` requires `span_FEATURE_COMPARISON` -#endif - -#ifndef span_FEATURE_MAKE_SPAN -#ifdef span_FEATURE_MAKE_SPAN_TO_STD -#define span_FEATURE_MAKE_SPAN span_IN_STD(span_FEATURE_MAKE_SPAN_TO_STD) -#else -#define span_FEATURE_MAKE_SPAN 0 -#endif -#endif - -#ifndef span_FEATURE_BYTE_SPAN -#define span_FEATURE_BYTE_SPAN 0 -#endif - -// Control presence of exception handling (try and auto discover): - -#ifndef span_CONFIG_NO_EXCEPTIONS -#if _MSC_VER -#include // for _HAS_EXCEPTIONS -#endif -#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) -#define span_CONFIG_NO_EXCEPTIONS 0 -#else -#define span_CONFIG_NO_EXCEPTIONS 1 -#undef span_CONFIG_CONTRACT_VIOLATION_THROWS -#undef span_CONFIG_CONTRACT_VIOLATION_TERMINATES -#define span_CONFIG_CONTRACT_VIOLATION_THROWS 0 -#define span_CONFIG_CONTRACT_VIOLATION_TERMINATES 1 -#endif -#endif - -// Control pre- and postcondition violation behaviour: - -#if defined(span_CONFIG_CONTRACT_LEVEL_ON) -#define span_CONFIG_CONTRACT_LEVEL_MASK 0x11 -#elif defined(span_CONFIG_CONTRACT_LEVEL_OFF) -#define span_CONFIG_CONTRACT_LEVEL_MASK 0x00 -#elif defined(span_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY) -#define span_CONFIG_CONTRACT_LEVEL_MASK 0x01 -#elif defined(span_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY) -#define span_CONFIG_CONTRACT_LEVEL_MASK 0x10 -#else -#define span_CONFIG_CONTRACT_LEVEL_MASK 0x11 -#endif - -#if defined(span_CONFIG_CONTRACT_VIOLATION_THROWS) -#define span_CONFIG_CONTRACT_VIOLATION_THROWS_V span_CONFIG_CONTRACT_VIOLATION_THROWS -#else -#define span_CONFIG_CONTRACT_VIOLATION_THROWS_V 0 -#endif - -#if defined(span_CONFIG_CONTRACT_VIOLATION_THROWS) && span_CONFIG_CONTRACT_VIOLATION_THROWS \ - && defined(span_CONFIG_CONTRACT_VIOLATION_TERMINATES) && span_CONFIG_CONTRACT_VIOLATION_TERMINATES -# error Please define none or one of span_CONFIG_CONTRACT_VIOLATION_THROWS and span_CONFIG_CONTRACT_VIOLATION_TERMINATES to 1, but not both. -#endif - -// C++ language version detection (C++20 is speculative): -// Note: VC14.0/1900 (VS2015) lacks too much from C++14. - -#ifndef span_CPLUSPLUS -#if defined(_MSVC_LANG) && !defined(__clang__) -#define span_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG) -#else -#define span_CPLUSPLUS __cplusplus -#endif -#endif - -#define span_CPP98_OR_GREATER (span_CPLUSPLUS >= 199711L) -#define span_CPP11_OR_GREATER (span_CPLUSPLUS >= 201103L) -#define span_CPP14_OR_GREATER (span_CPLUSPLUS >= 201402L) -#define span_CPP17_OR_GREATER (span_CPLUSPLUS >= 201703L) -#define span_CPP20_OR_GREATER (span_CPLUSPLUS >= 202000L) - -// C++ language version (represent 98 as 3): - -#define span_CPLUSPLUS_V (span_CPLUSPLUS / 100 - (span_CPLUSPLUS > 200000 ? 2000 : 1994)) - -#define span_IN_STD(v) (((v) == 98 ? 3 : (v)) >= span_CPLUSPLUS_V) - -#define span_CONFIG(feature) (span_CONFIG_##feature) -#define span_FEATURE(feature) (span_FEATURE_##feature) -#define span_FEATURE_TO_STD(feature) (span_IN_STD(span_FEATURE(feature##_TO_STD))) - -// Use C++20 std::span if available and requested: - -#if span_CPP20_OR_GREATER && defined(__has_include) -#if __has_include( ) -#define span_HAVE_STD_SPAN 1 -#else -#define span_HAVE_STD_SPAN 0 -#endif -#else -#define span_HAVE_STD_SPAN 0 -#endif - -#define span_USES_STD_SPAN \ - ((span_CONFIG_SELECT_SPAN == span_SPAN_STD) \ - || ((span_CONFIG_SELECT_SPAN == span_SPAN_DEFAULT) && span_HAVE_STD_SPAN)) - +// Apache License Version 2 Usage +// Alternatively, this file may be used under the terms of Apache License +// Version 2.0 (the "License") for non-commercial use; you may not use this +// file except in compliance with the License. You may obtain a copy of the +// License at // -// Use C++20 std::span: +// https://www.apache.org/licenses/LICENSE-2.0 // - -#if span_USES_STD_SPAN - -#include - -namespace nonstd { - - using std::span; - - using std::as_bytes; - using std::as_writable_bytes; - using std::dynamic_extent; - - // Note: C++20 does not provide comparison - // using std::operator==; - // using std::operator!=; - // using std::operator<; - // using std::operator<=; - // using std::operator>; - // using std::operator>=; -} // namespace nonstd - -#else // span_USES_STD_SPAN - -#include - -// Compiler versions: +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // -// MSVC++ 6.0 _MSC_VER == 1200 span_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0) -// MSVC++ 7.0 _MSC_VER == 1300 span_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002) -// MSVC++ 7.1 _MSC_VER == 1310 span_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) -// MSVC++ 8.0 _MSC_VER == 1400 span_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005) -// MSVC++ 9.0 _MSC_VER == 1500 span_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008) -// MSVC++ 10.0 _MSC_VER == 1600 span_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010) -// MSVC++ 11.0 _MSC_VER == 1700 span_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012) -// MSVC++ 12.0 _MSC_VER == 1800 span_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013) -// MSVC++ 14.0 _MSC_VER == 1900 span_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015) -// MSVC++ 14.1 _MSC_VER >= 1910 span_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) -// MSVC++ 14.2 _MSC_VER >= 1920 span_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019) - -#if defined(_MSC_VER) && !defined(__clang__) -#define span_COMPILER_MSVC_VER (_MSC_VER) -#define span_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * (5 + (_MSC_VER < 1900))) -#else -#define span_COMPILER_MSVC_VER 0 -#define span_COMPILER_MSVC_VERSION 0 -#endif - -#define span_COMPILER_VERSION(major, minor, patch) (10 * (10 * (major) + (minor)) + (patch)) - -#if defined(__clang__) -#define span_COMPILER_CLANG_VERSION span_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) -#else -#define span_COMPILER_CLANG_VERSION 0 -#endif - -#if defined(__GNUC__) && !defined(__clang__) -#define span_COMPILER_GNUC_VERSION span_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#else -#define span_COMPILER_GNUC_VERSION 0 -#endif +// ============================================================================ // -// half-open range [lo..hi): -#define span_BETWEEN(v, lo, hi) ((lo) <= (v) && (v) < (hi)) +#pragma once -// Compiler warning suppression: +#ifndef ZTD_IDK_DETAIL_SPAN_IMPLEMENTATION_HPP +#define ZTD_IDK_DETAIL_SPAN_IMPLEMENTATION_HPP -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wundef" -#pragma clang diagnostic ignored "-Wmismatched-tags" -#define span_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") +#include -#elif defined __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wundef" -#define span_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") - -#elif span_COMPILER_MSVC_VER >= 1900 -#define span_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable : codes)) -#define span_RESTORE_WARNINGS() __pragma(warning(pop)) - -// Suppress the following MSVC GSL warnings: -// - C26439, gsl::f.6 : special function 'function' can be declared 'noexcept' -// - C26440, gsl::f.6 : function 'function' can be declared 'noexcept' -// - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions; -// use brace initialization, gsl::narrow_cast or gsl::narrow -// - C26473: gsl::t.1 : don't cast between pointer types where the source type and the target type are the same -// - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead -// - C26490: gsl::t.1 : don't use reinterpret_cast - -span_DISABLE_MSVC_WARNINGS(26439 26440 26472 26473 26481 26490) - -#else -#define span_RESTORE_WARNINGS() /*empty*/ -#endif - -// Presence of language and library features: - -#ifdef _HAS_CPP0X -#define span_HAS_CPP0X _HAS_CPP0X -#else -#define span_HAS_CPP0X 0 -#endif - -#define span_CPP11_80 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1400) -#define span_CPP11_90 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1500) -#define span_CPP11_100 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1600) -#define span_CPP11_110 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1700) -#define span_CPP11_120 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1800) -#define span_CPP11_140 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1900) - -#define span_CPP14_000 (span_CPP14_OR_GREATER) -#define span_CPP14_120 (span_CPP14_OR_GREATER || span_COMPILER_MSVC_VER >= 1800) -#define span_CPP14_140 (span_CPP14_OR_GREATER || span_COMPILER_MSVC_VER >= 1900) - -#define span_CPP17_000 (span_CPP17_OR_GREATER) - -// Presence of C++11 language features: - -#define span_HAVE_ALIAS_TEMPLATE span_CPP11_140 -#define span_HAVE_AUTO span_CPP11_100 -#define span_HAVE_CONSTEXPR_11 span_CPP11_140 -#define span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG span_CPP11_120 -#define span_HAVE_EXPLICIT_CONVERSION span_CPP11_140 -#define span_HAVE_INITIALIZER_LIST span_CPP11_120 -#define span_HAVE_IS_DEFAULT span_CPP11_140 -#define span_HAVE_IS_DELETE span_CPP11_140 -#define span_HAVE_NOEXCEPT span_CPP11_140 -#define span_HAVE_NULLPTR span_CPP11_100 -#define span_HAVE_STATIC_ASSERT span_CPP11_100 - -// Presence of C++14 language features: - -#define span_HAVE_CONSTEXPR_14 span_CPP14_000 - -// Presence of C++17 language features: - -#define span_HAVE_DEPRECATED span_CPP17_000 -#define span_HAVE_NODISCARD span_CPP17_000 -#define span_HAVE_NORETURN span_CPP17_000 - -// MSVC: template parameter deduction guides since Visual Studio 2017 v15.7 - -#if defined(__cpp_deduction_guides) -#define span_HAVE_DEDUCTION_GUIDES 1 -#else -#define span_HAVE_DEDUCTION_GUIDES (span_CPP17_OR_GREATER && !span_BETWEEN(span_COMPILER_MSVC_VER, 1, 1913)) -#endif - -// Presence of C++ library features: - -#define span_HAVE_ADDRESSOF span_CPP17_000 -#define span_HAVE_ARRAY span_CPP11_110 -#define span_HAVE_BYTE span_CPP17_000 -#define span_HAVE_CONDITIONAL span_CPP11_120 -#define span_HAVE_CONTAINER_DATA_METHOD (span_CPP11_140 || (span_COMPILER_MSVC_VER >= 1500 && span_HAS_CPP0X)) -#define span_HAVE_DATA span_CPP17_000 -#define span_HAVE_LONGLONG span_CPP11_80 -#define span_HAVE_REMOVE_CONST span_CPP11_110 -#define span_HAVE_SNPRINTF span_CPP11_140 -#define span_HAVE_STRUCT_BINDING span_CPP11_120 -#define span_HAVE_TYPE_TRAITS span_CPP11_90 - -// Presence of byte-lite: - -#ifdef NONSTD_BYTE_LITE_HPP -#define span_HAVE_NONSTD_BYTE 1 -#else -#define span_HAVE_NONSTD_BYTE 0 -#endif - -// C++ feature usage: - -#if span_HAVE_ADDRESSOF -#define span_ADDRESSOF(x) std::addressof(x) -#else -#define span_ADDRESSOF(x) (&x) -#endif - -#if span_HAVE_CONSTEXPR_11 -#define span_constexpr constexpr -#else -#define span_constexpr /*span_constexpr*/ -#endif - -#if span_HAVE_CONSTEXPR_14 -#define span_constexpr14 constexpr -#else -#define span_constexpr14 /*span_constexpr*/ -#endif - -#if span_HAVE_EXPLICIT_CONVERSION -#define span_explicit explicit -#else -#define span_explicit /*explicit*/ -#endif - -#if span_HAVE_IS_DELETE -#define span_is_delete = delete -#else -#define span_is_delete -#endif - -#if span_HAVE_IS_DELETE -#define span_is_delete_access public -#else -#define span_is_delete_access private -#endif - -#if span_HAVE_NOEXCEPT && !span_CONFIG_CONTRACT_VIOLATION_THROWS_V -#define span_noexcept noexcept -#else -#define span_noexcept /*noexcept*/ -#endif - -#if span_HAVE_NULLPTR -#define span_nullptr nullptr -#else -#define span_nullptr NULL -#endif - -#if span_HAVE_DEPRECATED -#define span_deprecated(msg) [[deprecated(msg)]] -#else -#define span_deprecated(msg) /*[[deprecated]]*/ -#endif - -#if span_HAVE_NODISCARD -#define span_nodiscard [[nodiscard]] -#else -#define span_nodiscard /*[[nodiscard]]*/ -#endif - -#if span_HAVE_NORETURN -#define span_noreturn [[noreturn]] -#else -#define span_noreturn /*[[noreturn]]*/ -#endif - -// Other features: - -#define span_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG -#define span_HAVE_ITERATOR_CTOR span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG - -// Additional includes: - -#if span_HAVE(ADDRESSOF) -#include -#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include -#if span_HAVE(ARRAY) #include -#endif - -#if span_HAVE(BYTE) +#include +#include +#include +#include #include -#endif - -#if span_HAVE(DATA) -#include // for std::data(), std::size() -#endif - -#if span_HAVE(TYPE_TRAITS) -#include -#endif - -#if !span_HAVE(CONSTRAINED_SPAN_CONTAINER_CTOR) -#include -#endif - -#if span_FEATURE(MEMBER_AT) > 1 -#include -#endif -#if !span_CONFIG(NO_EXCEPTIONS) -#include -#endif - -// Contract violation - -#define span_ELIDE_CONTRACT_EXPECTS (0 == (span_CONFIG_CONTRACT_LEVEL_MASK & 0x01)) -#define span_ELIDE_CONTRACT_ENSURES (0 == (span_CONFIG_CONTRACT_LEVEL_MASK & 0x10)) - -#if span_ELIDE_CONTRACT_EXPECTS -#define span_constexpr_exp span_constexpr -#define span_EXPECTS(cond) /* Expect elided */ -#else -#define span_constexpr_exp span_constexpr14 -#define span_EXPECTS(cond) span_CONTRACT_CHECK("Precondition", cond) -#endif - -#if span_ELIDE_CONTRACT_ENSURES -#define span_constexpr_ens span_constexpr -#define span_ENSURES(cond) /* Ensures elided */ -#else -#define span_constexpr_ens span_constexpr14 -#define span_ENSURES(cond) span_CONTRACT_CHECK("Postcondition", cond) -#endif - -#define span_CONTRACT_CHECK(type, cond) \ - cond ? static_cast(0) \ - : nonstd::span_lite::detail::report_contract_violation( \ - span_LOCATION(__FILE__, __LINE__) ": " type " violation.") - -#ifdef __GNUG__ -#define span_LOCATION(file, line) file ":" span_STRINGIFY(line) -#else -#define span_LOCATION(file, line) file "(" span_STRINGIFY(line) ")" -#endif - -// Method enabling - -#if span_HAVE(DEFAULT_FUNCTION_TEMPLATE_ARG) - -#define span_REQUIRES_0(VA) template ::type = 0> - -#if span_BETWEEN(span_COMPILER_MSVC_VERSION, 1, 140) -// VS 2013 and earlier seem to have trouble with SFINAE for default non-type arguments -#define span_REQUIRES_T(VA) , typename = typename std::enable_if<(VA), nonstd::span_lite::detail::enabler>::type -#else -#define span_REQUIRES_T(VA) , typename std::enable_if<(VA), int>::type = 0 -#endif - -#define span_REQUIRES_R(R, VA) typename std::enable_if<(VA), R>::type +namespace ztd { + ZTD_IDK_INLINE_ABI_NAMESPACE_OPEN_I_ -#define span_REQUIRES_A(VA) , typename std::enable_if<(VA), void*>::type = nullptr + namespace __span_detail { + inline constexpr ::std::size_t __dynamic_extent = static_cast<::std::size_t>(-1LL); -#else - -#define span_REQUIRES_0(VA) /*empty*/ -#define span_REQUIRES_T(VA) /*empty*/ -#define span_REQUIRES_R(R, VA) R -#define span_REQUIRES_A(VA) /*empty*/ - -#endif - -namespace nonstd { namespace span_lite { - - // [views.constants], constants - - typedef span_CONFIG_EXTENT_TYPE extent_t; - typedef span_CONFIG_SIZE_TYPE size_t; - - span_constexpr const extent_t dynamic_extent = static_cast(-1); - - template + template class span; - // Tag to select span constructor taking a container (prevent ms-gsl warning C26426): - - struct with_container_t { - span_constexpr with_container_t() span_noexcept { - } - }; - const span_constexpr with_container_t with_container; - - // C++11 emulation: - - namespace std11 { - -#if span_HAVE(REMOVE_CONST) - - using std::remove_const; - using std::remove_cv; - using std::remove_volatile; - -#else - - template - struct remove_const { - typedef T type; - }; - template - struct remove_const { - typedef T type; - }; - - template - struct remove_volatile { - typedef T type; - }; - template - struct remove_volatile { - typedef T type; - }; - - template - struct remove_cv { - typedef typename std11::remove_volatile::type>::type type; - }; - -#endif // span_HAVE( REMOVE_CONST ) - -#if span_HAVE(TYPE_TRAITS) - - using std::false_type; - using std::integral_constant; - using std::is_same; - using std::is_signed; - using std::remove_reference; - using std::true_type; - -#else - - template - struct integral_constant { - enum { value = v }; - }; - typedef integral_constant true_type; - typedef integral_constant false_type; - - template - struct is_same : false_type { }; - template - struct is_same : true_type { }; - - template - struct is_signed : false_type { }; - template <> - struct is_signed : true_type { }; - template <> - struct is_signed : true_type { }; - template <> - struct is_signed : true_type { }; - -#endif - - } // namespace std11 - - // C++17 emulation: + template + class __is_span : public ::std::false_type { }; - namespace std17 { + template + class __is_span<::ztd::__span_detail::span<_Ty, _N>> : public ::std::true_type { }; - template - struct bool_constant : std11::integral_constant { }; + template + inline constexpr bool __is_span_v = ::ztd::__span_detail::__is_span<_Ty>::value; -#if span_CPP11_120 - - template - using void_t = void; - -#endif - -#if span_HAVE(DATA) - - using std::data; - using std::size; - -#elif span_HAVE(CONSTRAINED_SPAN_CONTAINER_CTOR) - - template - inline span_constexpr auto size(const T (&)[N]) span_noexcept->size_t { - return N; - } - - template - inline span_constexpr auto size(C const& cont) -> decltype(cont.size()) { - return cont.size(); - } - - template - inline span_constexpr auto data(T (&arr)[N]) span_noexcept->T* { - return &arr[0]; - } - - template - inline span_constexpr auto data(C& cont) -> decltype(cont.data()) { - return cont.data(); - } - - template - inline span_constexpr auto data(C const& cont) -> decltype(cont.data()) { - return cont.data(); - } - - template - inline span_constexpr auto data(std::initializer_list il) span_noexcept->E const* { - return il.begin(); - } - -#endif // span_HAVE( DATA ) - -#if span_HAVE(BYTE) - using std::byte; -#elif span_HAVE(NONSTD_BYTE) - using nonstd::byte; -#endif - - } // namespace std17 - - // C++20 emulation: - - namespace std20 { - -#if span_HAVE(DEDUCTION_GUIDES) - template - using iter_reference_t = decltype(*std::declval()); -#endif - - } // namespace std20 - - // Implementation details: - - namespace detail { - - /*enum*/ struct enabler { }; - - template - constexpr bool is_positive(T x) { - return std11::is_signed::value ? x >= 0 : true; + template <::std::size_t _Extent> + class __span_size { + public: + constexpr __span_size() noexcept = default; + constexpr __span_size(::std::size_t __size) noexcept { + ZTD_CONSTEXPR_ASSERT(__size <= _Extent); } -#if span_HAVE(TYPE_TRAITS) - - template - struct is_span_oracle : std::false_type { }; - - template - struct is_span_oracle> : std::true_type { }; - - template - struct is_span : is_span_oracle::type> { }; - - template - struct is_std_array_oracle : std::false_type { }; - -#if span_HAVE(ARRAY) - - template - struct is_std_array_oracle> : std::true_type { }; - -#endif - - template - struct is_std_array : is_std_array_oracle::type> { }; - - template - struct is_array : std::false_type { }; - - template - struct is_array : std::true_type { }; - - template - struct is_array : std::true_type { }; - -#if span_CPP11_140 && !span_BETWEEN(span_COMPILER_GNUC_VERSION, 1, 500) - - template - struct has_size_and_data : std::false_type { }; - - template - struct has_size_and_data())), decltype(std17::data(std::declval()))>> - : std::true_type { }; - - template - struct is_compatible_element : std::false_type { }; - - template - struct is_compatible_element()))>> - : std::is_convertible< - typename std::remove_pointer()))>::type (*)[], E (*)[]> { }; - - template - struct is_container : std17::bool_constant::value && !is_array::value - && !is_std_array::value && has_size_and_data::value> { }; - - template - struct is_compatible_container - : std17::bool_constant::value && is_compatible_element::value> { }; - -#else // span_CPP11_140 - - template ::value && !is_array::value && !is_std_array::value - && (std::is_convertible< - typename std::remove_pointer()))>::type (*)[], - E (*)[]>::value) - // && has_size_and_data< C >::value - )), - class = decltype(std17::size(std::declval())), class = decltype(std17::data(std::declval()))> - struct is_compatible_container : std::true_type { }; - -#endif // span_CPP11_140 - -#endif // span_HAVE( TYPE_TRAITS ) - -#if !span_CONFIG(NO_EXCEPTIONS) -#if span_FEATURE(MEMBER_AT) > 1 - - // format index and size: - -#if defined(__clang__) -#pragma clang diagnostic ignored "-Wlong-long" -#elif defined __GNUC__ -#pragma GCC diagnostic ignored "-Wformat=ll" -#pragma GCC diagnostic ignored "-Wlong-long" -#endif - - inline void throw_out_of_range(size_t idx, size_t size) { - const char fmt[] = "span::at(): index '%lli' is out of range [0..%lli)"; - char buffer[2 * 20 + sizeof fmt]; - sprintf(buffer, fmt, static_cast(idx), static_cast(size)); - - throw std::out_of_range(buffer); + constexpr ::std::size_t size() const noexcept { + return _Extent; } + }; -#else // MEMBER_AT - - inline void throw_out_of_range(size_t /*idx*/, size_t /*size*/) { - throw std::out_of_range("span::at(): index outside span"); + template <> + class __span_size<__dynamic_extent> { + public: + constexpr __span_size() noexcept : _M_size(0) { } -#endif // MEMBER_AT -#endif // NO_EXCEPTIONS - -#if span_CONFIG(CONTRACT_VIOLATION_THROWS_V) - - struct contract_violation : std::logic_error { - explicit contract_violation(char const* const message) : std::logic_error(message) { - } - }; - - inline void report_contract_violation(char const* msg) { - throw contract_violation(msg); + constexpr __span_size(::std::size_t __size) noexcept : _M_size(__size) { } -#else // span_CONFIG( CONTRACT_VIOLATION_THROWS_V ) - - span_noreturn inline void report_contract_violation(char const* /*msg*/) span_noexcept { - std::terminate(); + constexpr ::std::size_t size() const noexcept { + return this->_M_size; } -#endif // span_CONFIG( CONTRACT_VIOLATION_THROWS_V ) - - } // namespace detail - - // Prevent signed-unsigned mismatch: - -#define span_sizeof(T) static_cast(sizeof(T)) + std::size_t _M_size; + }; - template - inline span_constexpr size_t to_size(T size) { - return static_cast(size); - } + template + class span : public __span_size<_Extent> { + private: + using __base_span_size = __span_size<_Extent>; - // - // [views.span] - A view over a contiguous, single-dimension sequence of objects - // - template - class span { public: - // constants and types - - typedef T element_type; - typedef typename std11::remove_cv::type value_type; - - typedef T& reference; - typedef T* pointer; - typedef T const* const_pointer; - typedef T const& const_reference; - - typedef size_t size_type; - typedef extent_t extent_type; + using pointer = _Ty*; + using element_type = _Ty; + using value_type = ::std::remove_const_t; + using iterator = _Ty*; + using reference = ::std::add_lvalue_reference_t<_Ty>; + using const_reference = reference; + using const_iterator = iterator; + using reverse_iterator = ::std::reverse_iterator; + using const_reverse_iterator = ::std::reverse_iterator; + using difference_type = ::std::ptrdiff_t; + using size_type = ::std::size_t; + using iterator_tag = ::ztd::contiguous_iterator_tag; + using iterator_concept = ::ztd::contiguous_iterator_tag; + inline static constexpr size_type extent = _Extent; + + template <::std::size_t _Ex0 = extent, + ::std::enable_if_t<(_Ex0 == 0) || (_Ex0 == ::ztd::__span_detail::__dynamic_extent)>* = nullptr> + constexpr span() noexcept : __base_span_size(), _M_data() { + } + constexpr span(const span&) noexcept = default; + constexpr span(span&&) noexcept = default; + + + constexpr span(::std::nullptr_t, size_type __count) noexcept + : __base_span_size(__count), _M_data(nullptr) { + } - typedef pointer iterator; - typedef const_pointer const_iterator; - - typedef std::ptrdiff_t difference_type; - - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - - // static constexpr extent_type extent = Extent; - enum { extent = Extent }; - - // 26.7.3.2 Constructors, copy, and assignment [span.cons] - - span_REQUIRES_0((Extent == 0) || (Extent == dynamic_extent)) span_constexpr span() span_noexcept - : data_(span_nullptr), - size_(0) { - // span_EXPECTS( data() == span_nullptr ); - // span_EXPECTS( size() == 0 ); + template // cf + && ::ztd::is_non_derived_compatible_pointer_v< // cf + ::std::remove_reference_t<::ztd::ranges::iterator_reference_t<_It>>, // cf + element_type // cf + > // cf + >* = nullptr> + ZTD_EXPLICIT(extent != ::ztd::__span_detail::__dynamic_extent) + constexpr span(_It __first, size_type __count) noexcept + : __base_span_size(__count), _M_data(::ztd::to_address(__first)) { } -#if span_HAVE(ITERATOR_CTOR) - // Didn't yet succeed in combining the next two constructors: - - span_constexpr_exp span(std::nullptr_t, size_type count) : data_(span_nullptr), size_(count) { - span_EXPECTS(data_ == span_nullptr && count == 0); + template <::std::size_t _N, + ::std::enable_if_t<(extent == _N) || (extent == ::ztd::__span_detail::__dynamic_extent)>* = nullptr> + constexpr span(::ztd::type_identity_t (&__arr)[_N]) noexcept + : __base_span_size(_N), _M_data(__arr) { } - template ()), reference>::value))> - span_constexpr_exp span(It first, size_type count) : data_(to_address(first)), size_(count) { - span_EXPECTS((data_ == span_nullptr && count == 0) - || (data_ != span_nullptr && detail::is_positive(count))); + template + && ((extent == _N) || (extent == ::ztd::__span_detail::__dynamic_extent))>* = nullptr> + constexpr span(::std::array<_Elem, _N>& __arr) noexcept : __base_span_size(_N), _M_data(__arr.data()) { } -#else - span_constexpr_exp span(pointer ptr, size_type count) : data_(ptr), size_(count) { - span_EXPECTS( - (ptr == span_nullptr && count == 0) || (ptr != span_nullptr && detail::is_positive(count))); - } -#endif -#if span_HAVE(ITERATOR_CTOR) - template ()), reference>::value - && !std::is_convertible::value))> - span_constexpr_exp span(It first, End last) span_noexcept : data_(to_address(first)), - size_(to_size(last - first)) { - span_EXPECTS(last - first >= 0); + template + && ((extent == _N) || (extent == ::ztd::__span_detail::__dynamic_extent))>* = nullptr> + constexpr span(const ::std::array<_Elem, _N>& __arr) noexcept + : __base_span_size(_N), _M_data(__arr.data()) { } -#else - span_constexpr_exp span(pointer first, pointer last) : data_(first), size_(to_size(last - first)) { - span_EXPECTS(last - first >= 0); - } -#endif - template (N)) - && std::is_convertible::value))> - span_constexpr span(element_type (&arr)[N]) span_noexcept : data_(span_ADDRESSOF(arr[0])), size_(N) { + template >* = nullptr> + constexpr span(::std::initializer_list<_Elem> __il) noexcept + : __base_span_size(__il.size()), _M_data(__il.begin()) { } -#if span_HAVE(ARRAY) - - template (N)) - && std::is_convertible::value))> - span_constexpr span(std::array& arr) span_noexcept : data_(arr.data()), - size_(to_size(arr.size())) { + template // cf + && !::std::is_same_v> // cf + >* = nullptr> + constexpr span(const ::ztd::__span_detail::span<_Ty0, _Ex0>& __source) noexcept + : __base_span_size(__source.size()), _M_data(__source.data()) { } - template (N)) - && std::is_convertible::value)) -#endif - > - span_constexpr span(std::array const& arr) span_noexcept : data_(arr.data()), - size_(to_size(arr.size())) { + template > // cf + && !::ztd::is_initializer_list_v<::ztd::remove_cvref_t<_Range>> // cf + && !::ztd::__span_detail::__is_span_v<::ztd::remove_cvref_t<_Range>> // cf + && ::ztd::ranges::is_range_v<_Range> // cf + && ::ztd::ranges::is_range_contiguous_range_v<_Range> // cf + && ::ztd::ranges::is_sized_range_v<_Range> // cf + && ::ztd::is_non_derived_compatible_pointer_v< // cf + ::std::remove_reference_t<::ztd::ranges::range_reference_t<_Range>>, // cf + element_type> // cf + && (::std::is_lvalue_reference_v<_Range> // cf + ? (::std::is_const_v<::std::remove_reference_t<_Range>> // cf + ? (::std::is_const_v) + : true) + : (true)) // cf + >* = nullptr> + ZTD_EXPLICIT(extent != ::ztd::__span_detail::__dynamic_extent) + constexpr span(_Range&& __range) noexcept + : __base_span_size(::ztd::ranges::size(__range)), _M_data(::ztd::ranges::data(__range)) { } -#endif // span_HAVE( ARRAY ) - -#if span_HAVE(CONSTRAINED_SPAN_CONTAINER_CTOR) - template ::type>::type, - element_type>::value) // cf - && (std::is_lvalue_reference::value // cf - ? (std::is_const>::value // cf - ? (std::is_const::value) - : true) - : (true)))> - span_constexpr span(Container&& cont) span_noexcept : data_(std17::data(cont)), - size_(to_size(std17::size(cont))) { + template // cf + && ::ztd::ranges::is_iterator_random_access_iterator_v<_ItLast> // cf + && ::ztd::ranges::is_iterator_contiguous_iterator_v<_ItFirst> // cf + && !::std::is_convertible_v<_ItLast, size_type> // cf + >* = nullptr> + ZTD_EXPLICIT(extent != ::ztd::__span_detail::__dynamic_extent) + constexpr span(_ItFirst __first, _ItLast __last) noexcept + : __base_span_size(static_cast(::std::distance(__first, __last))) + , _M_data(::ztd::to_address(__first)) { } -#endif // span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) + constexpr span& operator=(const span&) noexcept = default; + constexpr span& operator=(span&&) noexcept = default; -#if span_FEATURE(WITH_CONTAINER) - - template - span_constexpr span(with_container_t, Container& cont) - : data_(cont.size() == 0 ? span_nullptr : span_ADDRESSOF(cont[0])), size_(to_size(cont.size())) { + constexpr bool empty() const noexcept { + return this->size() == 0; } - template - span_constexpr span(with_container_t, Container const& cont) - : data_(cont.size() == 0 ? span_nullptr : const_cast(span_ADDRESSOF(cont[0]))) - , size_(to_size(cont.size())) { + constexpr pointer data() const noexcept { + return this->_M_data; } -#endif - -#if span_HAVE(IS_DEFAULT) - span_constexpr span(span const& other) span_noexcept = default; - - ~span() span_noexcept = default; - span_constexpr14 span& operator=(span const& other) span_noexcept = default; -#else - span_constexpr span(span const& other) span_noexcept : data_(other.data_), size_(other.size_) { + constexpr iterator begin() const noexcept { + return this->_M_data; } - ~span() span_noexcept { + constexpr iterator end() const noexcept { + return this->_M_data + this->size(); } - span_constexpr14 span& operator=(span const& other) span_noexcept { - data_ = other.data_; - size_ = other.size_; - - return *this; + constexpr const_iterator cbegin() const noexcept { + return this->_M_data; } -#endif - template ::value))> - span_constexpr_exp span(span const& other) span_noexcept - : data_(static_cast(other.data())), - size_(other.size()) { - span_EXPECTS(OtherExtent == dynamic_extent || other.size() == to_size(OtherExtent)); + constexpr const_iterator cend() const noexcept { + return this->_M_data + this->size(); } - // 26.7.3.3 Subviews [span.sub] - - template - span_constexpr_exp span first() const { - span_EXPECTS(detail::is_positive(Count) && Count <= size()); - - return span(data(), Count); + constexpr iterator rbegin() const noexcept { + return reverse_iterator(this->end()); } - template - span_constexpr_exp span last() const { - span_EXPECTS(detail::is_positive(Count) && Count <= size()); - - return span(data() + (size() - Count), Count); + constexpr reverse_iterator rend() const noexcept { + return reverse_iterator(this->begin()); } -#if span_HAVE(DEFAULT_FUNCTION_TEMPLATE_ARG) - template -#else - template -#endif - span_constexpr_exp span subspan() const { - span_EXPECTS((detail::is_positive(Offset) && Offset <= size()) - && (Count == dynamic_extent || (detail::is_positive(Count) && Count + Offset <= size()))); - - return span(data() + Offset, - Count != dynamic_extent ? Count - : (Extent != dynamic_extent ? Extent - Offset : size() - Offset)); + constexpr const_reverse_iterator crbegin() const noexcept { + return const_reverse_iterator(this->cend()); } - span_constexpr_exp span first(size_type count) const { - span_EXPECTS(detail::is_positive(count) && count <= size()); - - return span(data(), count); + constexpr const_reverse_iterator crend() const noexcept { + return const_reverse_iterator(this->cbegin()); } - span_constexpr_exp span last(size_type count) const { - span_EXPECTS(detail::is_positive(count) && count <= size()); - - return span(data() + (size() - count), count); + constexpr reference front() noexcept { + ZTD_CONSTEXPR_ASSERT(this->size() > 0); + return this->_M_data[0]; } - span_constexpr_exp span subspan( - size_type offset, size_type count = static_cast(dynamic_extent)) const { - span_EXPECTS(((detail::is_positive(offset) && offset <= size())) - && (count == static_cast(dynamic_extent) - || (detail::is_positive(count) && offset + count <= size()))); - - return span( - data() + offset, count == static_cast(dynamic_extent) ? size() - offset : count); + constexpr const_reference front() const noexcept { + ZTD_CONSTEXPR_ASSERT(this->size() > 0); + return this->_M_data[0]; } - // 26.7.3.4 Observers [span.obs] - - span_constexpr size_type size() const span_noexcept { - return size_; + constexpr reference back() noexcept { + ZTD_CONSTEXPR_ASSERT(this->size() > 0); + return this->_M_data[this->size() - 1]; } - span_constexpr std::ptrdiff_t ssize() const span_noexcept { - return static_cast(size_); + constexpr const_reference back() const noexcept { + ZTD_CONSTEXPR_ASSERT(this->size() > 0); + return this->_M_data[this->size() - 1]; } - span_constexpr size_type size_bytes() const span_noexcept { - return size() * to_size(sizeof(element_type)); + constexpr reference operator[](size_type __index) const noexcept { + ZTD_CONSTEXPR_ASSERT(__index < this->size()); + return this->_M_data[__index]; } - span_nodiscard span_constexpr bool empty() const span_noexcept { - return size() == 0; + constexpr size_type size() const noexcept { + return this->__base_span_size::size(); } - // 26.7.3.5 Element access [span.elem] - - span_constexpr_exp reference operator[](size_type idx) const { - span_EXPECTS(detail::is_positive(idx) && idx < size()); - - return *(data() + idx); + constexpr size_type size_bytes() const noexcept { + return (this->size() * sizeof(element_type)) / sizeof(unsigned char); } -#if span_FEATURE(MEMBER_CALL_OPERATOR) - span_deprecated("replace operator() with operator[]") - - span_constexpr_exp reference - operator()(size_type idx) const { - span_EXPECTS(detail::is_positive(idx) && idx < size()); - - return *(data() + idx); - } -#endif - -#if span_FEATURE(MEMBER_AT) - span_constexpr14 reference at(size_type idx) const { -#if span_CONFIG(NO_EXCEPTIONS) - return this->operator[](idx); -#else - if (!detail::is_positive(idx) || size() <= idx) { - detail::throw_out_of_range(idx, size()); + template <::std::size_t _Count> + constexpr span first() const noexcept { + if constexpr (extent == ::ztd::__span_detail::__dynamic_extent) { + ZTD_CONSTEXPR_ASSERT(_Count <= this->size()); } - return *(data() + idx); -#endif - } -#endif - - span_constexpr pointer data() const span_noexcept { - return data_; - } - -#if span_FEATURE(MEMBER_BACK_FRONT) - - span_constexpr_exp reference front() const span_noexcept { - span_EXPECTS(!empty()); - - return *data(); - } - - span_constexpr_exp reference back() const span_noexcept { - span_EXPECTS(!empty()); - - return *(data() + size() - 1); - } - -#endif - - // xx.x.x.x Modifiers [span.modifiers] - -#if span_FEATURE(MEMBER_SWAP) - - span_constexpr14 void swap(span& other) span_noexcept { - using std::swap; - swap(data_, other.data_); - swap(size_, other.size_); - } -#endif - - // 26.7.3.6 Iterator support [span.iterators] - - span_constexpr iterator begin() const span_noexcept { -#if span_CPP11_OR_GREATER - return { data() }; -#else - return iterator(data()); -#endif - } - - span_constexpr iterator end() const span_noexcept { -#if span_CPP11_OR_GREATER - return { data() + size() }; -#else - return iterator(data() + size()); -#endif - } - - span_constexpr const_iterator cbegin() const span_noexcept { -#if span_CPP11_OR_GREATER - return { data() }; -#else - return const_iterator(data()); -#endif - } - - span_constexpr const_iterator cend() const span_noexcept { -#if span_CPP11_OR_GREATER - return { data() + size() }; -#else - return const_iterator(data() + size()); -#endif - } - - span_constexpr reverse_iterator rbegin() const span_noexcept { - return reverse_iterator(end()); - } - - span_constexpr reverse_iterator rend() const span_noexcept { - return reverse_iterator(begin()); + else { + static_assert(extent == ::ztd::__span_detail::__dynamic_extent || (_Count <= extent)); + } + return span(this->data(), _Count); } - span_constexpr const_reverse_iterator crbegin() const span_noexcept { - return const_reverse_iterator(cend()); + constexpr span first( + size_type __count) const noexcept { + ZTD_CONSTEXPR_ASSERT(__count <= this->size()); + return span(this->data(), __count); } - span_constexpr const_reverse_iterator crend() const span_noexcept { - return const_reverse_iterator(cbegin()); + template <::std::size_t _Count> + constexpr span last() const { + if constexpr (extent == ::ztd::__span_detail::__dynamic_extent) { + ZTD_CONSTEXPR_ASSERT(_Count <= this->size()); + } + else { + static_assert(extent == ::ztd::__span_detail::__dynamic_extent || (_Count <= extent)); + } + // NOTE: should we be `static_assert`ing the inability to use __dynamic_extent as a _Count? + // or is it just so improbable it doesn't matter? + return span(this->_M_data + (this->size() - _Count), _Count); } - private: - // Note: C++20 has std::pointer_traits::to_address( it ); - -#if span_HAVE(ITERATOR_CTOR) - static inline span_constexpr pointer to_address(std::nullptr_t) span_noexcept { - return nullptr; + constexpr span last(size_type __count) const { + ZTD_CONSTEXPR_ASSERT(__count <= this->size()); + return span( + this->_M_data + (this->size() - __count), __count); } - template - static inline span_constexpr U* to_address(U* p) span_noexcept { - return p; + template <::std::size_t _Offset, std::size_t _Count = ::ztd::__span_detail::__dynamic_extent> + constexpr auto subspan() const { + static_assert(extent == ::ztd::__span_detail::__dynamic_extent || (extent <= _Offset)); + if constexpr (_Count == ::ztd::__span_detail::__dynamic_extent) { + return span( + this->_M_data + _Offset, this->size() - _Offset); + } + else { + static_assert(extent == ::ztd::__span_detail::__dynamic_extent + || ((extent <= _Offset) && ((extent - _Offset) >= _Count))); + return span(this->_M_data + _Offset, _Count); + } } - template ::value))> - static inline span_constexpr pointer to_address(Ptr const& it) span_noexcept { - return to_address(it.operator->()); + constexpr span subspan( + size_type __offset, size_type __count = ::ztd::__span_detail::__dynamic_extent) const { + if (__count == ::ztd::__span_detail::__dynamic_extent) { + return span( + this->_M_data + __offset, this->size() - __offset); + } + else { + ZTD_CONSTEXPR_ASSERT(this->size() <= __offset); + ZTD_CONSTEXPR_ASSERT((this->size() - __offset) >= __count); + return span( + this->_M_data + __offset, __count); + } } -#endif // span_HAVE( ITERATOR_CTOR ) private: - pointer data_; - size_type size_; + _Ty* _M_data; }; - // class template argument deduction guides: + template + span(_It, _ItOrSize) -> span<::std::remove_reference_t<::ztd::ranges::iterator_reference_t<_It>>>; -#if span_HAVE(DEDUCTION_GUIDES) + template + span(_Ty (&)[_Ex]) -> span<_Ty, _Ex>; - template - span(T (&)[N]) -> span(N)>; + template + span(std::array<_Ty, _Ex>&) -> span<_Ty, _Ex>; - template - span(std::array&) -> span(N)>; + template + span(const std::array<_Ty, _Ex>&) -> span; - template - span(std::array const&) -> span(N)>; + template + span(_Range&&) -> span<::std::remove_reference_t<::ztd::ranges::range_reference_t<_Range>>>; -#if span_HAVE(CONSTRAINED_SPAN_CONTAINER_CTOR) - - template - span(Container&) -> span; - - template - span(Container const&) -> span; - -#endif - - // iterator: constraints: It satisfies contiguous_­iterator. - - template - span(It, EndOrSize) -> span>::type>; - -#endif // span_HAVE( DEDUCTION_GUIDES ) - - // 26.7.3.7 Comparison operators [span.comparison] - -#if span_FEATURE(COMPARISON) -#if span_FEATURE(SAME) - - template - inline span_constexpr bool same(span const& l, span const& r) span_noexcept { - return std11::is_same::value && l.size() == r.size() - && static_cast(l.data()) == r.data(); + template + inline constexpr bool operator==(span<_Ty1, _Ex1> const& __left, span<_Ty2, _Ex2> const& __right) { + return (__left.size() == __right.size() && std::equal(__left.begin(), __left.end(), __right.begin())); } -#endif - - template - inline span_constexpr bool operator==(span const& l, span const& r) { - return -#if span_FEATURE(SAME) - same(l, r) || -#endif - (l.size() == r.size() && std::equal(l.begin(), l.end(), r.begin())); + template + inline constexpr bool operator==( + ::ztd::type_identity_t> const& __left, span<_Ty2, _Ex2> const& __right) { + return (__left.size() == __right.size() && std::equal(__left.begin(), __left.end(), __right.begin())); } - template - inline span_constexpr bool operator==(::ztd::type_identity_t> const& l, span const& r) { - return -#if span_FEATURE(SAME) - same(l, r) || -#endif - (l.size() == r.size() && std::equal(l.begin(), l.end(), r.begin())); + template + inline constexpr bool operator==( + span<_Ty1, _Ex1> const& __left, ::ztd::type_identity_t> const& __right) { + return (__left.size() == __right.size() && std::equal(__left.begin(), __left.end(), __right.begin())); } - template - inline span_constexpr bool operator==(span const& l, ::ztd::type_identity_t> const& r) { - return -#if span_FEATURE(SAME) - same(l, r) || -#endif - (l.size() == r.size() && std::equal(l.begin(), l.end(), r.begin())); + template + inline constexpr bool operator<(::ztd::__span_detail::span<_Ty1, _Ex1> const& __left, + ::ztd::__span_detail::span<_Ty2, _Ex2> const& __right) noexcept { + return ::std::lexicographical_compare(__left.cbegin(), __left.cend(), __right.cbegin(), __right.cend()); } - - template - inline span_constexpr bool operator<(span const& l, span const& r) span_noexcept { - return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); + template + inline constexpr bool operator<(::ztd::type_identity_t<::ztd::__span_detail::span<_Ty1, _Ex1>> const& __left, + ::ztd::__span_detail::span<_Ty2, _Ex2> const& __right) noexcept { + return ::std::lexicographical_compare(__left.cbegin(), __left.cend(), __right.cbegin(), __right.cend()); } - template - inline span_constexpr bool operator<( - ::ztd::type_identity_t> const& l, span const& r) span_noexcept { - return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); - } - - template - inline span_constexpr bool operator<( - span const& l, ::ztd::type_identity_t> const& r) span_noexcept { - return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); + template + inline constexpr bool operator<(::ztd::__span_detail::span<_Ty1, _Ex1> const& __left, + ::ztd::type_identity_t<::ztd::__span_detail::span<_Ty2, _Ex2>> const& __right) noexcept { + return ::std::lexicographical_compare(__left.cbegin(), __left.cend(), __right.cbegin(), __right.cend()); } - template - inline span_constexpr bool operator!=(span const& l, span const& r) span_noexcept { - return !(l == r); + template + inline constexpr bool operator!=(::ztd::__span_detail::span<_Ty1, _Ex1> const& __left, + ::ztd::__span_detail::span<_Ty2, _Ex2> const& __right) noexcept { + return !(__left == __right); } - template - inline span_constexpr bool operator!=( - ::ztd::type_identity_t> const& l, span const& r) span_noexcept { - return !(l == r); + template + inline constexpr bool operator!=(::ztd::type_identity_t<::ztd::__span_detail::span<_Ty1, _Ex1>> const& __left, + ::ztd::__span_detail::span<_Ty2, _Ex2> const& __right) noexcept { + return !(__left == __right); } - template - inline span_constexpr bool operator!=( - span const& l, ::ztd::type_identity_t> const& r) span_noexcept { - return !(l == r); + template + inline constexpr bool operator!=(::ztd::__span_detail::span<_Ty1, _Ex1> const& __left, + ::ztd::type_identity_t<::ztd::__span_detail::span<_Ty2, _Ex2>> const& __right) noexcept { + return !(__left == __right); } - template - inline span_constexpr bool operator<=(span const& l, span const& r) span_noexcept { - return !(r < l); + template + inline constexpr bool operator<=(::ztd::__span_detail::span<_Ty1, _Ex1> const& __left, + ::ztd::__span_detail::span<_Ty2, _Ex2> const& __right) noexcept { + return !(__right < __left); } - template - inline span_constexpr bool operator<=( - ::ztd::type_identity_t> const& l, span const& r) span_noexcept { - return !(r < l); + template + inline constexpr bool operator<=(::ztd::type_identity_t<::ztd::__span_detail::span<_Ty1, _Ex1>> const& __left, + ::ztd::__span_detail::span<_Ty2, _Ex2> const& __right) noexcept { + return !(__right < __left); } - template - inline span_constexpr bool operator<=( - span const& l, ::ztd::type_identity_t> const& r) span_noexcept { - return !(r < l); + template + inline constexpr bool operator<=(::ztd::__span_detail::span<_Ty1, _Ex1> const& __left, + ::ztd::type_identity_t<::ztd::__span_detail::span<_Ty2, _Ex2>> const& __right) noexcept { + return !(__right < __left); } - template - inline span_constexpr bool operator>(span const& l, span const& r) span_noexcept { - return (r < l); + template + inline constexpr bool operator>(::ztd::__span_detail::span<_Ty1, _Ex1> const& __left, + ::ztd::__span_detail::span<_Ty2, _Ex2> const& __right) noexcept { + return (__right < __left); } - template - inline span_constexpr bool operator>( - ::ztd::type_identity_t> const& l, span const& r) span_noexcept { - return (r < l); + template + inline constexpr bool operator>(::ztd::type_identity_t<::ztd::__span_detail::span<_Ty1, _Ex1>> const& __left, + ::ztd::__span_detail::span<_Ty2, _Ex2> const& __right) noexcept { + return (__right < __left); } - template - inline span_constexpr bool operator>( - span const& l, ::ztd::type_identity_t> const& r) span_noexcept { - return (r < l); + template + inline constexpr bool operator>(::ztd::__span_detail::span<_Ty1, _Ex1> const& __left, + ::ztd::type_identity_t<::ztd::__span_detail::span<_Ty2, _Ex2>> const& __right) noexcept { + return (__right < __left); } - template - inline span_constexpr bool operator>=(span const& l, span const& r) span_noexcept { - return !(l < r); + template + inline constexpr bool operator>=(::ztd::__span_detail::span<_Ty1, _Ex1> const& __left, + ::ztd::__span_detail::span<_Ty2, _Ex2> const& __right) noexcept { + return !(__left < __right); } - template - inline span_constexpr bool operator>=( - ::ztd::type_identity_t> const& l, span const& r) span_noexcept { - return !(l < r); + template + inline constexpr bool operator>=(::ztd::type_identity_t<::ztd::__span_detail::span<_Ty1, _Ex1>> const& __left, + ::ztd::__span_detail::span<_Ty2, _Ex2> const& __right) noexcept { + return !(__left < __right); } - template - inline span_constexpr bool operator>=( - span const& l, ::ztd::type_identity_t> const& r) span_noexcept { - return !(l < r); + template + inline constexpr bool operator>=(::ztd::__span_detail::span<_Ty1, _Ex1> const& __left, + ::ztd::type_identity_t<::ztd::__span_detail::span<_Ty2, _Ex2>> const& __right) noexcept { + return !(__left < __right); } -#endif // span_FEATURE( COMPARISON ) - - // 26.7.2.6 views of object representation [span.objectrep] - -#if span_HAVE(BYTE) || span_HAVE(NONSTD_BYTE) - - // Avoid MSVC 14.1 (1910), VS 2017: warning C4307: '*': integral constant overflow: - - template - struct BytesExtent { -#if span_CPP11_OR_GREATER - enum ET : extent_t { value = span_sizeof(T) * Extent }; -#else - enum ET { value = span_sizeof(T) * Extent }; -#endif - }; - - template - struct BytesExtent { -#if span_CPP11_OR_GREATER - enum ET : extent_t { value = dynamic_extent }; -#else - enum ET { value = dynamic_extent }; -#endif - }; - - template - inline span_constexpr span::value> as_bytes( - span spn) span_noexcept { -#if 0 - return { reinterpret_cast< std17::byte const * >( spn.data() ), spn.size_bytes() }; -#else - return span::value>( - reinterpret_cast(spn.data()), spn.size_bytes()); // NOLINT -#endif + template + constexpr span as_bytes(::ztd::__span_detail::span<_Ty, _Ex> __source) noexcept { + return ::ztd::__span_detail::span( + reinterpret_cast<::std::byte const*>(__source.data()), __source.size_bytes()); } - template - inline span_constexpr span::value> as_writable_bytes( - span spn) span_noexcept { -#if 0 - return { reinterpret_cast< std17::byte * >( spn.data() ), spn.size_bytes() }; -#else - return span::value>( - reinterpret_cast(spn.data()), spn.size_bytes()); // NOLINT -#endif + template + constexpr span as_writable_bytes(::ztd::__span_detail::span<_Ty, _Ex> __source) noexcept { + return ::ztd::__span_detail::span( + reinterpret_cast<::std::byte*>(__source.data()), __source.size_bytes()); } -#endif // span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE ) + } // namespace __span_detail - // 27.8 Container and view access [iterator.container] + ZTD_IDK_INLINE_ABI_NAMESPACE_CLOSE_I_ +} // namespace ztd - template - span_constexpr std::size_t size(span const& spn) { - return static_cast(spn.size()); - } - - template - span_constexpr std::ptrdiff_t ssize(span const& spn) { - return static_cast(spn.size()); - } - -}} // namespace nonstd::span_lite - -// make available in nonstd: - -namespace nonstd { - - using span_lite::dynamic_extent; - - using span_lite::span; - - using span_lite::with_container; - -#if span_FEATURE(COMPARISON) -#if span_FEATURE(SAME) - using span_lite::same; -#endif - - using span_lite::operator==; - using span_lite::operator!=; - using span_lite::operator<; - using span_lite::operator<=; - using span_lite::operator>; - using span_lite::operator>=; -#endif - -#if span_HAVE(BYTE) - using span_lite::as_bytes; - using span_lite::as_writable_bytes; -#endif - - using span_lite::size; - using span_lite::ssize; - -} // namespace nonstd - -#endif // span_USES_STD_SPAN - -// make_span() [span-lite extension]: - -#if span_FEATURE(MAKE_SPAN) || span_FEATURE(NON_MEMBER_FIRST_LAST_SUB_SPAN) \ - || span_FEATURE(NON_MEMBER_FIRST_LAST_SUB_CONTAINER) - -#if span_USES_STD_SPAN -#define span_constexpr constexpr -#define span_noexcept noexcept -#define span_nullptr nullptr -#ifndef span_CONFIG_EXTENT_TYPE -#define span_CONFIG_EXTENT_TYPE std::size_t -#endif -using extent_t = span_CONFIG_EXTENT_TYPE; -#endif // span_USES_STD_SPAN - -namespace nonstd { namespace span_lite { - - template - inline span_constexpr span make_span(T* ptr, size_t count) span_noexcept { - return span(ptr, count); - } - - template - inline span_constexpr span make_span(T* first, T* last) span_noexcept { - return span(first, last); - } - - template - inline span_constexpr span(N)> make_span(T (&arr)[N]) span_noexcept { - return span(N)>(&arr[0], N); - } - -#if span_USES_STD_SPAN || span_HAVE(ARRAY) - - template - inline span_constexpr span(N)> make_span(std::array& arr) span_noexcept { - return span(N)>(arr); - } - - template - inline span_constexpr span(N)> make_span( - std::array const& arr) span_noexcept { - return span(N)>(arr); - } - -#endif // span_HAVE( ARRAY ) - -#if span_USES_STD_SPAN - - template ()))> - inline span_constexpr auto make_span( - Container& cont) span_noexcept->span::type> { - return span::type>(cont); - } - - template ()))> - inline span_constexpr auto make_span( - Container const& cont) span_noexcept->span::type> { - return span::type>(cont); - } - -#elif span_HAVE(CONSTRAINED_SPAN_CONTAINER_CTOR) && span_HAVE(AUTO) - - template ()))> - inline span_constexpr auto make_span( - Container& cont) span_noexcept->span::type> { - return span::type>(cont); - } - - template ()))> - inline span_constexpr auto make_span( - Container const& cont) span_noexcept->span::type> { - return span::type>(cont); - } - -#else - - template - inline span_constexpr span make_span(span spn) span_noexcept { - return spn; - } - - template - inline span_constexpr span make_span(std::vector& cont) span_noexcept { - return span(with_container, cont); - } - - template - inline span_constexpr span make_span(std::vector const& cont) span_noexcept { - return span(with_container, cont); - } - -#endif // span_USES_STD_SPAN || ( ... ) - -#if !span_USES_STD_SPAN && span_FEATURE(WITH_CONTAINER) - - template - inline span_constexpr span make_span( - with_container_t, Container& cont) span_noexcept { - return span(with_container, cont); - } - - template - inline span_constexpr span make_span( - with_container_t, Container const& cont) span_noexcept { - return span(with_container, cont); - } - -#endif // ! span_USES_STD_SPAN && span_FEATURE( WITH_CONTAINER ) - - // extensions: non-member views: - // this feature implies the presence of make_span() - -#if span_FEATURE(NON_MEMBER_FIRST_LAST_SUB_SPAN) - - template - span_constexpr span first(span spn) { - return spn.template first(); - } - - template - span_constexpr span first(span spn, size_t count) { - return spn.first(count); - } - - template - span_constexpr span last(span spn) { - return spn.template last(); - } - - template - span_constexpr span last(span spn, size_t count) { - return spn.last(count); - } - - template - span_constexpr span subspan(span spn) { - return spn.template subspan(); - } - - template - span_constexpr span subspan(span spn, size_t offset, extent_t count = dynamic_extent) { - return spn.subspan(offset, count); - } - -#endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) - -#if span_FEATURE(NON_MEMBER_FIRST_LAST_SUB_CONTAINER) && span_CPP11_120 - - template - span_constexpr auto first(T& t) -> decltype(make_span(t).template first()) { - return make_span(t).template first(); - } - - template - span_constexpr auto first(T& t, size_t count) -> decltype(make_span(t).first(count)) { - return make_span(t).first(count); - } - - template - span_constexpr auto last(T& t) -> decltype(make_span(t).template last()) { - return make_span(t).template last(); - } - - template - span_constexpr auto last(T& t, extent_t count) -> decltype(make_span(t).last(count)) { - return make_span(t).last(count); - } - - template - span_constexpr auto subspan(T& t) -> decltype(make_span(t).template subspan()) { - return make_span(t).template subspan(); - } - - template - span_constexpr auto subspan(T& t, size_t offset, extent_t count = dynamic_extent) - -> decltype(make_span(t).subspan(offset, count)) { - return make_span(t).subspan(offset, count); - } - -#endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) - -}} // namespace nonstd::span_lite - -// make available in nonstd: - -namespace nonstd { - using span_lite::make_span; - -#if span_FEATURE(NON_MEMBER_FIRST_LAST_SUB_SPAN) \ - || (span_FEATURE(NON_MEMBER_FIRST_LAST_SUB_CONTAINER) && span_CPP11_120) - - using span_lite::first; - using span_lite::last; - using span_lite::subspan; - -#endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_[SPAN|CONTAINER] ) - -} // namespace nonstd - -#endif // #if span_FEATURE_TO_STD( MAKE_SPAN ) - -#if span_CPP11_OR_GREATER && span_FEATURE(BYTE_SPAN) && (span_HAVE(BYTE) || span_HAVE(NONSTD_BYTE)) - -namespace nonstd { namespace span_lite { - - template - inline span_constexpr auto byte_span(T& t) span_noexcept->span { - return span(reinterpret_cast(&t), span_sizeof(T)); - } - - template - inline span_constexpr auto byte_span(T const& t) span_noexcept->span { - return span(reinterpret_cast(&t), span_sizeof(T)); - } - -}} // namespace nonstd::span_lite - -// make available in nonstd: - -namespace nonstd { - using span_lite::byte_span; -} // namespace nonstd - -#endif // span_FEATURE( BYTE_SPAN ) - -#if span_HAVE(STRUCT_BINDING) - -#if span_CPP14_OR_GREATER -#include -#elif span_CPP11_OR_GREATER -#include -namespace std { - template - using tuple_element_t = typename tuple_element::type; -} -#else -namespace std { - template - class tuple_size; /*undefined*/ - - template - class tuple_element; /* undefined */ -} // namespace std -#endif // span_CPP14_OR_GREATER - -namespace std { - - // 26.7.X Tuple interface - - // std::tuple_size<>: - - template - class tuple_size> - : public integral_constant(Extent)> { }; - - // std::tuple_size<>: Leave undefined for dynamic extent: - - template - class tuple_size>; - - // std::tuple_element<>: - - template - class tuple_element> { - public: -#if span_HAVE(STATIC_ASSERT) - static_assert(Extent != nonstd::dynamic_extent && I < Extent, - "tuple_element: dynamic extent or index out of range"); #endif - using type = ElementType; - }; - - // std::get<>(), 2 variants: - - template - span_constexpr ElementType& get(nonstd::span& spn) span_noexcept { -#if span_HAVE(STATIC_ASSERT) - static_assert( - Extent != nonstd::dynamic_extent && I < Extent, "get<>(span): dynamic extent or index out of range"); -#endif - return spn[I]; - } - - template - span_constexpr ElementType const& get(nonstd::span const& spn) span_noexcept { -#if span_HAVE(STATIC_ASSERT) - static_assert( - Extent != nonstd::dynamic_extent && I < Extent, "get<>(span): dynamic extent or index out of range"); -#endif - return spn[I]; - } - -} // end namespace std - -#endif // span_HAVE( STRUCT_BINDING ) - -#if !span_USES_STD_SPAN -span_RESTORE_WARNINGS() -#endif // span_USES_STD_SPAN - -#endif // NONSTD_SPAN_HPP_INCLUDED diff --git a/include/ztd/idk/explicit.hpp b/include/ztd/idk/explicit.hpp new file mode 100644 index 0000000..3087326 --- /dev/null +++ b/include/ztd/idk/explicit.hpp @@ -0,0 +1,61 @@ +// ============================================================================= +// +// ztd.idk +// Copyright © 2022-2023 JeanHeyd "ThePhD" Meneide and Shepherd's Oasis, LLC +// Contact: opensource@soasis.org +// +// Commercial License Usage +// Licensees holding valid commercial ztd.idk licenses may use this file in +// accordance with the commercial license agreement provided with the +// Software or, alternatively, in accordance with the terms contained in +// a written agreement between you and Shepherd's Oasis, LLC. +// For licensing terms and conditions see your agreement. For +// further information contact opensource@soasis.org. +// +// Apache License Version 2 Usage +// Alternatively, this file may be used under the terms of Apache License +// Version 2.0 (the "License") for non-commercial use; you may not use this +// file except in compliance with the License. You may obtain a copy of the +// License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ============================================================================ // + +#pragma once + +#ifndef ZTD_IDK_EXPLICIT_HPP +#define ZTD_IDK_EXPLICIT_HPP + +#include + +////// +/// @addtogroup ztd_idk_explicit Explicit Utilities +/// +/// @{ +////// + +#if ZTD_IS_ON(ZTD_STD_EXPLICIT) +////// +/// @brief Either compiles to explicit(bool) or simply compiles to nothing depending on if the feature is available. +/// +/// @param[in] ... An expression which computes a boolean value. +#define ZTD_EXPLICIT(...) explicit(__VA_ARGS__) +#else +////// +/// @brief Either compiles to explicit(bool) or simply compiles to nothing depending on if the feature is available. +/// +/// @param[in] ... An expression which computes a boolean value. +#define ZTD_EXPLICIT(...) /* nothing */ +#endif +////// +/// @} +////// + +#endif diff --git a/include/ztd/idk/is_array.hpp b/include/ztd/idk/is_array.hpp new file mode 100644 index 0000000..16e4824 --- /dev/null +++ b/include/ztd/idk/is_array.hpp @@ -0,0 +1,70 @@ +// ============================================================================= +// +// ztd.idk +// Copyright © 2022-2023 JeanHeyd "ThePhD" Meneide and Shepherd's Oasis, LLC +// Contact: opensource@soasis.org +// +// Commercial License Usage +// Licensees holding valid commercial ztd.idk licenses may use this file in +// accordance with the commercial license agreement provided with the +// Software or, alternatively, in accordance with the terms contained in +// a written agreement between you and Shepherd's Oasis, LLC. +// For licensing terms and conditions see your agreement. For +// further information contact opensource@soasis.org. +// +// Apache License Version 2 Usage +// Alternatively, this file may be used under the terms of Apache License +// Version 2.0 (the "License") for non-commercial use; you may not use this +// file except in compliance with the License. You may obtain a copy of the +// License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ============================================================================ // + +#pragma once + +#ifndef ZTD_IDK_IS_ARRAY_HPP +#define ZTD_IDK_IS_ARRAY_HPP + +#include + +#include + +#include + +namespace ztd { + ZTD_IDK_INLINE_ABI_NAMESPACE_OPEN_I_ + + ////// + /// @brief Whether or not the given type is exactly a `std::array`. + template + class is_std_array : public ::std::false_type { }; + + ////// + /// @brief Whether or not the given type is exactly a `std::array`. + template + class is_std_array<::std::array<_Ty, _N>> : public ::std::true_type { }; + + ////// + /// @brief Whether or not the given type is exactly a `std::array`. + template + inline constexpr bool is_std_array_v = is_std_array<_Ty>::value; + + ////// + /// @brief Whether or not the given type is exactly a `std::array`. + template + inline constexpr bool is_std_or_c_array_v = ::std::is_array_v<_Ty> || is_std_array_v<_Ty>; + + ZTD_IDK_INLINE_ABI_NAMESPACE_CLOSE_I_ +} // namespace ztd + +#include + +#endif diff --git a/include/ztd/idk/span.hpp b/include/ztd/idk/span.hpp index 0046e95..5ae751d 100644 --- a/include/ztd/idk/span.hpp +++ b/include/ztd/idk/span.hpp @@ -109,10 +109,6 @@ namespace std { #else -// Use home-grown span from Martin Moene -#define span_FEATURE_MAKE_SPAN 1 -#define span_FEATURE_COMPARISON 1 -#define span_FEATURE_WITH_INITIALIZER_LIST_P2447 1 #include #include @@ -122,19 +118,18 @@ namespace ztd { ////// /// @brief dynamic extent copycat - /// - inline constexpr decltype(::nonstd::span_lite::dynamic_extent) dynamic_extent = ::nonstd::span_lite::dynamic_extent; - - using ::nonstd::span_lite::as_bytes; - using ::nonstd::span_lite::as_writable_bytes; - using ::nonstd::span_lite::make_span; - using ::nonstd::span_lite::span; - using ::nonstd::span_lite::operator==; - using ::nonstd::span_lite::operator!=; - using ::nonstd::span_lite::operator<; - using ::nonstd::span_lite::operator<=; - using ::nonstd::span_lite::operator>; - using ::nonstd::span_lite::operator>=; + // + inline constexpr auto dynamic_extent = ::ztd::__span_detail::__dynamic_extent; + + using ::ztd::__span_detail::as_bytes; + using ::ztd::__span_detail::as_writable_bytes; + using ::ztd::__span_detail::span; + using ::ztd::__span_detail::operator==; + using ::ztd::__span_detail::operator!=; + using ::ztd::__span_detail::operator<; + using ::ztd::__span_detail::operator<=; + using ::ztd::__span_detail::operator>; + using ::ztd::__span_detail::operator>=; ZTD_IDK_INLINE_ABI_NAMESPACE_CLOSE_I_ } // namespace ztd diff --git a/include/ztd/idk/type_traits.hpp b/include/ztd/idk/type_traits.hpp index 364414f..311caa0 100644 --- a/include/ztd/idk/type_traits.hpp +++ b/include/ztd/idk/type_traits.hpp @@ -38,6 +38,7 @@ #include #include +#include #if ZTD_IS_ON(ZTD_STD_SPACESHIP_COMPARE) && ZTD_IS_ON(ZTD_STD_LIBRARY_SPACESHIP_COMPARE) #include #endif @@ -156,6 +157,25 @@ namespace ztd { template inline constexpr bool is_code_unit_v = is_code_unit<_Type>::value; + + + ////// + /// @brief Check whether a given type is an `initializer_list`. + template + class is_initializer_list : ::std::false_type { }; + + ////// + /// @brief Check whether a given type is an `initializer_list`. + template + class is_initializer_list> : ::std::true_type { }; + + ////// + /// @brief An @c _v alias for ztd::is_initializer_list. + template + inline constexpr bool is_initializer_list_v = is_code_unit<_Type>::value; + + + ////// /// @brief Checks if the given type is one of the types that is usable in the standard with the @c std::char_traits /// traits type that's used for @c std::string_view , @c std::string and others. diff --git a/include/ztd/ranges/adl.hpp b/include/ztd/ranges/adl.hpp index c3ceb3f..8366b8c 100644 --- a/include/ztd/ranges/adl.hpp +++ b/include/ztd/ranges/adl.hpp @@ -41,6 +41,7 @@ #include #include #include +#include #include @@ -241,6 +242,22 @@ namespace ztd { namespace ranges { using type = typename ::std::iterator_traits<::std::remove_reference_t<_It>>::pointer; }; + template + struct __iterator_element_type_or_fallback { + private: + using _Reference = iterator_reference_t<::std::remove_reference_t<_It>>; + + public: + using type = ::std::conditional_t<::std::is_reference_v<_Reference>, + ::std::remove_reference_t<_Reference>, void>; + }; + + template + struct __iterator_element_type_or_fallback<_It, + ::std::void_t::element_type>> { + using type = typename ::std::remove_reference_t<_It>::element_type; + }; + template using __iterator_concept_or_fallback_t = typename __iterator_concept_or_category_or_fallback<::std::remove_reference_t<_It>>::type; @@ -258,6 +275,9 @@ namespace ztd { namespace ranges { template using iterator_value_type_t = typename __rng_detail::__iterator_value_type_interception<_It>::type; + template + using iterator_element_type_t = typename __rng_detail::__iterator_element_type_or_fallback<_It>::type; + template using iterator_size_type_t = ::std::make_signed_t>>; @@ -311,6 +331,30 @@ namespace ztd { namespace ranges { template using __detect_crend = decltype(crend(::std::declval<_Range>())); + template + using __detect_member_begin = decltype(::std::declval<_Range>().begin()); + + template + using __detect_member_rbegin = decltype(::std::declval<_Range>().rbegin()); + + template + using __detect_member_cbegin = decltype(::std::declval<_Range>().cbegin()); + + template + using __detect_member_crbegin = decltype(::std::declval<_Range>().crbegin()); + + template + using __detect_member_end = decltype(::std::declval<_Range>().end()); + + template + using __detect_member_rend = decltype(::std::declval<_Range>().rend()); + + template + using __detect_member_cend = decltype(::std::declval<_Range>().cend()); + + template + using __detect_member_crend = decltype(::std::declval<_Range>().crend()); + template constexpr bool __begin_noexcept() noexcept { if constexpr (::std::is_array_v>) { @@ -319,9 +363,28 @@ namespace ztd { namespace ranges { else if constexpr (is_detected_v<__detect_begin, _Range>) { return noexcept(begin(::std::declval<_Range>())); } - else { + else if constexpr (is_detected_v<__detect_member_begin, _Range>) { return noexcept(::std::declval<_Range>().begin()); } + else { + return true; + } + } + + template + constexpr bool __begin_sfinae() noexcept { + if constexpr (::std::is_array_v>) { + return true; + } + else if constexpr (is_detected_v<__detect_begin, _Range>) { + return true; + } + else if constexpr (is_detected_v<__detect_member_begin, _Range>) { + return true; + } + else { + return false; + } } template @@ -332,11 +395,29 @@ namespace ztd { namespace ranges { else if constexpr (is_detected_v<__detect_cbegin, _Range>) { return noexcept(cbegin(::std::declval<_Range>())); } - else { + else if constexpr (is_detected_v<__detect_member_cbegin, _Range>) { return noexcept(::std::declval<_Range>().cbegin()); } + else { + return true; + } } + template + constexpr bool __cbegin_sfinae() noexcept { + if constexpr (::std::is_array_v>) { + return true; + } + else if constexpr (is_detected_v<__detect_cbegin, _Range>) { + return true; + } + else if constexpr (is_detected_v<__detect_member_cbegin, _Range>) { + return true; + } + else { + return false; + } + } template constexpr bool __rbegin_noexcept() noexcept { @@ -346,11 +427,29 @@ namespace ztd { namespace ranges { else if constexpr (is_detected_v<__detect_rbegin, _Range>) { return noexcept(rbegin(::std::declval<_Range>())); } - else { + else if constexpr (is_detected_v<__detect_member_rbegin, _Range>) { return noexcept(::std::declval<_Range>().rbegin()); } + else { + return true; + } } + template + constexpr bool __rbegin_sfinae() noexcept { + if constexpr (::std::is_array_v>) { + return true; + } + else if constexpr (is_detected_v<__detect_rbegin, _Range>) { + return true; + } + else if constexpr (is_detected_v<__detect_member_rbegin, _Range>) { + return true; + } + else { + return false; + } + } template constexpr bool __crbegin_noexcept() noexcept { @@ -360,9 +459,28 @@ namespace ztd { namespace ranges { else if constexpr (is_detected_v<__detect_crbegin, _Range>) { return noexcept(crbegin(::std::declval<_Range>())); } - else { + else if constexpr (is_detected_v<__detect_member_crbegin, _Range>) { return noexcept(::std::declval<_Range>().crbegin()); } + else { + return true; + } + } + + template + constexpr bool __crbegin_sfinae() noexcept { + if constexpr (::std::is_array_v>) { + return true; + } + else if constexpr (is_detected_v<__detect_crbegin, _Range>) { + return true; + } + else if constexpr (is_detected_v<__detect_member_crbegin, _Range>) { + return true; + } + else { + return false; + } } template @@ -373,9 +491,28 @@ namespace ztd { namespace ranges { else if constexpr (is_detected_v<__detect_end, _Range>) { return noexcept(end(::std::declval<_Range>())); } - else { + else if constexpr (is_detected_v<__detect_member_end, _Range>) { return noexcept(::std::declval<_Range>().end()); } + else { + return true; + } + } + + template + constexpr bool __end_sfinae() noexcept { + if constexpr (::std::is_array_v>) { + return true; + } + else if constexpr (is_detected_v<__detect_end, _Range>) { + return true; + } + else if constexpr (is_detected_v<__detect_member_end, _Range>) { + return true; + } + else { + return false; + } } template @@ -386,11 +523,29 @@ namespace ztd { namespace ranges { else if constexpr (is_detected_v<__detect_cend, _Range>) { return noexcept(cend(::std::declval<_Range>())); } - else { + else if constexpr (is_detected_v<__detect_member_cend, _Range>) { return noexcept(::std::declval<_Range>().cend()); } + else { + return true; + } } + template + constexpr bool __cend_sfinae() noexcept { + if constexpr (::std::is_array_v>) { + return true; + } + else if constexpr (is_detected_v<__detect_cend, _Range>) { + return true; + } + else if constexpr (is_detected_v<__detect_member_cend, _Range>) { + return true; + } + else { + return false; + } + } template constexpr bool __rend_noexcept() noexcept { @@ -400,11 +555,29 @@ namespace ztd { namespace ranges { else if constexpr (is_detected_v<__detect_rend, _Range>) { return noexcept(rend(::std::declval<_Range>())); } - else { + else if constexpr (is_detected_v<__detect_member_rend, _Range>) { return noexcept(::std::declval<_Range>().rend()); } + else { + return true; + } } + template + constexpr bool __rend_sfinae() noexcept { + if constexpr (::std::is_array_v>) { + return true; + } + else if constexpr (is_detected_v<__detect_rend, _Range>) { + return true; + } + else if constexpr (is_detected_v<__detect_member_rend, _Range>) { + return true; + } + else { + return false; + } + } template constexpr bool __crend_noexcept() noexcept { @@ -414,9 +587,28 @@ namespace ztd { namespace ranges { else if constexpr (is_detected_v<__detect_crend, _Range>) { return noexcept(crend(::std::declval<_Range>())); } - else { + else if constexpr (is_detected_v<__detect_member_crend, _Range>) { return noexcept(::std::declval<_Range>().crend()); } + else { + return true; + } + } + + template + constexpr bool __crend_sfinae() noexcept { + if constexpr (::std::is_array_v>) { + return true; + } + else if constexpr (is_detected_v<__detect_crend, _Range>) { + return true; + } + else if constexpr (is_detected_v<__detect_member_crend, _Range>) { + return true; + } + else { + return false; + } } template @@ -446,9 +638,10 @@ namespace ztd { namespace ranges { class __begin_fn { public: - template + template ()>* = nullptr> constexpr decltype(auto) operator()(_Range&& __range) const noexcept(__begin_noexcept<_Range>()) { - if constexpr (::std::is_array_v>) { + using _URange = remove_cvref_t<_Range>; + if constexpr (::std::is_array_v<_URange>) { return (__range + 0); } else if constexpr (is_detected_v<__detect_begin, _Range>) { @@ -462,7 +655,7 @@ namespace ztd { namespace ranges { class __cbegin_fn { public: - template + template ()>* = nullptr> constexpr decltype(auto) operator()(_Range&& __range) const noexcept(__cbegin_noexcept<_Range>()) { if constexpr (::std::is_array_v>) { return (__range + 0); @@ -478,7 +671,7 @@ namespace ztd { namespace ranges { class __rbegin_fn { public: - template + template ()>* = nullptr> constexpr decltype(auto) operator()(_Range&& __range) const noexcept(__rbegin_noexcept<_Range>()) { if constexpr (::std::is_array_v>) { return ::std::make_reverse_iterator(__range + ::std::extent_v>); @@ -494,7 +687,8 @@ namespace ztd { namespace ranges { class __crbegin_fn { public: - template + template ()>* = nullptr> constexpr decltype(auto) operator()(_Range&& __range) const noexcept(__crbegin_noexcept<_Range>()) { if constexpr (::std::is_array_v>) { return ::std::make_reverse_iterator(__range + ::std::extent_v>); @@ -510,7 +704,8 @@ namespace ztd { namespace ranges { class __end_fn { public: - template + template ()>* = nullptr> constexpr decltype(auto) operator()(_Range&& __range) const noexcept(__end_noexcept<_Range>()) { if constexpr (::std::is_array_v>) { return (__range + ::std::extent_v>); @@ -526,7 +721,8 @@ namespace ztd { namespace ranges { class __cend_fn { public: - template + template ()>* = nullptr> constexpr decltype(auto) operator()(_Range&& __range) const noexcept(__cend_noexcept<_Range>()) { if constexpr (::std::is_array_v>) { return (__range + ::std::extent_v>); @@ -542,7 +738,8 @@ namespace ztd { namespace ranges { class __rend_fn { public: - template + template ()>* = nullptr> constexpr decltype(auto) operator()(_Range&& __range) const noexcept(__rend_noexcept<_Range>()) { if constexpr (::std::is_array_v>) { return ::std::make_reverse_iterator(__range + 0); @@ -558,7 +755,8 @@ namespace ztd { namespace ranges { class __crend_fn { public: - template + template ()>* = nullptr> constexpr decltype(auto) operator()(_Range&& __range) const noexcept(__crend_noexcept<_Range>()) { if constexpr (::std::is_array_v>) { return ::std::make_reverse_iterator(__range + 0); @@ -714,6 +912,9 @@ namespace ztd { namespace ranges { template using range_value_type_t = iterator_value_type_t>; + template + using range_element_type_t = iterator_element_type_t>; + template using range_reference_t = iterator_reference_t>; @@ -728,7 +929,12 @@ namespace ztd { namespace ranges { #endif template - using range_cv_value_type_t = ::std::remove_reference_t<::ztd::ranges::range_reference_t<_Range>>; + using range_const_iterator_t = ::ztd::remove_cvref_t>()))>; + + template + using range_const_sentinel_t = ::ztd::remove_cvref_t>()))>; template using iterator_category_t = diff --git a/include/ztd/ranges/range.hpp b/include/ztd/ranges/range.hpp index 68d346a..7584f75 100644 --- a/include/ztd/ranges/range.hpp +++ b/include/ztd/ranges/range.hpp @@ -53,13 +53,88 @@ namespace ztd { namespace ranges { ZTD_RANGES_INLINE_ABI_NAMESPACE_OPEN_I_ - template - using range_const_iterator_t - = decltype(::ztd::ranges::cbegin(::std::declval<::std::add_lvalue_reference_t<_Range>>())); + namespace __rng_detail { + template > + class __is_input_range : public ::std::false_type { }; - template - using range_const_sentinel_t - = decltype(::ztd::ranges::cend(::std::declval<::std::add_lvalue_reference_t<_Range>>())); + template + class __is_input_range<_Range, true> + : public ::std::integral_constant>> { }; + + template > + class __is_output_range : public ::std::false_type { }; + + template + class __is_output_range<_Range, true> + : public ::std::integral_constant>> { }; + + template > + class __is_bidirectional_range : public ::std::false_type { }; + + template + class __is_bidirectional_range<_Range, true> + : public ::std::integral_constant>> { }; + + template > + class __is_random_access_range : public ::std::false_type { }; + + template + class __is_random_access_range<_Range, true> + : public ::std::integral_constant>> { }; + + template > + class __is_contiguous_range : public ::std::false_type { }; + + template + class __is_contiguous_range<_Range, true> + : public ::std::integral_constant>> { }; + + template > + class __is_input_range_exactly : public ::std::false_type { }; + + template + class __is_input_range_exactly<_Range, true> + : public ::std::integral_constant>> { }; + + template > + class __is_output_range_exactly : public ::std::false_type { }; + + template + class __is_output_range_exactly<_Range, true> + : public ::std::integral_constant>> { }; + + template > + class __is_bidirectional_range_exactly : public ::std::false_type { }; + + template + class __is_bidirectional_range_exactly<_Range, true> + : public ::std::integral_constant>> { }; + + template > + class __is_random_access_range_exactly : public ::std::false_type { }; + + template + class __is_random_access_range_exactly<_Range, true> + : public ::std::integral_constant>> { }; + + template > + class __is_contiguous_range_exactly : public ::std::false_type { }; + + template + class __is_contiguous_range_exactly<_Range, true> + : public ::std::integral_constant>> { + }; + + template > + class __is_sized_range : public ::std::false_type { }; + + template + class __is_sized_range<_Range, true> + : public ::std::integral_constant, range_sentinel_t<_Range>>> { }; + } // namespace __rng_detail template using range_pointer_t = iterator_pointer_t>; @@ -74,40 +149,49 @@ namespace ztd { namespace ranges { inline constexpr bool is_range_iterator_concept_or_better_v = ::std::is_base_of_v<_Tag, range_iterator_concept_t<_Range>>; + template + inline constexpr bool is_range_input_range_v = __rng_detail::__is_input_range<_Range>::value; + + template + inline constexpr bool is_range_output_range_v = __rng_detail::__is_output_range<_Range>::value; + template inline constexpr bool is_range_input_or_output_range_v - = is_iterator_input_or_output_iterator_v>; + = is_range_input_range_v<_Range> || is_range_output_range_v<_Range>; + + template + inline constexpr bool is_range_bidirectional_range_v = __rng_detail::__is_bidirectional_range<_Range>::value; + + template + inline constexpr bool is_range_random_access_range_v = __rng_detail::__is_random_access_range<_Range>::value; template - inline constexpr bool is_range_bidirectional_range_v - = is_iterator_bidirectional_iterator_v>; + inline constexpr bool is_range_contiguous_range_v = __rng_detail::__is_contiguous_range<_Range>::value; template - inline constexpr bool is_range_random_access_range_v - = is_iterator_random_access_iterator_v>; + inline constexpr bool is_sized_range_v = __rng_detail::__is_sized_range<_Range>::value; template - inline constexpr bool is_range_contiguous_range_v = is_iterator_contiguous_iterator_v>; + inline constexpr bool is_range_input_range_exactly_v = __rng_detail::__is_input_range_exactly<_Range>::value; template - inline constexpr bool is_sized_range_v - = is_sized_sentinel_for_v, range_sentinel_t<_Range>>; + inline constexpr bool is_range_output_range_exactly_v = __rng_detail::__is_output_range_exactly<_Range>::value; template inline constexpr bool is_range_input_or_output_range_exactly_v - = is_iterator_input_or_output_iterator_exactly_v>; + = is_range_input_range_exactly_v<_Range> || is_range_output_range_exactly_v<_Range>; template inline constexpr bool is_range_bidirectional_range_exactly_v - = is_iterator_bidirectional_iterator_exactly_v>; + = __rng_detail::__is_bidirectional_range_exactly<_Range>::value; template inline constexpr bool is_range_random_access_range_exactly_v - = is_iterator_random_access_iterator_exactly_v>; + = __rng_detail::__is_random_access_range_exactly<_Range>::value; template inline constexpr bool is_range_contiguous_range_exactly_v - = is_iterator_contiguous_iterator_exactly_v>; + = __rng_detail::__is_contiguous_range_exactly<_Range>::value; ////// /// @brief A detection decltype for use with ztd::is_detected and similar. Checks if the given type has a .reserve diff --git a/include/ztd/ranges/reconstruct.hpp b/include/ztd/ranges/reconstruct.hpp index f0c220b..6ae130e 100644 --- a/include/ztd/ranges/reconstruct.hpp +++ b/include/ztd/ranges/reconstruct.hpp @@ -58,18 +58,17 @@ namespace ztd { namespace ranges { namespace __rng_detail { - template class __reconstruct_fn; - template + template class __cascading_reconstruct_fn; - template + template constexpr bool __is_tagless_iterator_reconstruct_noexcept() noexcept { if constexpr (((::std::is_class_v<_It> || ::std::is_enum_v<_It>) || (::std::is_class_v<_Sen> || ::std::is_enum_v<_Sen>)) - && is_tag_invocable_v<__reconstruct_fn<_Mutable>, _It, _Sen>) { - return is_nothrow_tag_invocable_v<__reconstruct_fn<_Mutable>, _It, _Sen>; + && is_tag_invocable_v<__reconstruct_fn, _It, _Sen>) { + return is_nothrow_tag_invocable_v<__reconstruct_fn, _It, _Sen>; } else { return ::std::is_nothrow_constructible_v, remove_cvref_t<_Sen>>, _It, @@ -77,45 +76,43 @@ namespace ztd { namespace ranges { } } - template + template constexpr bool __is_iterator_reconstruct_noexcept() noexcept { - return is_tag_invocable_v<__reconstruct_fn<_Mutable>, _InPlace, _It, _Sen> - ? is_nothrow_tag_invocable_v<__reconstruct_fn<_Mutable>, _InPlace, _It, _Sen> - : __is_tagless_iterator_reconstruct_noexcept<_Mutable, _It, _Sen>(); + return is_tag_invocable_v<__reconstruct_fn, _InPlace, _It, _Sen> + ? is_nothrow_tag_invocable_v<__reconstruct_fn, _InPlace, _It, _Sen> + : __is_tagless_iterator_reconstruct_noexcept<_It, _Sen>(); } - template + template constexpr bool __is_range_iterator_reconstruct_noexcept() noexcept { - return is_tag_invocable_v<__reconstruct_fn<_Mutable>, _InPlace, _Range, _It, _Sen> - ? is_nothrow_tag_invocable_v<__reconstruct_fn<_Mutable>, _InPlace, _Range, _It, _Sen> - : __is_iterator_reconstruct_noexcept<_Mutable, _InPlace, _It, _Sen>(); + return is_tag_invocable_v<__reconstruct_fn, _InPlace, _Range, _It, _Sen> + ? is_nothrow_tag_invocable_v<__reconstruct_fn, _InPlace, _Range, _It, _Sen> + : __is_iterator_reconstruct_noexcept<_InPlace, _It, _Sen>(); } - template + template constexpr bool __is_range_reconstruct_noexcept() noexcept { - return __is_range_iterator_reconstruct_noexcept<_Mutable, _InPlace, _Range, - ::std::conditional_t<_Mutable, range_iterator_t<_Range>, range_const_iterator_t<_Range>>, - ::std::conditional_t<_Mutable, range_sentinel_t<_Range>, range_const_sentinel_t<_Range>>>(); + return __is_range_iterator_reconstruct_noexcept<_InPlace, _Range, range_iterator_t<_Range>, + range_sentinel_t<_Range>>(); } - template + template constexpr bool __is_range_reconstruct_or_tagless_iterator_reconstruct_noexcept() noexcept { if constexpr (is_specialization_of_v, ::std::in_place_type_t>) { - return __is_range_reconstruct_noexcept<_Mutable, _InPlaceOrIt, _RangeOrSen>(); + return __is_range_reconstruct_noexcept<_InPlaceOrIt, _RangeOrSen>(); } else { - return __is_tagless_iterator_reconstruct_noexcept<_Mutable, _InPlaceOrIt, _RangeOrSen>(); + return __is_tagless_iterator_reconstruct_noexcept<_InPlaceOrIt, _RangeOrSen>(); } } - template - class __reconstruct_fn : public ::ztd::hijack::token<__reconstruct_fn<_Mutable>>, - public ::ztd_hijack_global_token<__reconstruct_fn<_Mutable>> { + class __reconstruct_fn : public ::ztd::hijack::token<__reconstruct_fn>, + public ::ztd_hijack_global_token<__reconstruct_fn> { public: template - constexpr auto operator()(::std::in_place_type_t<_InPlaceTag> __inplace, _It&& __iterator, - _Sen&& __sentinel) const noexcept(__is_iterator_reconstruct_noexcept<_Mutable, - ::std::in_place_type_t<_InPlaceTag>, _It, _Sen>()) { + constexpr auto operator()( + ::std::in_place_type_t<_InPlaceTag> __inplace, _It&& __iterator, _Sen&& __sentinel) const + noexcept(__is_iterator_reconstruct_noexcept<::std::in_place_type_t<_InPlaceTag>, _It, _Sen>()) { if constexpr (is_tag_invocable_v<__reconstruct_fn, ::std::in_place_type_t<_InPlaceTag>, ::ztd::remove_cvref_t<_It>, ::ztd::remove_cvref_t<_Sen>>) { return ::ztd::tag_invoke( @@ -128,9 +125,10 @@ namespace ztd { namespace ranges { } template - constexpr decltype(auto) operator()(::std::in_place_type_t<_InPlaceTag> __inplace, _Range&& __range, - _It&& __it, _Sen&& __sen) const noexcept(__is_range_iterator_reconstruct_noexcept<_Mutable, - ::std::in_place_type_t<_InPlaceTag>, _Range, _It, _Sen>()) { + constexpr decltype(auto) operator()( + ::std::in_place_type_t<_InPlaceTag> __inplace, _Range&& __range, _It&& __it, _Sen&& __sen) const + noexcept(__is_range_iterator_reconstruct_noexcept<::std::in_place_type_t<_InPlaceTag>, _Range, _It, + _Sen>()) { if constexpr (is_tag_invocable_v<__reconstruct_fn, ::std::in_place_type_t<_InPlaceTag>, _Range, _It, _Sen>) { return ::ztd::tag_invoke(*this, __inplace, ::std::forward<_Range>(__range), @@ -144,26 +142,17 @@ namespace ztd { namespace ranges { template constexpr decltype(auto) operator()( _InPlaceOrIt&& __inplace_or_iterator, _RangeOrSen&& __range_or_sentinel) const - noexcept(__is_range_reconstruct_or_tagless_iterator_reconstruct_noexcept<_Mutable, _InPlaceOrIt, - _RangeOrSen>()) { + noexcept( + __is_range_reconstruct_or_tagless_iterator_reconstruct_noexcept<_InPlaceOrIt, _RangeOrSen>()) { if constexpr (is_specialization_of_v, ::std::in_place_type_t>) { if constexpr (is_tag_invocable_v<__reconstruct_fn, _InPlaceOrIt, _RangeOrSen>) { return ::ztd::tag_invoke(*this, ::std::forward<_InPlaceOrIt>(__inplace_or_iterator), ::std::forward<_RangeOrSen>(__range_or_sentinel)); } else { - if constexpr (_Mutable) { - return (*this)(::std::forward<_InPlaceOrIt>(__inplace_or_iterator), - ::std::forward<_RangeOrSen>(__range_or_sentinel), - ::ztd::ranges::begin(__range_or_sentinel), - ::ztd::ranges::end(__range_or_sentinel)); - } - else { - return (*this)(::std::forward<_InPlaceOrIt>(__inplace_or_iterator), - ::std::forward<_RangeOrSen>(__range_or_sentinel), - ::ztd::ranges::cbegin(__range_or_sentinel), - ::ztd::ranges::cend(__range_or_sentinel)); - } + return (*this)(::std::forward<_InPlaceOrIt>(__inplace_or_iterator), + ::std::forward<_RangeOrSen>(__range_or_sentinel), + ::ztd::ranges::begin(__range_or_sentinel), ::ztd::ranges::end(__range_or_sentinel)); } } else if constexpr (((::std::is_class_v<_InPlaceOrIt> || ::std::is_enum_v<_InPlaceOrIt>) @@ -181,29 +170,22 @@ namespace ztd { namespace ranges { } }; - template + template static constexpr bool __is_reconstructible() noexcept { if constexpr (sizeof...(_Args) == 0) { if constexpr (is_specialization_of_v, ::std::in_place_type_t>) { - if constexpr (is_tag_invocable_v<__reconstruct_fn<_Mutable>, _InPlaceOrIt, _RangeOrSen>) { + if constexpr (is_tag_invocable_v<__reconstruct_fn, _InPlaceOrIt, _RangeOrSen>) { return true; } else { - if constexpr (_Mutable) { - return __is_reconstructible<_Mutable, _InPlaceOrIt, _RangeOrSen, - ::ztd::ranges::range_iterator_t<_RangeOrSen>, - ::ztd::ranges::range_sentinel_t<_RangeOrSen>>(); - } - else { - return __is_reconstructible<_Mutable, _InPlaceOrIt, _RangeOrSen, - ::ztd::ranges::range_const_iterator_t<_RangeOrSen>, - ::ztd::ranges::range_const_sentinel_t<_RangeOrSen>>(); - } + return __is_reconstructible<_InPlaceOrIt, _RangeOrSen, + ::ztd::ranges::range_iterator_t<_RangeOrSen>, + ::ztd::ranges::range_sentinel_t<_RangeOrSen>>(); } } else if constexpr (((::std::is_class_v<_InPlaceOrIt> || ::std::is_enum_v<_InPlaceOrIt>) || (::std::is_class_v<_RangeOrSen> || ::std::is_enum_v<_RangeOrSen>)) - && is_tag_invocable_v<__reconstruct_fn<_Mutable>, _InPlaceOrIt, _RangeOrSen>) { + && is_tag_invocable_v<__reconstruct_fn, _InPlaceOrIt, _RangeOrSen>) { return true; } else { @@ -211,47 +193,46 @@ namespace ztd { namespace ranges { } } else if constexpr (sizeof...(_Args) == 1) { - if constexpr (is_tag_invocable_v<__reconstruct_fn<_Mutable>, ::ztd::remove_cvref_t<_InPlaceOrIt>, - ::ztd::remove_cvref_t<_RangeOrSen>, ::ztd::remove_cvref_t<_Args>...>) { + if constexpr (is_tag_invocable_v<__reconstruct_fn, ::ztd::remove_cvref_t<_InPlaceOrIt>, _RangeOrSen, + _Args...>) { return true; } else { - return __is_reconstructible<_Mutable, _RangeOrSen, _Args...>(); + return __is_reconstructible<_RangeOrSen, _Args...>(); } } else if constexpr (sizeof...(_Args) == 2) { - if constexpr (is_tag_invocable_v<__reconstruct_fn<_Mutable>, _InPlaceOrIt, _RangeOrSen, _Args...>) { + if constexpr (is_tag_invocable_v<__reconstruct_fn, _InPlaceOrIt, _RangeOrSen, _Args...>) { return true; } else { - return __is_reconstructible<_Mutable, _InPlaceOrIt, _Args...>(); + return __is_reconstructible<_InPlaceOrIt, _Args...>(); } } else { - static_assert( - ::ztd::always_false_constant_v, "improper arguments to __is_reconstructible"); + static_assert(::ztd::always_false_v<_InPlaceOrIt>, "improper arguments to __is_reconstructible"); } } - template + template inline constexpr bool __is_reconstructible_noexcept() noexcept { if constexpr (sizeof...(_Args) == 0) { if constexpr (is_specialization_of_v, ::std::in_place_type_t>) { - return __is_range_reconstruct_noexcept<_Mutable, _InPlaceOrIt, _RangeOrSen>(); + return __is_range_reconstruct_noexcept<_InPlaceOrIt, _RangeOrSen>(); } else { - return __is_tagless_iterator_reconstruct_noexcept<_Mutable, _InPlaceOrIt, _RangeOrSen>(); + return __is_tagless_iterator_reconstruct_noexcept<_InPlaceOrIt, _RangeOrSen>(); } } else if constexpr (sizeof...(_Args) == 1) { - return __is_iterator_reconstruct_noexcept<_Mutable, _InPlaceOrIt, _RangeOrSen, _Args...>(); + return __is_iterator_reconstruct_noexcept<_InPlaceOrIt, _RangeOrSen, _Args...>(); } else if constexpr (sizeof...(_Args) == 2) { - return __is_range_iterator_reconstruct_noexcept<_Mutable, _InPlaceOrIt, _RangeOrSen, _Args...>(); + return __is_range_iterator_reconstruct_noexcept<_InPlaceOrIt, _RangeOrSen, _Args...>(); } else { - static_assert(::ztd::always_false_constant_v, - "improper arguments to __is_reconstructible_noexcept"); + static_assert( + ::ztd::always_false_v<_InPlaceOrIt>, "improper arguments to __is_reconstructible_noexcept"); } } } // namespace __rng_detail @@ -264,68 +245,55 @@ namespace ztd { namespace ranges { /// reconstruction for things outside of their control, without needing to place it in the global namespace or /// the immediate ztd::ranges namespace, where there are too many other types that could force asking more /// questions about what is in the list for ADL and drive up compile-times. - inline constexpr __rng_detail::__reconstruct_fn reconstruct = {}; + inline constexpr __rng_detail::__reconstruct_fn reconstruct = {}; } // namespace __fn namespace __rng_detail { - template + template static constexpr bool __is_cascading_reconstructible(::ztd::tag<_Type>) noexcept { - return __is_reconstructible<_Mutable, ::std::in_place_type_t<_Type>, _Args...>(); + return __is_reconstructible<::std::in_place_type_t<_Type>, _Args...>(); } - template + template static constexpr bool __is_cascading_reconstructible(::ztd::tag<_Type, _Types...>) noexcept { - if constexpr (__is_reconstructible<_Mutable, ::std::in_place_type_t<_Type>, _Args...>()) { + if constexpr (__is_reconstructible<::std::in_place_type_t<_Type>, _Args...>()) { return true; } else { - return __is_cascading_reconstructible<_Mutable, _Args...>(::ztd::tag<_Types...>()); + return __is_cascading_reconstructible<_Args...>(::ztd::tag<_Types...>()); } } - template + template inline constexpr bool __is_cascading_reconstructible_noexcept(::ztd::tag<_Types...>) noexcept { - return ((__is_reconstructible_noexcept<_Mutable, ::std::in_place_type_t<_Types>, _Args...>()) || ...); + return ((__is_reconstructible_noexcept<::std::in_place_type_t<_Types>, _Args...>()) || ...); } - template + template constexpr decltype(auto) __cascading_reconstruct(::ztd::tag<_Type>, _Args&&... __args) noexcept( - __is_reconstructible_noexcept<_Mutable, ::std::in_place_type_t<_Type>, _Args...>()) { - if constexpr (_Mutable) { - return ::ztd::ranges::reconstruct(::std::in_place_type<_Type>, ::std::forward<_Args>(__args)...); - } - else { - // Oops - return; - } + __is_reconstructible_noexcept<::std::in_place_type_t<_Type>, _Args...>()) { + return ::ztd::ranges::reconstruct(::std::in_place_type<_Type>, ::std::forward<_Args>(__args)...); } - template 0)>* = nullptr> constexpr decltype(auto) __cascading_reconstruct(::ztd::tag<_Type, _Types...>, _Args&&... __args) noexcept( - __is_cascading_reconstructible_noexcept<_Mutable, _Args...>(::ztd::tag<_Type, _Types...>())) { - if constexpr (__is_reconstructible<_Mutable, ::std::in_place_type_t<_Type>, _Args...>()) { - if constexpr (_Mutable) { - return ::ztd::ranges::reconstruct( - ::std::in_place_type<_Type>, ::std::forward<_Args>(__args)...); - } - else { - // oops - return; - } + __is_cascading_reconstructible_noexcept<_Args...>(::ztd::tag<_Type, _Types...>())) { + if constexpr (__is_reconstructible<::std::in_place_type_t<_Type>, _Args...>()) { + return ::ztd::ranges::reconstruct(::std::in_place_type<_Type>, ::std::forward<_Args>(__args)...); } else { - return __cascading_reconstruct<_Mutable>(::ztd::tag<_Types...>(), ::std::forward<_Args>(__args)...); + return __cascading_reconstruct(::ztd::tag<_Types...>(), ::std::forward<_Args>(__args)...); } } - template + template class __cascading_reconstruct_fn { public: template constexpr decltype(auto) operator()(_Args&&... __args) const - noexcept(__is_cascading_reconstructible_noexcept<_Mutable, _Args...>(::ztd::tag<_Types...>())) { - return __cascading_reconstruct<_Mutable>(::ztd::tag<_Types...>(), ::std::forward<_Args>(__args)...); + noexcept(__is_cascading_reconstructible_noexcept<_Args...>(::ztd::tag<_Types...>())) { + return __cascading_reconstruct(::ztd::tag<_Types...>(), ::std::forward<_Args>(__args)...); } }; @@ -336,7 +304,7 @@ namespace ztd { namespace ranges { /// @brief A reconstruct that attempts multiple versions of reconstruct, and if none of them works then /// fallsback to the default subrange return value. template - inline constexpr __rng_detail::__cascading_reconstruct_fn cascading_reconstruct = {}; + inline constexpr __rng_detail::__cascading_reconstruct_fn<_Args...> cascading_reconstruct = {}; } // namespace __fn ZTD_RANGES_INLINE_ABI_NAMESPACE_CLOSE_I_ @@ -381,7 +349,7 @@ namespace ztd { namespace hijack { } } // namespace __hj_detail - template ()>* = nullptr> constexpr ::ztd::span<_Ty> tag_invoke(ztd::tag_t<::ztd::ranges::reconstruct>, ::std::in_place_type_t<::ztd::span<_Ty, _Extent>>, _It __iterator, _Sen __sentinel) noexcept { @@ -439,43 +407,43 @@ namespace ztd { namespace ranges { inline constexpr bool is_tagless_iterator_reconstructible_v = ((::std::is_class_v<_It> || ::std::is_enum_v<_It>) // cf || (::std::is_class_v<_Sen> || ::std::is_enum_v<_Sen>)) // cf - && is_tag_invocable_v<__rng_detail::__reconstruct_fn, _It, _Sen>; + && is_tag_invocable_v<__rng_detail::__reconstruct_fn, _It, _Sen>; template inline constexpr bool is_iterator_reconstructible_v - = is_tag_invocable_v<__rng_detail::__reconstruct_fn, _Tag, _It, _Sen>; + = is_tag_invocable_v<__rng_detail::__reconstruct_fn, _Tag, _It, _Sen>; template inline constexpr bool is_range_iterator_reconstructible_v - = is_tag_invocable_v<__rng_detail::__reconstruct_fn, _Tag, _Range, _It, _Sen>; + = is_tag_invocable_v<__rng_detail::__reconstruct_fn, _Tag, _Range, _It, _Sen>; template inline constexpr bool is_range_reconstructible_v - = is_tag_invocable_v<__rng_detail::__reconstruct_fn, _Tag, _Range>; + = is_tag_invocable_v<__rng_detail::__reconstruct_fn, _Tag, _Range>; template - inline constexpr bool is_reconstructible_v = __rng_detail::__is_reconstructible(); + inline constexpr bool is_reconstructible_v = __rng_detail::__is_reconstructible<_Args...>(); template inline constexpr bool is_nothrow_tagless_iterator_reconstructible_v = ((::std::is_class_v<_It> || ::std::is_enum_v<_It>) // cf || (::std::is_class_v<_Sen> || ::std::is_enum_v<_Sen>)) // cf - && is_nothrow_tag_invocable_v<__rng_detail::__reconstruct_fn, _It, _Sen>; + && is_nothrow_tag_invocable_v<__rng_detail::__reconstruct_fn, _It, _Sen>; template inline constexpr bool is_nothrow_iterator_reconstructible_v - = is_nothrow_tag_invocable_v<__rng_detail::__reconstruct_fn, _Tag, _It, _Sen>; + = is_nothrow_tag_invocable_v<__rng_detail::__reconstruct_fn, _Tag, _It, _Sen>; template inline constexpr bool is_nothrow_range_iterator_reconstructible_v - = is_nothrow_tag_invocable_v<__rng_detail::__reconstruct_fn, _Tag, _Range, _It, _Sen>; + = is_nothrow_tag_invocable_v<__rng_detail::__reconstruct_fn, _Tag, _Range, _It, _Sen>; template inline constexpr bool is_nothrow_range_reconstructible_v - = is_nothrow_tag_invocable_v<__rng_detail::__reconstruct_fn, _It, _Sen>; + = is_nothrow_tag_invocable_v<__rng_detail::__reconstruct_fn, _It, _Sen>; template - inline constexpr bool is_nothrow_reconstructible_v = __rng_detail::__is_reconstructible_noexcept(); + inline constexpr bool is_nothrow_reconstructible_v = __rng_detail::__is_reconstructible_noexcept<_Args...>(); template >, typename _Sen = ranges::range_sentinel_t>> diff --git a/include/ztd/version/detail/is.h b/include/ztd/version/detail/is.h index 0b83f55..9eed0aa 100644 --- a/include/ztd/version/detail/is.h +++ b/include/ztd/version/detail/is.h @@ -51,7 +51,7 @@ #define ZTD_USE(_SYMBOL) _SYMBOL##_I_ #define ZTD_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) #_TOKEN -#define ZTD_TOKEN_TO_STRING_I_(_TOKEN) ZTD_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) +#define ZTD_TOKEN_TO_STRING(_TOKEN) ZTD_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) #define ZTD_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) _LEFT##_RIGHT #define ZTD_CONCAT_TOKENS_I_(_LEFT, _RIGHT) ZTD_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) diff --git a/include/ztd/version/detail/version.c++.hpp b/include/ztd/version/detail/version.c++.hpp index ab2a67d..a18d3f7 100644 --- a/include/ztd/version/detail/version.c++.hpp +++ b/include/ztd/version/detail/version.c++.hpp @@ -37,6 +37,65 @@ #include // clang-format off +#if defined(ZTD_EXCEPTIONS) + #if (ZTD_EXCEPTIONS != 0) + #define ZTD_EXCEPTIONS_I_ ZTD_ON + #else + #define ZTD_EXCEPTIONS_I_ ZTD_OFF + #endif +#elif defined(__cpp_exceptions) && (__cpp_exceptions != 0) + #define ZTD_EXCEPTIONS_I_ ZTD_DEFAULT_ON +#elif ZTD_IS_ON(ZTD_COMPILER_GCC) + #if defined(__EXCEPTIONS) && (__EXCEPTIONS != 0) + #define ZTD_EXCEPTIONS_I_ ZTD_DEFAULT_ON + #else + #define ZTD_EXCEPTIONS_I_ ZTD_DEFAULT_OFF + #endif +#elif ZTD_IS_ON(ZTD_COMPILER_CLANG) + #if defined(__has_feature) && _has_feature(cxx_exceptions) + #define ZTD_EXCEPTIONS_I_ ZTD_DEFAULT_ON + #else + #define ZTD_EXCEPTIONS_I_ ZTD_DEFAULT_OFF + #endif +#elif ZTD_IS_ON(ZTD_COMPILER_VCXX) + #if defined(_CPPUNWIND) && (_CPPUNWIND != 0) + #define ZTD_EXCEPTIONS_I_ ZTD_DEFAULT_ON + #else + #define ZTD_EXCEPTIONS_I_ ZTD_DEFAULT_OFF + #endif +#else + #define ZTD_EXCEPTIONS_I_ ZTD_DEFAULT_OFF +#endif + +#if defined(ZTD_RTTI) + #if (ZTD_RTTI != 0) + #define ZTD_RTTI_I_ ZTD_ON + #else + #define ZTD_RTTI_I_ ZTD_OFF + #endif +#elif defined(__cpp_rtti) && (__cpp_rtti != 0) + #define ZTD_RTTI_I_ ZTD_DEFAULT_ON +#elif ZTD_IS_ON(ZTD_COMPILER_GCC) + #if defined(__GXX_RTTI) && (__GXX_RTTI != 0) + #define ZTD_RTTI_I_ ZTD_DEFAULT_ON + #else + #define ZTD_RTTI_I_ ZTD_DEFAULT_OFF + #endif +#elif ZTD_IS_ON(ZTD_COMPILER_CLANG) + #if defined(__has_feature) && _has_feature(cxx_rtti) + #define ZTD_RTTI_I_ ZTD_DEFAULT_ON + #else + #define ZTD_RTTI_I_ ZTD_DEFAULT_OFF + #endif +#elif ZTD_IS_ON(ZTD_COMPILER_VCXX) + #if defined(_CPPRTTI) && (_CPPRTTI != 0) + #define ZTD_RTTI_I_ ZTD_DEFAULT_ON + #else + #define ZTD_RTTI_I_ ZTD_DEFAULT_OFF + #endif +#else + #define ZTD_RTTI_I_ ZTD_DEFAULT_OFF +#endif #if defined (ZTD_STD_ALIGNED_OPERATOR_NEW) #if (ZTD_STD_ALIGNED_OPERATOR_NEW != 0) @@ -84,7 +143,17 @@ #define ZTD_STD_DESIGNATED_INITIALIZERS_I_ ZTD_DEFAULT_OFF #endif - +#if defined(ZTD_STD_EXPLICIT) + #if (ZTD_STD_EXPLICIT != 0) + #define ZTD_STD_EXPLICIT_I_ ZTD_ON + #else + #define ZTD_STD_EXPLICIT_I_ ZTD_OFF + #endif +#elif defined(__cpp_conditional_explicit) && (__cpp_conditional_explicit != 0) + #define ZTD_STD_EXPLICIT_I_ ZTD_DEFAULT_ON +#else + #define ZTD_STD_EXPLICIT_I_ ZTD_DEFAULT_OFF +#endif #if defined(ZTD_STD_SPACESHIP_COMPARE) #if (ZTD_STD_SPACESHIP_COMPARE != 0) @@ -396,7 +465,7 @@ #if defined(ZTD_CXX_COMPILE_TIME_ENCODING_NAME) #define ZTD_CXX_COMPILE_TIME_ENCODING_NAME_GET_I_() ZTD_CXX_COMPILE_TIME_ENCODING_NAME - #define ZTD_CXX_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "set by the user with ZTD_CXX_COMPILE_TIME_ENCODING_NAME as (" ZTD_TOKEN_TO_STRING_I_(ZTD_COMPILE_TIME_ENCODING_NAME) ")" + #define ZTD_CXX_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "set by the user with ZTD_CXX_COMPILE_TIME_ENCODING_NAME as (" ZTD_TOKEN_TO_STRING(ZTD_COMPILE_TIME_ENCODING_NAME) ")" #define ZTD_CXX_COMPILE_TIME_ENCODING_NAME_I_ ZTD_DEFAULT_ON #elif ZTD_IS_ON(ZTD_CXX) && ZTD_IS_ON(ZTD_STD_LIBRARY_TEXT_ENCODING_ID) #define ZTD_CXX_COMPILE_TIME_ENCODING_NAME_GET_I_() ::std::text_encoding::literal().name() @@ -410,7 +479,7 @@ #if defined(ZTD_CXX_COMPILE_TIME_WIDE_ENCODING_NAME) #define ZTD_CXX_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() ZTD_CXX_COMPILE_TIME_WIDE_ENCODING_NAME - #define ZTD_CXX_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() "set by the user with ZTD_CXX_COMPILE_TIME_WIDE_ENCODING_NAME as (" ZTD_TOKEN_TO_STRING_I_(ZTD_COMPILE_TIME_WIDE_ENCODING_NAME) ")" + #define ZTD_CXX_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() "set by the user with ZTD_CXX_COMPILE_TIME_WIDE_ENCODING_NAME as (" ZTD_TOKEN_TO_STRING(ZTD_COMPILE_TIME_WIDE_ENCODING_NAME) ")" #define ZTD_CXX_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_ON #elif ZTD_IS_ON(ZTD_CXX) && ZTD_IS_ON(ZTD_STD_LIBRARY_TEXT_ENCODING_ID) #define ZTD_CXX_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() ::std::text_encoding::wide_literal().name() diff --git a/include/ztd/version/detail/version.c.h b/include/ztd/version/detail/version.c.h index 35777ee..64f1a3f 100644 --- a/include/ztd/version/detail/version.c.h +++ b/include/ztd/version/detail/version.c.h @@ -399,6 +399,22 @@ #define ZTD_ASSERT_CHECKS_I_ ZTD_OFF #endif +#if defined(ZTD_CONSTEXPR_ASSERT_CHECKS) + #if (ZTD_CONSTEXPR_ASSERT_CHECKS != 0) + #define ZTD_CONSTEXPR_ASSERT_CHECKS_I_ ZTD_ON + #else + #define ZTD_CONSTEXPR_ASSERT_CHECKS_I_ ZTD_OFF + #endif +#elif ZTD_IS_ON(ZTD_DEBUG) || ZTD_IS_ON(ZTD_ASSERT_CHECKS) + // C++17 and lower is worthless for constexpr code; don't fucking bother + #if defined(__cplusplus) && (__cplusplus >= 202000L) + #define ZTD_CONSTEXPR_ASSERT_CHECKS_I_ ZTD_ON + #else + #define ZTD_CONSTEXPR_ASSERT_CHECKS_I_ ZTD_OFF + #endif +#else + #define ZTD_CONSTEXPR_ASSERT_CHECKS_I_ ZTD_OFF +#endif #if defined(ZTD_NL_LANGINFO_H) #if (ZTD_NL_LANGINFO_H != 0) @@ -795,11 +811,11 @@ #if defined(ZTD_COMPILE_TIME_ENCODING_NAME) #define ZTD_COMPILE_TIME_ENCODING_NAME_GET_I_() ZTD_COMPILE_TIME_ENCODING_NAME - #define ZTD_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "set by the user with ZTD_COMPILE_TIME_ENCODING_NAME as (" ZTD_TOKEN_TO_STRING_I_(ZTD_COMPILE_TIME_ENCODING_NAME) ")" + #define ZTD_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "set by the user with ZTD_COMPILE_TIME_ENCODING_NAME as (" ZTD_TOKEN_TO_STRING(ZTD_COMPILE_TIME_ENCODING_NAME) ")" #define ZTD_COMPILE_TIME_ENCODING_NAME_I_ ZTD_DEFAULT_ON #elif defined(_MSVC_EXECUTION_CHARACTER_SET) #define ZTD_COMPILE_TIME_ENCODING_NAME_GET_I_() ZTD_VCXX_MSC_CODEPAGE_ID_TO_NAME_I_(_MSVC_EXECUTION_CHARACTER_SET) - #define ZTD_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "MSVC CodePage ID: " ZTD_TOKEN_TO_STRING_I_(_MSVC_EXECUTION_CHARACTER_SET) " (" ZTD_VCXX_MSC_CODEPAGE_ID_TO_NAME_I_(_MSVC_EXECUTION_CHARACTER_SET) ")" + #define ZTD_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "MSVC CodePage ID: " ZTD_TOKEN_TO_STRING(_MSVC_EXECUTION_CHARACTER_SET) " (" ZTD_VCXX_MSC_CODEPAGE_ID_TO_NAME_I_(_MSVC_EXECUTION_CHARACTER_SET) ")" #define ZTD_COMPILE_TIME_ENCODING_NAME_I_ ZTD_DEFAULT_ON #elif defined(__GNUC_EXECUTION_CHARSET_NAME) #define ZTD_COMPILE_TIME_ENCODING_NAME_GET_I_() __GNUC_EXECUTION_CHARSET_NAME @@ -817,7 +833,7 @@ #if defined(ZTD_COMPILE_TIME_WIDE_ENCODING_NAME) #define ZTD_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() ZTD_COMPILE_TIME_WIDE_ENCODING_NAME - #define ZTD_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() "set by the user with ZTD_COMPILE_TIME_ENCODING_NAME as (" ZTD_TOKEN_TO_STRING_I_(ZTD_COMPILE_TIME_WIDE_ENCODING_NAME) ")" + #define ZTD_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() "set by the user with ZTD_COMPILE_TIME_ENCODING_NAME as (" ZTD_TOKEN_TO_STRING(ZTD_COMPILE_TIME_WIDE_ENCODING_NAME) ")" #define ZTD_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_ON #elif defined(__GNUC_WIDE_EXECUTION_CHARSET_NAME) #define ZTD_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() __GNUC_WIDE_EXECUTION_CHARSET_NAME