From 4e569f011550da7089d0a56fba733c247289f5ae Mon Sep 17 00:00:00 2001 From: Ziemas Date: Sun, 18 Feb 2024 19:23:19 +0100 Subject: [PATCH] Switch to std::span (#3376) Now that we have cpp20 we can ditch nonstd::span. Depends on #3375 --- .github/workflows/linux-build-gcc.yaml | 7 +- common/util/BinaryReader.h | 7 +- decompiler/data/streamed_audio.cpp | 4 +- game/sound/989snd/loader.cpp | 20 +- game/sound/989snd/loader.h | 5 +- game/sound/989snd/musicbank.h | 9 +- game/sound/989snd/player.cpp | 2 +- game/sound/989snd/player.h | 4 +- game/sound/989snd/sfxblock.h | 5 +- game/sound/sndshim.cpp | 2 +- third-party/span.hpp | 1884 ------------------------ 11 files changed, 32 insertions(+), 1917 deletions(-) delete mode 100644 third-party/span.hpp diff --git a/.github/workflows/linux-build-gcc.yaml b/.github/workflows/linux-build-gcc.yaml index f05f21a8e..740ab24ec 100644 --- a/.github/workflows/linux-build-gcc.yaml +++ b/.github/workflows/linux-build-gcc.yaml @@ -31,10 +31,15 @@ jobs: run: | sudo apt update sudo apt install build-essential cmake \ - clang gcc g++ lcov make nasm libxrandr-dev \ + clang gcc-10 g++-10 lcov make nasm libxrandr-dev \ libxinerama-dev libxcursor-dev libpulse-dev \ libxi-dev zip ninja-build libgl1-mesa-dev libssl-dev + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 + sudo update-alternatives --set gcc /usr/bin/gcc-10 + sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 100 + sudo update-alternatives --set g++ /usr/bin/g++-10 + - name: Setup Buildcache uses: mikehardy/buildcache-action@v2.1.0 with: diff --git a/common/util/BinaryReader.h b/common/util/BinaryReader.h index 4b1b0baea..c40d56bcb 100644 --- a/common/util/BinaryReader.h +++ b/common/util/BinaryReader.h @@ -7,16 +7,15 @@ #include #include +#include #include #include "common/common_types.h" #include "common/util/Assert.h" -#include "third-party/span.hpp" - class BinaryReader { public: - explicit BinaryReader(nonstd::span _span) : m_span(_span) {} + explicit BinaryReader(std::span _span) : m_span(_span) {} template T read() { @@ -39,6 +38,6 @@ class BinaryReader { void set_seek(u32 seek) { m_seek = seek; } private: - nonstd::span m_span; + std::span m_span; uint32_t m_seek = 0; }; diff --git a/decompiler/data/streamed_audio.cpp b/decompiler/data/streamed_audio.cpp index 86574b05b..5a975d628 100644 --- a/decompiler/data/streamed_audio.cpp +++ b/decompiler/data/streamed_audio.cpp @@ -210,7 +210,7 @@ struct AudioFileInfo { }; AudioFileInfo process_audio_file(const fs::path& output_folder, - nonstd::span data, + std::span data, const std::string& name, const std::string& suffix, bool stereo) { @@ -276,7 +276,7 @@ void process_streamed_audio(const decompiler::Config& config, } lg::info("File {}, total {:.2f} minutes", entry.name, audio_len / 60.0); - auto data = nonstd::span(wad_data).subspan(entry.start_byte); + auto data = std::span(wad_data).subspan(entry.start_byte); auto info = process_audio_file(output_path, data, entry.name, suffix, entry.stereo); audio_len += info.length_seconds; filename_data[i][lang_id + 1] = info.filename; diff --git a/game/sound/989snd/loader.cpp b/game/sound/989snd/loader.cpp index 28cdf33b7..06624481d 100644 --- a/game/sound/989snd/loader.cpp +++ b/game/sound/989snd/loader.cpp @@ -191,7 +191,7 @@ static Grain ReadGrainV2(BinaryReader& data, BinaryReader grainData, u8* samples return grain; }; -SFXBlock* SFXBlock::ReadBlock(nonstd::span bank_data, nonstd::span samples) { +SFXBlock* SFXBlock::ReadBlock(std::span bank_data, std::span samples) { BinaryReader data(bank_data); // auto block = std::make_unique(); auto block = new SFXBlock(); @@ -313,9 +313,9 @@ SFXBlock* SFXBlock::ReadBlock(nonstd::span bank_data, nonstd::span sampl return block; } -MusicBank* MusicBank::ReadBank(nonstd::span bank_data, - nonstd::span samples, - nonstd::span midi_data) { +MusicBank* MusicBank::ReadBank(std::span bank_data, + std::span samples, + std::span midi_data) { BinaryReader data(bank_data); // auto bank = std::make_unique(); auto bank = new MusicBank(); @@ -388,7 +388,7 @@ MusicBank* MusicBank::ReadBank(nonstd::span bank_data, } } - auto seq_buf = nonstd::span(bank->SeqData.get(), midi_data.size_bytes()); + auto seq_buf = std::span(bank->SeqData.get(), midi_data.size_bytes()); BinaryReader seq_data(seq_buf); FileAttributes fa; fa.Read(seq_data); @@ -407,7 +407,7 @@ MusicBank* MusicBank::ReadBank(nonstd::span bank_data, return bank; } -BankHandle Loader::BankLoad(nonstd::span bank) { +BankHandle Loader::BankLoad(std::span bank) { BinaryReader reader(bank); FileAttributes fa; fa.Read(reader); @@ -419,17 +419,15 @@ BankHandle Loader::BankLoad(nonstd::span bank) { reader.set_seek(fa.where[0].offset); u32 fourcc = reader.read(); - nonstd::span bank_data(nonstd::span(bank).subspan(fa.where[0].offset, fa.where[0].size)); - nonstd::span sample_data( - nonstd::span(bank).subspan(fa.where[1].offset, fa.where[1].size)); + std::span bank_data(std::span(bank).subspan(fa.where[0].offset, fa.where[0].size)); + std::span sample_data(std::span(bank).subspan(fa.where[1].offset, fa.where[1].size)); if (fourcc == snd::fourcc("SBv2")) { if (fa.num_chunks != 3) { fmt::print("SBv2 without midi data not supported\n"); return 0; } - nonstd::span midi_data( - nonstd::span(bank).subspan(fa.where[2].offset, fa.where[2].size)); + std::span midi_data(std::span(bank).subspan(fa.where[2].offset, fa.where[2].size)); auto bank = MusicBank::ReadBank(bank_data, sample_data, midi_data); mBanks.emplace_back(bank); diff --git a/game/sound/989snd/loader.h b/game/sound/989snd/loader.h index 099357ec2..1ed63b543 100644 --- a/game/sound/989snd/loader.h +++ b/game/sound/989snd/loader.h @@ -3,6 +3,7 @@ #pragma once #include +#include #include #include "soundbank.h" @@ -10,8 +11,6 @@ #include "common/common_types.h" #include "common/util/BinaryReader.h" -#include "third-party/span.hpp" - namespace snd { using BankHandle = SoundBank*; @@ -37,7 +36,7 @@ class Loader { void UnloadBank(BankHandle id); - BankHandle BankLoad(nonstd::span bank); + BankHandle BankLoad(std::span bank); private: std::vector> mBanks; diff --git a/game/sound/989snd/musicbank.h b/game/sound/989snd/musicbank.h index cd64a1224..76a3b75d3 100644 --- a/game/sound/989snd/musicbank.h +++ b/game/sound/989snd/musicbank.h @@ -1,11 +1,10 @@ #pragma once +#include #include #include #include "soundbank.h" -#include "third-party/span.hpp" - namespace snd { struct Midi { @@ -63,9 +62,9 @@ class MusicBank : public SoundBank { std::unique_ptr SeqData; std::variant MidiData; - static MusicBank* ReadBank(nonstd::span bank_data, - nonstd::span samples, - nonstd::span midi_data); + static MusicBank* ReadBank(std::span bank_data, + std::span samples, + std::span midi_data); std::optional> MakeHandler(VoiceManager& vm, u32 sound_id, diff --git a/game/sound/989snd/player.cpp b/game/sound/989snd/player.cpp index d9477f953..245e71056 100644 --- a/game/sound/989snd/player.cpp +++ b/game/sound/989snd/player.cpp @@ -233,7 +233,7 @@ void Player::SetMasterVolume(u32 group, s32 volume) { } } -BankHandle Player::LoadBank(nonstd::span bank) { +BankHandle Player::LoadBank(std::span bank) { std::scoped_lock lock(mTickLock); return mLoader.BankLoad(bank); } diff --git a/game/sound/989snd/player.h b/game/sound/989snd/player.h index ccc23a009..83f4b6d9c 100644 --- a/game/sound/989snd/player.h +++ b/game/sound/989snd/player.h @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -18,7 +19,6 @@ #include "game/sound/989snd/vagvoice.h" #include "third-party/cubeb/cubeb/include/cubeb/cubeb.h" -#include "third-party/span.hpp" namespace snd { @@ -32,7 +32,7 @@ class Player { // player(player&& other) noexcept = default; // player& operator=(player&& other) noexcept = default; - BankHandle LoadBank(nonstd::span bank); + BankHandle LoadBank(std::span bank); u32 PlaySound(BankHandle bank, u32 sound, s32 vol, s32 pan, s32 pm, s32 pb); u32 PlaySoundByName(BankHandle bank, diff --git a/game/sound/989snd/sfxblock.h b/game/sound/989snd/sfxblock.h index 3255e363d..e7cd3f02a 100644 --- a/game/sound/989snd/sfxblock.h +++ b/game/sound/989snd/sfxblock.h @@ -1,11 +1,10 @@ #pragma once +#include #include #include "sfxgrain.h" #include "soundbank.h" -#include "third-party/span.hpp" - namespace snd { struct SFXUserData { // 0x10 @@ -46,7 +45,7 @@ class SFXBlock : public SoundBank { std::map Names; std::unique_ptr SampleData; - static SFXBlock* ReadBlock(nonstd::span bank_data, nonstd::span samples); + static SFXBlock* ReadBlock(std::span bank_data, std::span samples); std::optional> MakeHandler(VoiceManager& vm, u32 sound_id, diff --git a/game/sound/sndshim.cpp b/game/sound/sndshim.cpp index 5df2dc530..583101080 100644 --- a/game/sound/sndshim.cpp +++ b/game/sound/sndshim.cpp @@ -214,7 +214,7 @@ snd::BankHandle snd_BankLoadEx(const char* filename, if (player) { // TODO put the load on the thread pool? auto file_buf = file_util::read_binary_file(std::string(filename)); - return player->LoadBank(nonstd::span(file_buf).subspan(offset)); + return player->LoadBank(std::span(file_buf).subspan(offset)); } else { return 0; } diff --git a/third-party/span.hpp b/third-party/span.hpp deleted file mode 100644 index 5e611cedc..000000000 --- a/third-party/span.hpp +++ /dev/null @@ -1,1884 +0,0 @@ -// -// span for C++98 and later. -// Based on http://wg21.link/p0122r7 -// For more information see https://github.com/martinmoene/span-lite -// -// Copyright 2018-2021 Martin Moene -// -// 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 - -#define span_lite_MAJOR 0 -#define span_lite_MINOR 10 -#define span_lite_PATCH 3 - -#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 -# define span_FEATURE_WITH_CONTAINER_TO_STD 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 0 // 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 -# define span_FEATURE_MAKE_SPAN_TO_STD 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 defined(_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) ) - -// -// Use C++20 std::span: -// - -#if span_USES_STD_SPAN - -#include - -namespace nonstd { - -using std::span; - -// 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: -// -// 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) ) - -// Compiler warning suppression: - -#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" ) - -#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 - -#if span_HAVE( ARRAY ) -# include -#endif - -#if span_HAVE( BYTE ) -# 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< void >( 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< bool B = (VA), typename std::enable_if::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 - -#define span_REQUIRES_A(VA) \ - , typename std::enable_if< (VA), void*>::type = nullptr - -#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< class T, extent_t Extent = dynamic_extent > -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_cv; -using std::remove_const; -using std::remove_volatile; - -#else - -template< class T > struct remove_const { typedef T type; }; -template< class T > struct remove_const< T const > { typedef T type; }; - -template< class T > struct remove_volatile { typedef T type; }; -template< class T > struct remove_volatile< T volatile > { typedef T type; }; - -template< class T > -struct remove_cv -{ - typedef typename std11::remove_volatile< typename std11::remove_const< T >::type >::type type; -}; - -#endif // span_HAVE( REMOVE_CONST ) - -#if span_HAVE( TYPE_TRAITS ) - -using std::is_same; -using std::is_signed; -using std::integral_constant; -using std::true_type; -using std::false_type; -using std::remove_reference; - -#else - -template< class T, T v > struct integral_constant { enum { value = v }; }; -typedef integral_constant< bool, true > true_type; -typedef integral_constant< bool, false > false_type; - -template< class T, class U > struct is_same : false_type{}; -template< class T > struct is_same : true_type{}; - -template< typename T > 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: - -namespace std17 { - -template< bool v > struct bool_constant : std11::integral_constant{}; - -#if span_CPP11_120 - -template< class...> -using void_t = void; - -#endif - -#if span_HAVE( DATA ) - -using std::data; -using std::size; - -#elif span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) - -template< typename T, std::size_t N > -inline span_constexpr auto size( const T(&)[N] ) span_noexcept -> size_t -{ - return N; -} - -template< typename C > -inline span_constexpr auto size( C const & cont ) -> decltype( cont.size() ) -{ - return cont.size(); -} - -template< typename T, std::size_t N > -inline span_constexpr auto data( T(&arr)[N] ) span_noexcept -> T* -{ - return &arr[0]; -} - -template< typename C > -inline span_constexpr auto data( C & cont ) -> decltype( cont.data() ) -{ - return cont.data(); -} - -template< typename C > -inline span_constexpr auto data( C const & cont ) -> decltype( cont.data() ) -{ - return cont.data(); -} - -template< typename E > -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< class T > -using iter_reference_t = decltype( *std::declval() ); -#endif - -} // namespace std20 - -// Implementation details: - -namespace detail { - -/*enum*/ struct enabler{}; - -template< typename T > -span_constexpr bool is_positive( T x ) -{ - return std11::is_signed::value ? x >= 0 : true; -} - -#if span_HAVE( TYPE_TRAITS ) - -template< class Q > -struct is_span_oracle : std::false_type{}; - -template< class T, span_CONFIG_EXTENT_TYPE Extent > -struct is_span_oracle< span > : std::true_type{}; - -template< class Q > -struct is_span : is_span_oracle< typename std::remove_cv::type >{}; - -template< class Q > -struct is_std_array_oracle : std::false_type{}; - -#if span_HAVE( ARRAY ) - -template< class T, std::size_t Extent > -struct is_std_array_oracle< std::array > : std::true_type{}; - -#endif - -template< class Q > -struct is_std_array : is_std_array_oracle< typename std::remove_cv::type >{}; - -template< class Q > -struct is_array : std::false_type {}; - -template< class T > -struct is_array : std::true_type {}; - -template< class T, std::size_t N > -struct is_array : std::true_type {}; - -#if span_CPP11_140 && ! span_BETWEEN( span_COMPILER_GNUC_VERSION, 1, 500 ) - -template< class, class = void > -struct has_size_and_data : std::false_type{}; - -template< class C > -struct has_size_and_data -< - C, std17::void_t< - decltype( std17::size(std::declval()) ), - decltype( std17::data(std::declval()) ) > -> : std::true_type{}; - -template< class, class, class = void > -struct is_compatible_element : std::false_type {}; - -template< class C, class E > -struct is_compatible_element -< - C, E, std17::void_t< - decltype( std17::data(std::declval()) ) > -> : std::is_convertible< typename std::remove_pointer() ) )>::type(*)[], E(*)[] >{}; - -template< class C > -struct is_container : std17::bool_constant -< - ! is_span< C >::value - && ! is_array< C >::value - && ! is_std_array< C >::value - && has_size_and_data< C >::value ->{}; - -template< class C, class E > -struct is_compatible_container : std17::bool_constant -< - is_container::value - && is_compatible_element::value ->{}; - -#else // span_CPP11_140 - -template< - class C, class E - span_REQUIRES_T(( - ! is_span< C >::value - && ! is_array< C >::value - && ! is_std_array< C >::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 - -span_noreturn 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 ); -} - -#else // MEMBER_AT - -span_noreturn inline void throw_out_of_range( size_t /*idx*/, size_t /*size*/ ) -{ - throw std::out_of_range( "span::at(): index outside span" ); -} -#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 ); -} - -#else // span_CONFIG( CONTRACT_VIOLATION_THROWS_V ) - -span_noreturn inline void report_contract_violation( char const * /*msg*/ ) span_noexcept -{ - std::terminate(); -} - -#endif // span_CONFIG( CONTRACT_VIOLATION_THROWS_V ) - -} // namespace detail - -// Prevent signed-unsigned mismatch: - -#define span_sizeof(T) static_cast( sizeof(T) ) - -template< class T > -inline span_constexpr size_t to_size( T size ) -{ - return static_cast( size ); -} - -// -// [views.span] - A view over a contiguous, single-dimension sequence of objects -// -template< class T, extent_t Extent /*= dynamic_extent*/ > -class span -{ -public: - // constants and types - - typedef T element_type; - typedef typename std11::remove_cv< T >::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; - - typedef pointer iterator; - typedef const_pointer const_iterator; - - typedef std::ptrdiff_t difference_type; - - typedef std::reverse_iterator< iterator > reverse_iterator; - typedef std::reverse_iterator< const_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 ); - } - -#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< typename It - span_REQUIRES_T(( - std::is_convertible()), element_type &>::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 ) ) - ); - } -#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< typename It, typename End - span_REQUIRES_T(( - std::is_convertible()), element_type *>::value - && ! std::is_convertible::value - )) - > - span_constexpr_exp span( It first, End last ) - : data_( to_address( first ) ) - , size_( to_size( last - first ) ) - { - span_EXPECTS( - last - first >= 0 - ); - } -#else - span_constexpr_exp span( pointer first, pointer last ) - : data_( first ) - , size_( to_size( last - first ) ) - { - span_EXPECTS( - last - first >= 0 - ); - } -#endif - - template< std::size_t N - span_REQUIRES_T(( - (Extent == dynamic_extent || Extent == static_cast(N)) - && std::is_convertible< value_type(*)[], element_type(*)[] >::value - )) - > - span_constexpr span( element_type ( &arr )[ N ] ) span_noexcept - : data_( span_ADDRESSOF( arr[0] ) ) - , size_( N ) - {} - -#if span_HAVE( ARRAY ) - - template< std::size_t N - span_REQUIRES_T(( - (Extent == dynamic_extent || Extent == static_cast(N)) - && std::is_convertible< value_type(*)[], element_type(*)[] >::value - )) - > -# if span_FEATURE( CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE ) - span_constexpr span( std::array< element_type, N > & arr ) span_noexcept -# else - span_constexpr span( std::array< value_type, N > & arr ) span_noexcept -# endif - : data_( arr.data() ) - , size_( to_size( arr.size() ) ) - {} - - template< std::size_t N -# if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - span_REQUIRES_T(( - (Extent == dynamic_extent || Extent == static_cast(N)) - && std::is_convertible< value_type(*)[], element_type(*)[] >::value - )) -# endif - > - span_constexpr span( std::array< value_type, N> const & arr ) span_noexcept - : data_( arr.data() ) - , size_( to_size( arr.size() ) ) - {} - -#endif // span_HAVE( ARRAY ) - -#if span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) - template< class Container - span_REQUIRES_T(( - detail::is_compatible_container< Container, element_type >::value - )) - > - span_constexpr span( Container & cont ) - : data_( std17::data( cont ) ) - , size_( to_size( std17::size( cont ) ) ) - {} - - template< class Container - span_REQUIRES_T(( - std::is_const< element_type >::value - && detail::is_compatible_container< Container, element_type >::value - )) - > - span_constexpr span( Container const & cont ) - : data_( std17::data( cont ) ) - , size_( to_size( std17::size( cont ) ) ) - {} - -#endif // span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) - -#if span_FEATURE( WITH_CONTAINER ) - - template< class Container > - span_constexpr span( with_container_t, Container & cont ) - : data_( cont.size() == 0 ? span_nullptr : span_ADDRESSOF( cont[0] ) ) - , size_( to_size( cont.size() ) ) - {} - - template< class Container > - 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() ) ) - {} -#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_ ) - {} - - ~span() span_noexcept - {} - - span_constexpr14 span & operator=( span const & other ) span_noexcept - { - data_ = other.data_; - size_ = other.size_; - - return *this; - } -#endif - - template< class OtherElementType, extent_type OtherExtent - span_REQUIRES_T(( - (Extent == dynamic_extent || OtherExtent == dynamic_extent || Extent == OtherExtent) - && std::is_convertible::value - )) - > - span_constexpr_exp span( span const & other ) span_noexcept - : data_( other.data() ) - , size_( other.size() ) - { - span_EXPECTS( OtherExtent == dynamic_extent || other.size() == to_size(OtherExtent) ); - } - - // 26.7.3.3 Subviews [span.sub] - - template< extent_type Count > - span_constexpr_exp span< element_type, Count > - first() const - { - span_EXPECTS( detail::is_positive( Count ) && Count <= size() ); - - return span< element_type, Count >( data(), Count ); - } - - template< extent_type Count > - span_constexpr_exp span< element_type, Count > - last() const - { - span_EXPECTS( detail::is_positive( Count ) && Count <= size() ); - - return span< element_type, Count >( data() + (size() - Count), Count ); - } - -#if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - template< size_type Offset, extent_type Count = dynamic_extent > -#else - template< size_type Offset, extent_type Count /*= dynamic_extent*/ > -#endif - span_constexpr_exp span< element_type, Count > - subspan() const - { - span_EXPECTS( - ( detail::is_positive( Offset ) && Offset <= size() ) && - ( Count == dynamic_extent || (detail::is_positive( Count ) && Count + Offset <= size()) ) - ); - - return span< element_type, Count >( - data() + Offset, Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : size() - Offset) ); - } - - span_constexpr_exp span< element_type, dynamic_extent > - first( size_type count ) const - { - span_EXPECTS( detail::is_positive( count ) && count <= size() ); - - return span< element_type, dynamic_extent >( data(), count ); - } - - span_constexpr_exp span< element_type, dynamic_extent > - last( size_type count ) const - { - span_EXPECTS( detail::is_positive( count ) && count <= size() ); - - return span< element_type, dynamic_extent >( data() + ( size() - count ), count ); - } - - span_constexpr_exp span< element_type, dynamic_extent > - 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< element_type, dynamic_extent >( - data() + offset, count == static_cast(dynamic_extent) ? size() - offset : count ); - } - - // 26.7.3.4 Observers [span.obs] - - span_constexpr size_type size() const span_noexcept - { - return size_; - } - - span_constexpr std::ptrdiff_t ssize() const span_noexcept - { - return static_cast( size_ ); - } - - span_constexpr size_type size_bytes() const span_noexcept - { - return size() * to_size( sizeof( element_type ) ); - } - - span_nodiscard span_constexpr bool empty() const span_noexcept - { - return size() == 0; - } - - // 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 ); - } - -#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() ); - } - 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() ); - } - - span_constexpr const_reverse_iterator crbegin() const span_noexcept - { - return const_reverse_iterator ( cend() ); - } - - span_constexpr const_reverse_iterator crend() const span_noexcept - { - return const_reverse_iterator( cbegin() ); - } - -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; - } - - template< typename U > - static inline span_constexpr U * to_address( U * p ) span_noexcept - { - return p; - } - - template< typename Ptr - span_REQUIRES_T(( ! std::is_pointer::value )) - > - static inline span_constexpr pointer to_address( Ptr const & it ) span_noexcept - { - return to_address( it.operator->() ); - } -#endif // span_HAVE( ITERATOR_CTOR ) - -private: - pointer data_; - size_type size_; -}; - -// class template argument deduction guides: - -#if span_HAVE( DEDUCTION_GUIDES ) - -template< class T, size_t N > -span( T (&)[N] ) -> span(N)>; - -template< class T, size_t N > -span( std::array & ) -> span(N)>; - -template< class T, size_t N > -span( std::array const & ) -> span(N)>; - -#if span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) - -template< class Container > -span( Container& ) -> span; - -template< class Container > -span( Container const & ) -> span; - -#endif - -// iterator: constraints: It satisfies contiguous_­iterator. - -template< class It, class EndOrSize > -span( It, EndOrSize ) -> span< typename std11::remove_reference< typename std20::iter_reference_t >::type >; - -#endif // span_HAVE( DEDUCTION_GUIDES ) - -// 26.7.3.7 Comparison operators [span.comparison] - -#if span_FEATURE( COMPARISON ) -#if span_FEATURE( SAME ) - -template< class T1, extent_t E1, class T2, extent_t E2 > -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(); -} - -#endif - -template< class T1, extent_t E1, class T2, extent_t E2 > -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< class T1, extent_t E1, class T2, extent_t E2 > -inline span_constexpr bool operator<( span const & l, span const & r ) -{ - return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() ); -} - -template< class T1, extent_t E1, class T2, extent_t E2 > -inline span_constexpr bool operator!=( span const & l, span const & r ) -{ - return !( l == r ); -} - -template< class T1, extent_t E1, class T2, extent_t E2 > -inline span_constexpr bool operator<=( span const & l, span const & r ) -{ - return !( r < l ); -} - -template< class T1, extent_t E1, class T2, extent_t E2 > -inline span_constexpr bool operator>( span const & l, span const & r ) -{ - return ( r < l ); -} - -template< class T1, extent_t E1, class T2, extent_t E2 > -inline span_constexpr bool operator>=( span const & l, span const & r ) -{ - return !( l < r ); -} - -#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< typename T, extent_t Extent > -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< typename T > -struct BytesExtent< T, dynamic_extent > -{ -#if span_CPP11_OR_GREATER - enum ET : extent_t { value = dynamic_extent }; -#else - enum ET { value = dynamic_extent }; -#endif -}; - -template< class T, extent_t Extent > -inline span_constexpr span< const std17::byte, BytesExtent::value > -as_bytes( span spn ) span_noexcept -{ -#if 0 - return { reinterpret_cast< std17::byte const * >( spn.data() ), spn.size_bytes() }; -#else - return span< const std17::byte, BytesExtent::value >( - reinterpret_cast< std17::byte const * >( spn.data() ), spn.size_bytes() ); // NOLINT -#endif -} - -template< class T, extent_t Extent > -inline span_constexpr span< std17::byte, BytesExtent::value > -as_writable_bytes( span spn ) span_noexcept -{ -#if 0 - return { reinterpret_cast< std17::byte * >( spn.data() ), spn.size_bytes() }; -#else - return span< std17::byte, BytesExtent::value >( - reinterpret_cast< std17::byte * >( spn.data() ), spn.size_bytes() ); // NOLINT -#endif -} - -#endif // span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE ) - -// 27.8 Container and view access [iterator.container] - -template< class T, extent_t Extent /*= dynamic_extent*/ > -span_constexpr std::size_t size( span const & spn ) -{ - return static_cast( spn.size() ); -} - -template< class T, extent_t Extent /*= dynamic_extent*/ > -span_constexpr std::ptrdiff_t ssize( span const & spn ) -{ - return static_cast( spn.size() ); -} - -} // namespace span_lite -} // namespace nonstd - -// 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< class T > -inline span_constexpr span -make_span( T * ptr, size_t count ) span_noexcept -{ - return span( ptr, count ); -} - -template< class T > -inline span_constexpr span -make_span( T * first, T * last ) span_noexcept -{ - return span( first, last ); -} - -template< class T, std::size_t N > -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< class T, std::size_t N > -inline span_constexpr span(N)> -make_span( std::array< T, N > & arr ) span_noexcept -{ - return span(N)>( arr ); -} - -template< class T, std::size_t N > -inline span_constexpr span< const T, static_cast(N) > -make_span( std::array< T, N > const & arr ) span_noexcept -{ - return span(N)>( arr ); -} - -#endif // span_HAVE( ARRAY ) - -#if span_USES_STD_SPAN - -template< class Container, class EP = decltype( std::data(std::declval())) > -inline span_constexpr auto -make_span( Container & cont ) span_noexcept -> span< typename std::remove_pointer::type > -{ - return span< typename std::remove_pointer::type >( cont ); -} - -template< class Container, class EP = decltype( std::data(std::declval())) > -inline span_constexpr auto -make_span( Container const & cont ) span_noexcept -> span< const typename std::remove_pointer::type > -{ - return span< const typename std::remove_pointer::type >( cont ); -} - -#elif span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) && span_HAVE( AUTO ) - -template< class Container, class EP = decltype( std17::data(std::declval())) > -inline span_constexpr auto -make_span( Container & cont ) span_noexcept -> span< typename std::remove_pointer::type > -{ - return span< typename std::remove_pointer::type >( cont ); -} - -template< class Container, class EP = decltype( std17::data(std::declval())) > -inline span_constexpr auto -make_span( Container const & cont ) span_noexcept -> span< const typename std::remove_pointer::type > -{ - return span< const typename std::remove_pointer::type >( cont ); -} - -#else - -template< class T > -inline span_constexpr span -make_span( span spn ) span_noexcept -{ - return spn; -} - -template< class T, class Allocator > -inline span_constexpr span -make_span( std::vector & cont ) span_noexcept -{ - return span( with_container, cont ); -} - -template< class T, class Allocator > -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< class Container > -inline span_constexpr span -make_span( with_container_t, Container & cont ) span_noexcept -{ - return span< typename Container::value_type >( with_container, cont ); -} - -template< class Container > -inline span_constexpr span -make_span( with_container_t, Container const & cont ) span_noexcept -{ - return span< const typename Container::value_type >( 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< extent_t Count, class T, extent_t Extent > -span_constexpr span -first( span spn ) -{ - return spn.template first(); -} - -template< class T, extent_t Extent > -span_constexpr span -first( span spn, size_t count ) -{ - return spn.first( count ); -} - -template< extent_t Count, class T, extent_t Extent > -span_constexpr span -last( span spn ) -{ - return spn.template last(); -} - -template< class T, extent_t Extent > -span_constexpr span -last( span spn, size_t count ) -{ - return spn.last( count ); -} - -template< size_t Offset, extent_t Count, class T, extent_t Extent > -span_constexpr span -subspan( span spn ) -{ - return spn.template subspan(); -} - -template< class T, extent_t Extent > -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< extent_t Count, class T > -span_constexpr auto -first( T & t ) -> decltype( make_span(t).template first() ) -{ - return make_span( t ).template first(); -} - -template< class T > -span_constexpr auto -first( T & t, size_t count ) -> decltype( make_span(t).first(count) ) -{ - return make_span( t ).first( count ); -} - -template< extent_t Count, class T > -span_constexpr auto -last( T & t ) -> decltype( make_span(t).template last() ) -{ - return make_span(t).template last(); -} - -template< class T > -span_constexpr auto -last( T & t, extent_t count ) -> decltype( make_span(t).last(count) ) -{ - return make_span( t ).last( count ); -} - -template< size_t Offset, extent_t Count = dynamic_extent, class T > -span_constexpr auto -subspan( T & t ) -> decltype( make_span(t).template subspan() ) -{ - return make_span( t ).template subspan(); -} - -template< class T > -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 span_lite -} // namespace nonstd - -// 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< class T > -inline span_constexpr auto -byte_span( T & t ) span_noexcept -> span< std17::byte, span_sizeof(T) > -{ - return span< std17::byte, span_sizeof(t) >( reinterpret_cast< std17::byte * >( &t ), span_sizeof(T) ); -} - -template< class T > -inline span_constexpr auto -byte_span( T const & t ) span_noexcept -> span< const std17::byte, span_sizeof(T) > -{ - return span< const std17::byte, span_sizeof(t) >( reinterpret_cast< std17::byte const * >( &t ), span_sizeof(T) ); -} - -} // namespace span_lite -} // namespace nonstd - -// 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< std::size_t I, typename T > - using tuple_element_t = typename tuple_element::type; -} -#else -namespace std { - template< typename T > - class tuple_size; /*undefined*/ - - template< std::size_t I, typename T > - class tuple_element; /* undefined */ -} -#endif // span_CPP14_OR_GREATER - -namespace std { - -// 26.7.X Tuple interface - -// std::tuple_size<>: - -template< typename ElementType, nonstd::span_lite::extent_t Extent > -class tuple_size< nonstd::span > : public integral_constant(Extent)> {}; - -// std::tuple_size<>: Leave undefined for dynamic extent: - -template< typename ElementType > -class tuple_size< nonstd::span >; - -// std::tuple_element<>: - -template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent > -class tuple_element< I, nonstd::span > -{ -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< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent > -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< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent > -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