зеркало из https://github.com/microsoft/STL.git
Merge branch 'main' into merge-flat_map
This commit is contained in:
Коммит
4a24161807
10
README.md
10
README.md
|
@ -141,7 +141,7 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem
|
|||
|
||||
# How To Build With The Visual Studio IDE
|
||||
|
||||
1. Install Visual Studio 2022 17.12 Preview 2 or later.
|
||||
1. Install Visual Studio 2022 17.12 Preview 3 or later.
|
||||
* Select "Windows 11 SDK (10.0.22621.0)" in the VS Installer.
|
||||
* Select "MSVC v143 - VS 2022 C++ ARM64/ARM64EC build tools (Latest)" in the VS Installer
|
||||
if you would like to build the ARM64/ARM64EC target.
|
||||
|
@ -150,7 +150,7 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem
|
|||
* We recommend selecting "C++ CMake tools for Windows" in the VS Installer.
|
||||
This will ensure that you're using supported versions of CMake and Ninja.
|
||||
* Otherwise, install [CMake][] 3.29.0 or later, and [Ninja][] 1.12.1 or later.
|
||||
* Make sure [Python][] 3.12 or later is available to CMake.
|
||||
* Make sure [Python][] 3.13 or later is available to CMake.
|
||||
2. Open Visual Studio, and choose the "Clone or check out code" option. Enter the URL of this repository,
|
||||
`https://github.com/microsoft/STL`.
|
||||
3. Open a terminal in the IDE with `` Ctrl + ` `` (by default) or press on "View" in the top bar, and then "Terminal".
|
||||
|
@ -160,7 +160,7 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem
|
|||
|
||||
# How To Build With A Native Tools Command Prompt
|
||||
|
||||
1. Install Visual Studio 2022 17.12 Preview 2 or later.
|
||||
1. Install Visual Studio 2022 17.12 Preview 3 or later.
|
||||
* Select "Windows 11 SDK (10.0.22621.0)" in the VS Installer.
|
||||
* Select "MSVC v143 - VS 2022 C++ ARM64/ARM64EC build tools (Latest)" in the VS Installer
|
||||
if you would like to build the ARM64/ARM64EC target.
|
||||
|
@ -169,7 +169,7 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem
|
|||
* We recommend selecting "C++ CMake tools for Windows" in the VS Installer.
|
||||
This will ensure that you're using supported versions of CMake and Ninja.
|
||||
* Otherwise, install [CMake][] 3.29.0 or later, and [Ninja][] 1.12.1 or later.
|
||||
* Make sure [Python][] 3.12 or later is available to CMake.
|
||||
* Make sure [Python][] 3.13 or later is available to CMake.
|
||||
2. Open a command prompt.
|
||||
3. Change directories to a location where you'd like a clone of this STL repository.
|
||||
4. `git clone https://github.com/microsoft/STL.git --recurse-submodules`
|
||||
|
@ -262,7 +262,7 @@ C:\Users\username\Desktop>dumpbin /DEPENDENTS .\example.exe | findstr msvcp
|
|||
# How To Run The Tests With A Native Tools Command Prompt
|
||||
|
||||
1. Follow either [How To Build With A Native Tools Command Prompt][] or [How To Build With The Visual Studio IDE][].
|
||||
2. Acquire [Python][] 3.12 or newer and have it on the `PATH` (or run it directly using its absolute or relative path).
|
||||
2. Acquire [Python][] 3.13 or newer and have it on the `PATH` (or run it directly using its absolute or relative path).
|
||||
3. Have LLVM's `bin` directory on the `PATH` (so `clang-cl.exe` is available).
|
||||
* We recommend selecting "C++ Clang tools for Windows" in the VS Installer. This will automatically add LLVM to the
|
||||
`PATH` of the x86 and x64 Native Tools Command Prompts, and will ensure that you're using a supported version.
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
variables:
|
||||
- name: poolName
|
||||
value: 'StlBuild-2024-09-10T1506-Pool'
|
||||
value: 'StlBuild-2024-10-15T1118-Pool'
|
||||
readonly: true
|
||||
- name: poolDemands
|
||||
value: 'EnableSpotVM -equals false'
|
||||
|
|
|
@ -43,7 +43,7 @@ foreach ($workload in $VisualStudioWorkloads) {
|
|||
$PowerShellUrl = 'https://github.com/PowerShell/PowerShell/releases/download/v7.4.5/PowerShell-7.4.5-win-x64.msi'
|
||||
$PowerShellArgs = @('/quiet', '/norestart')
|
||||
|
||||
$PythonUrl = 'https://www.python.org/ftp/python/3.12.6/python-3.12.6-amd64.exe'
|
||||
$PythonUrl = 'https://www.python.org/ftp/python/3.13.0/python-3.13.0-amd64.exe'
|
||||
$PythonArgs = @('/quiet', 'InstallAllUsers=1', 'PrependPath=1', 'CompileAll=1', 'Include_doc=0')
|
||||
|
||||
$CudaUrl = 'https://developer.download.nvidia.com/compute/cuda/12.4.0/local_installers/cuda_12.4.0_551.61_windows.exe'
|
||||
|
|
|
@ -106,6 +106,7 @@ function(add_benchmark name)
|
|||
target_link_libraries(benchmark-${name} PRIVATE benchmark::benchmark)
|
||||
endfunction()
|
||||
|
||||
add_benchmark(bitset_from_string src/bitset_from_string.cpp)
|
||||
add_benchmark(bitset_to_string src/bitset_to_string.cpp)
|
||||
add_benchmark(efficient_nonlocking_print src/efficient_nonlocking_print.cpp)
|
||||
add_benchmark(find_and_count src/find_and_count.cpp)
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#include <array>
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <bitset>
|
||||
#include <cstddef>
|
||||
#include <random>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
template <size_t N, class charT, size_t Min_length>
|
||||
auto random_digits_init() {
|
||||
mt19937_64 rnd{};
|
||||
uniform_int_distribution<> dis('0', '1');
|
||||
|
||||
constexpr size_t number_of_bitsets = (Min_length + N - 1) / N;
|
||||
static_assert(number_of_bitsets != 0);
|
||||
|
||||
constexpr size_t actual_size = number_of_bitsets * (N + 1); // +1 for \0
|
||||
|
||||
array<charT, actual_size> result;
|
||||
|
||||
for (size_t i = 0; i < actual_size; ++i) {
|
||||
if (i % (N + 1) == N) {
|
||||
result[i] = charT{'\0'}; // write null terminators
|
||||
} else {
|
||||
result[i] = static_cast<charT>(dis(rnd)); // fill random digits
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
enum class length_type : bool { char_count, null_term };
|
||||
|
||||
template <size_t N, class charT>
|
||||
const auto random_digits = random_digits_init<N, charT, 2048>();
|
||||
|
||||
template <length_type Length, size_t N, class charT>
|
||||
void BM_bitset_from_string(benchmark::State& state) {
|
||||
const auto& digit_array = random_digits<N, charT>;
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(digit_array);
|
||||
const auto arr_data = digit_array.data();
|
||||
const auto arr_size = digit_array.size();
|
||||
for (size_t pos = 0; pos != arr_size; pos += N + 1) {
|
||||
if constexpr (Length == length_type::char_count) {
|
||||
bitset<N> bs(arr_data + pos, N);
|
||||
benchmark::DoNotOptimize(bs);
|
||||
} else {
|
||||
bitset<N> bs(arr_data + pos);
|
||||
benchmark::DoNotOptimize(bs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
BENCHMARK(BM_bitset_from_string<length_type::char_count, 15, char>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::char_count, 16, char>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::char_count, 36, char>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::char_count, 64, char>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::char_count, 512, char>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::char_count, 2048, char>);
|
||||
|
||||
BENCHMARK(BM_bitset_from_string<length_type::char_count, 15, wchar_t>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::char_count, 16, wchar_t>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::char_count, 36, wchar_t>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::char_count, 64, wchar_t>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::char_count, 512, wchar_t>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::char_count, 2048, wchar_t>);
|
||||
|
||||
BENCHMARK(BM_bitset_from_string<length_type::null_term, 15, char>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::null_term, 16, char>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::null_term, 36, char>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::null_term, 64, char>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::null_term, 512, char>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::null_term, 2048, char>);
|
||||
|
||||
BENCHMARK(BM_bitset_from_string<length_type::null_term, 15, wchar_t>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::null_term, 16, wchar_t>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::null_term, 36, wchar_t>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::null_term, 64, wchar_t>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::null_term, 512, wchar_t>);
|
||||
BENCHMARK(BM_bitset_from_string<length_type::null_term, 2048, wchar_t>);
|
||||
|
||||
BENCHMARK_MAIN();
|
|
@ -5,7 +5,9 @@
|
|||
#include <benchmark/benchmark.h>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
@ -13,19 +15,28 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
enum class AlgType : bool { std_func, str_member };
|
||||
enum class AlgType { std_func, str_member_first, str_member_last };
|
||||
|
||||
template <AlgType Alg, class T, T Start = T{'a'}>
|
||||
template <AlgType Alg, class T, T Start = T{'!'}>
|
||||
void bm(benchmark::State& state) {
|
||||
const size_t Pos = static_cast<size_t>(state.range(0));
|
||||
const size_t NSize = static_cast<size_t>(state.range(1));
|
||||
const size_t HSize = Pos * 2;
|
||||
const size_t Which = 0;
|
||||
|
||||
using container = conditional_t<Alg == AlgType::str_member, basic_string<T>, vector<T>>;
|
||||
using container = conditional_t<Alg == AlgType::std_func, vector<T>, basic_string<T>>;
|
||||
|
||||
container h(HSize, T{'.'});
|
||||
constexpr T HaystackFiller{' '};
|
||||
static_assert(HaystackFiller < Start, "The following iota() should not produce the haystack filler.");
|
||||
|
||||
container h(HSize, HaystackFiller);
|
||||
container n(NSize, T{0});
|
||||
|
||||
if (NSize - 1 > static_cast<size_t>(numeric_limits<T>::max()) - static_cast<size_t>(Start)) {
|
||||
puts("ERROR: The following iota() would overflow.");
|
||||
abort();
|
||||
}
|
||||
|
||||
iota(n.begin(), n.end(), Start);
|
||||
|
||||
if (Pos >= HSize || Which >= NSize) {
|
||||
|
@ -37,8 +48,10 @@ void bm(benchmark::State& state) {
|
|||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(h);
|
||||
benchmark::DoNotOptimize(n);
|
||||
if constexpr (Alg == AlgType::str_member) {
|
||||
benchmark::DoNotOptimize(h.find_first_of(n.data(), 0, n.size()));
|
||||
if constexpr (Alg == AlgType::str_member_first) {
|
||||
benchmark::DoNotOptimize(h.find_first_of(n));
|
||||
} else if constexpr (Alg == AlgType::str_member_last) {
|
||||
benchmark::DoNotOptimize(h.find_last_of(n));
|
||||
} else {
|
||||
benchmark::DoNotOptimize(find_first_of(h.begin(), h.end(), n.begin(), n.end()));
|
||||
}
|
||||
|
@ -46,8 +59,8 @@ void bm(benchmark::State& state) {
|
|||
}
|
||||
|
||||
void common_args(auto bm) {
|
||||
bm->Args({2, 3})->Args({7, 4})->Args({9, 3})->Args({22, 5})->Args({58, 2});
|
||||
bm->Args({102, 4})->Args({325, 1})->Args({1011, 11})->Args({1502, 23})->Args({3056, 7});
|
||||
bm->Args({2, 3})->Args({7, 4})->Args({9, 3})->Args({22, 5})->Args({58, 2})->Args({102, 4});
|
||||
bm->Args({325, 1})->Args({400, 50})->Args({1011, 11})->Args({1502, 23})->Args({3056, 7});
|
||||
}
|
||||
|
||||
BENCHMARK(bm<AlgType::std_func, uint8_t>)->Apply(common_args);
|
||||
|
@ -55,8 +68,14 @@ BENCHMARK(bm<AlgType::std_func, uint16_t>)->Apply(common_args);
|
|||
BENCHMARK(bm<AlgType::std_func, uint32_t>)->Apply(common_args);
|
||||
BENCHMARK(bm<AlgType::std_func, uint64_t>)->Apply(common_args);
|
||||
|
||||
BENCHMARK(bm<AlgType::str_member, char>)->Apply(common_args);
|
||||
BENCHMARK(bm<AlgType::str_member, wchar_t>)->Apply(common_args);
|
||||
BENCHMARK(bm<AlgType::str_member, wchar_t, L'\x03B1'>)->Apply(common_args);
|
||||
BENCHMARK(bm<AlgType::str_member_first, char>)->Apply(common_args);
|
||||
BENCHMARK(bm<AlgType::str_member_first, wchar_t>)->Apply(common_args);
|
||||
BENCHMARK(bm<AlgType::str_member_first, wchar_t, L'\x03B1'>)->Apply(common_args);
|
||||
BENCHMARK(bm<AlgType::str_member_first, char32_t>)->Apply(common_args);
|
||||
BENCHMARK(bm<AlgType::str_member_first, char32_t, U'\x03B1'>)->Apply(common_args);
|
||||
|
||||
BENCHMARK(bm<AlgType::str_member_last, char>)->Apply(common_args);
|
||||
BENCHMARK(bm<AlgType::str_member_last, wchar_t>)->Apply(common_args);
|
||||
BENCHMARK(bm<AlgType::str_member_last, wchar_t, L'\x03B1'>)->Apply(common_args);
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <random>
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
enum class Op {
|
||||
Min,
|
||||
|
@ -20,9 +21,9 @@ enum class Op {
|
|||
|
||||
using namespace std;
|
||||
|
||||
template <class T, size_t Size, Op Operation>
|
||||
template <class T, Op Operation>
|
||||
void bm(benchmark::State& state) {
|
||||
T a[Size];
|
||||
vector<T> a(static_cast<size_t>(state.range()));
|
||||
|
||||
mt19937 gen(84710);
|
||||
|
||||
|
@ -35,6 +36,8 @@ void bm(benchmark::State& state) {
|
|||
}
|
||||
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(a);
|
||||
|
||||
if constexpr (Operation == Op::Min) {
|
||||
benchmark::DoNotOptimize(ranges::min_element(a));
|
||||
} else if constexpr (Operation == Op::Max) {
|
||||
|
@ -51,75 +54,81 @@ void bm(benchmark::State& state) {
|
|||
}
|
||||
}
|
||||
|
||||
BENCHMARK(bm<uint8_t, 8021, Op::Min>);
|
||||
BENCHMARK(bm<uint8_t, 8021, Op::Max>);
|
||||
BENCHMARK(bm<uint8_t, 8021, Op::Both>);
|
||||
BENCHMARK(bm<uint8_t, 8021, Op::Min_val>);
|
||||
BENCHMARK(bm<uint8_t, 8021, Op::Max_val>);
|
||||
BENCHMARK(bm<uint8_t, 8021, Op::Both_val>);
|
||||
template <size_t ElementSize>
|
||||
void common_arg(auto bm) {
|
||||
bm->Arg(8021);
|
||||
// AVX tail tests
|
||||
bm->Arg(63 / ElementSize);
|
||||
}
|
||||
|
||||
BENCHMARK(bm<uint16_t, 8021, Op::Min>);
|
||||
BENCHMARK(bm<uint16_t, 8021, Op::Max>);
|
||||
BENCHMARK(bm<uint16_t, 8021, Op::Both>);
|
||||
BENCHMARK(bm<uint16_t, 8021, Op::Min_val>);
|
||||
BENCHMARK(bm<uint16_t, 8021, Op::Max_val>);
|
||||
BENCHMARK(bm<uint16_t, 8021, Op::Both_val>);
|
||||
BENCHMARK(bm<uint8_t, Op::Min>)->Apply(common_arg<1>);
|
||||
BENCHMARK(bm<uint8_t, Op::Max>)->Apply(common_arg<1>);
|
||||
BENCHMARK(bm<uint8_t, Op::Both>)->Apply(common_arg<1>);
|
||||
BENCHMARK(bm<uint8_t, Op::Min_val>)->Apply(common_arg<1>);
|
||||
BENCHMARK(bm<uint8_t, Op::Max_val>)->Apply(common_arg<1>);
|
||||
BENCHMARK(bm<uint8_t, Op::Both_val>)->Apply(common_arg<1>);
|
||||
|
||||
BENCHMARK(bm<uint32_t, 8021, Op::Min>);
|
||||
BENCHMARK(bm<uint32_t, 8021, Op::Max>);
|
||||
BENCHMARK(bm<uint32_t, 8021, Op::Both>);
|
||||
BENCHMARK(bm<uint32_t, 8021, Op::Min_val>);
|
||||
BENCHMARK(bm<uint32_t, 8021, Op::Max_val>);
|
||||
BENCHMARK(bm<uint32_t, 8021, Op::Both_val>);
|
||||
BENCHMARK(bm<uint16_t, Op::Min>)->Apply(common_arg<2>);
|
||||
BENCHMARK(bm<uint16_t, Op::Max>)->Apply(common_arg<2>);
|
||||
BENCHMARK(bm<uint16_t, Op::Both>)->Apply(common_arg<2>);
|
||||
BENCHMARK(bm<uint16_t, Op::Min_val>)->Apply(common_arg<2>);
|
||||
BENCHMARK(bm<uint16_t, Op::Max_val>)->Apply(common_arg<2>);
|
||||
BENCHMARK(bm<uint16_t, Op::Both_val>)->Apply(common_arg<2>);
|
||||
|
||||
BENCHMARK(bm<uint64_t, 8021, Op::Min>);
|
||||
BENCHMARK(bm<uint64_t, 8021, Op::Max>);
|
||||
BENCHMARK(bm<uint64_t, 8021, Op::Both>);
|
||||
BENCHMARK(bm<uint64_t, 8021, Op::Min_val>);
|
||||
BENCHMARK(bm<uint64_t, 8021, Op::Max_val>);
|
||||
BENCHMARK(bm<uint64_t, 8021, Op::Both_val>);
|
||||
BENCHMARK(bm<uint32_t, Op::Min>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<uint32_t, Op::Max>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<uint32_t, Op::Both>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<uint32_t, Op::Min_val>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<uint32_t, Op::Max_val>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<uint32_t, Op::Both_val>)->Apply(common_arg<4>);
|
||||
|
||||
BENCHMARK(bm<int8_t, 8021, Op::Min>);
|
||||
BENCHMARK(bm<int8_t, 8021, Op::Max>);
|
||||
BENCHMARK(bm<int8_t, 8021, Op::Both>);
|
||||
BENCHMARK(bm<int8_t, 8021, Op::Min_val>);
|
||||
BENCHMARK(bm<int8_t, 8021, Op::Max_val>);
|
||||
BENCHMARK(bm<int8_t, 8021, Op::Both_val>);
|
||||
BENCHMARK(bm<uint64_t, Op::Min>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<uint64_t, Op::Max>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<uint64_t, Op::Both>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<uint64_t, Op::Min_val>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<uint64_t, Op::Max_val>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<uint64_t, Op::Both_val>)->Apply(common_arg<8>);
|
||||
|
||||
BENCHMARK(bm<int16_t, 8021, Op::Min>);
|
||||
BENCHMARK(bm<int16_t, 8021, Op::Max>);
|
||||
BENCHMARK(bm<int16_t, 8021, Op::Both>);
|
||||
BENCHMARK(bm<int16_t, 8021, Op::Min_val>);
|
||||
BENCHMARK(bm<int16_t, 8021, Op::Max_val>);
|
||||
BENCHMARK(bm<int16_t, 8021, Op::Both_val>);
|
||||
BENCHMARK(bm<int8_t, Op::Min>)->Apply(common_arg<1>);
|
||||
BENCHMARK(bm<int8_t, Op::Max>)->Apply(common_arg<1>);
|
||||
BENCHMARK(bm<int8_t, Op::Both>)->Apply(common_arg<1>);
|
||||
BENCHMARK(bm<int8_t, Op::Min_val>)->Apply(common_arg<1>);
|
||||
BENCHMARK(bm<int8_t, Op::Max_val>)->Apply(common_arg<1>);
|
||||
BENCHMARK(bm<int8_t, Op::Both_val>)->Apply(common_arg<1>);
|
||||
|
||||
BENCHMARK(bm<int32_t, 8021, Op::Min>);
|
||||
BENCHMARK(bm<int32_t, 8021, Op::Max>);
|
||||
BENCHMARK(bm<int32_t, 8021, Op::Both>);
|
||||
BENCHMARK(bm<int32_t, 8021, Op::Min_val>);
|
||||
BENCHMARK(bm<int32_t, 8021, Op::Max_val>);
|
||||
BENCHMARK(bm<int32_t, 8021, Op::Both_val>);
|
||||
BENCHMARK(bm<int16_t, Op::Min>)->Apply(common_arg<2>);
|
||||
BENCHMARK(bm<int16_t, Op::Max>)->Apply(common_arg<2>);
|
||||
BENCHMARK(bm<int16_t, Op::Both>)->Apply(common_arg<2>);
|
||||
BENCHMARK(bm<int16_t, Op::Min_val>)->Apply(common_arg<2>);
|
||||
BENCHMARK(bm<int16_t, Op::Max_val>)->Apply(common_arg<2>);
|
||||
BENCHMARK(bm<int16_t, Op::Both_val>)->Apply(common_arg<2>);
|
||||
|
||||
BENCHMARK(bm<int64_t, 8021, Op::Min>);
|
||||
BENCHMARK(bm<int64_t, 8021, Op::Max>);
|
||||
BENCHMARK(bm<int64_t, 8021, Op::Both>);
|
||||
BENCHMARK(bm<int64_t, 8021, Op::Min_val>);
|
||||
BENCHMARK(bm<int64_t, 8021, Op::Max_val>);
|
||||
BENCHMARK(bm<int64_t, 8021, Op::Both_val>);
|
||||
BENCHMARK(bm<int32_t, Op::Min>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<int32_t, Op::Max>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<int32_t, Op::Both>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<int32_t, Op::Min_val>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<int32_t, Op::Max_val>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<int32_t, Op::Both_val>)->Apply(common_arg<4>);
|
||||
|
||||
BENCHMARK(bm<float, 8021, Op::Min>);
|
||||
BENCHMARK(bm<float, 8021, Op::Max>);
|
||||
BENCHMARK(bm<float, 8021, Op::Both>);
|
||||
BENCHMARK(bm<float, 8021, Op::Min_val>);
|
||||
BENCHMARK(bm<float, 8021, Op::Max_val>);
|
||||
BENCHMARK(bm<float, 8021, Op::Both_val>);
|
||||
BENCHMARK(bm<int64_t, Op::Min>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<int64_t, Op::Max>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<int64_t, Op::Both>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<int64_t, Op::Min_val>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<int64_t, Op::Max_val>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<int64_t, Op::Both_val>)->Apply(common_arg<8>);
|
||||
|
||||
BENCHMARK(bm<double, 8021, Op::Min>);
|
||||
BENCHMARK(bm<double, 8021, Op::Max>);
|
||||
BENCHMARK(bm<double, 8021, Op::Both>);
|
||||
BENCHMARK(bm<double, 8021, Op::Min_val>);
|
||||
BENCHMARK(bm<double, 8021, Op::Max_val>);
|
||||
BENCHMARK(bm<double, 8021, Op::Both_val>);
|
||||
BENCHMARK(bm<float, Op::Min>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<float, Op::Max>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<float, Op::Both>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<float, Op::Min_val>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<float, Op::Max_val>)->Apply(common_arg<4>);
|
||||
BENCHMARK(bm<float, Op::Both_val>)->Apply(common_arg<4>);
|
||||
|
||||
BENCHMARK(bm<double, Op::Min>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<double, Op::Max>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<double, Op::Both>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<double, Op::Min_val>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<double, Op::Max_val>)->Apply(common_arg<8>);
|
||||
BENCHMARK(bm<double, Op::Both_val>)->Apply(common_arg<8>);
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
|
|
|
@ -20,6 +20,7 @@ set(HEADERS
|
|||
${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_ostream.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_print.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_ranges_to.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_ranges_tuple_formatter.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_sanitizer_annotate_container.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_string_view.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_system_error_abi.hpp
|
||||
|
|
|
@ -24,7 +24,10 @@
|
|||
#include <mbctype.h>
|
||||
#endif // !defined(_MSVC_TESTING_NVCC)
|
||||
|
||||
#ifndef _SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING
|
||||
#define _SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING
|
||||
#endif // !defined(_SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING)
|
||||
|
||||
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
|
||||
#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
|
||||
#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
|
||||
|
|
|
@ -123,6 +123,8 @@ struct _Dynamic_format_specs : _Basic_format_specs<_CharT> {
|
|||
int _Dynamic_precision_index = -1;
|
||||
};
|
||||
|
||||
[[noreturn]] inline void _Throw_format_error(const char* _Message);
|
||||
|
||||
_EXPORT_STD template <class _CharT>
|
||||
class basic_format_parse_context;
|
||||
|
||||
|
@ -398,6 +400,45 @@ constexpr bool enable_nonlocking_formatter_optimization<pair<_Ty1, _Ty2>> =
|
|||
template <class... _Ts>
|
||||
constexpr bool enable_nonlocking_formatter_optimization<tuple<_Ts...>> =
|
||||
(enable_nonlocking_formatter_optimization<_Ts> && ...);
|
||||
|
||||
template <class _CharT>
|
||||
struct _Fill_align_and_width_specs {
|
||||
int _Width = -1;
|
||||
int _Dynamic_width_index = -1;
|
||||
_Fmt_align _Alignment = _Fmt_align::_None;
|
||||
uint8_t _Fill_length = 1;
|
||||
// At most one codepoint (so one char32_t or four utf-8 char8_t).
|
||||
_CharT _Fill[4 / sizeof(_CharT)]{' '};
|
||||
};
|
||||
|
||||
// TRANSITION, VSO-1236041: Avoid declaring and defining member functions in different headers.
|
||||
template <class _CharT, class _Pc>
|
||||
_NODISCARD constexpr _Pc::iterator _Fill_align_and_width_formatter_parse(
|
||||
_Fill_align_and_width_specs<_CharT>& _Specs, _Pc& _Parse_ctx);
|
||||
|
||||
template <class _CharT, class _FormatContext, class _Func>
|
||||
_NODISCARD _FormatContext::iterator _Fill_align_and_width_formatter_format(
|
||||
const _Fill_align_and_width_specs<_CharT>& _Specs, _FormatContext& _Format_ctx, int _Width,
|
||||
_Fmt_align _Default_align, _Func&& _Fn);
|
||||
|
||||
template <class _CharT>
|
||||
struct _Fill_align_and_width_formatter {
|
||||
public:
|
||||
template <class _ParseContext = basic_format_parse_context<_CharT>> // improves throughput, see GH-5003
|
||||
_NODISCARD constexpr _ParseContext::iterator _Parse(type_identity_t<_ParseContext&> _Parse_ctx) {
|
||||
return _STD _Fill_align_and_width_formatter_parse(_Specs, _Parse_ctx);
|
||||
}
|
||||
|
||||
template <class _FormatContext, class _Func>
|
||||
_NODISCARD constexpr auto _Format(
|
||||
_FormatContext& _Format_ctx, const int _Width, _Fmt_align _Default_align, _Func&& _Fn) const {
|
||||
return _STD _Fill_align_and_width_formatter_format(
|
||||
_Specs, _Format_ctx, _Width, _Default_align, _STD forward<_Func>(_Fn));
|
||||
}
|
||||
|
||||
private:
|
||||
_Fill_align_and_width_specs<_CharT> _Specs;
|
||||
};
|
||||
#endif // _HAS_CXX23
|
||||
_STD_END
|
||||
|
||||
|
|
|
@ -283,7 +283,11 @@ struct _Iter_traits_category4<false> {
|
|||
|
||||
template <class _It>
|
||||
concept _Cpp17_random_delta =
|
||||
#if defined(__CUDACC__) && !defined(__clang__) // TRANSITION, CUDA 12.5
|
||||
totally_ordered<_It> && requires(_It __i, typename incrementable_traits<_It>::difference_type __n) {
|
||||
#else // ^^^ workaround / no workaround vvv
|
||||
totally_ordered<_It> && requires(_It __i, incrementable_traits<_It>::difference_type __n) {
|
||||
#endif // ^^^ no workaround ^^^
|
||||
{ __i += __n } -> same_as<_It&>;
|
||||
{ __i -= __n } -> same_as<_It&>;
|
||||
{ __i + __n } -> same_as<_It>;
|
||||
|
@ -381,7 +385,7 @@ constexpr bool _Integer_class = requires {
|
|||
};
|
||||
|
||||
template <class _Ty>
|
||||
concept _Integer_like = _Is_nonbool_integral<remove_cv_t<_Ty>> || _Integer_class<_Ty>;
|
||||
concept _Integer_like = _Is_nonbool_integral<_Ty> || _Integer_class<_Ty>;
|
||||
|
||||
template <class _Ty>
|
||||
concept _Signed_integer_like = _Integer_like<_Ty> && static_cast<_Ty>(-1) < static_cast<_Ty>(0);
|
||||
|
@ -438,11 +442,6 @@ _EXPORT_STD using ranges::get;
|
|||
template <class _It, class _Se, ranges::subrange_kind _Ki>
|
||||
constexpr bool _Is_subrange_v<ranges::subrange<_It, _Se, _Ki>> = true;
|
||||
|
||||
#if _HAS_CXX23
|
||||
template <class _It, class _Se, ranges::subrange_kind _Ki>
|
||||
constexpr bool _Tuple_like_impl<ranges::subrange<_It, _Se, _Ki>> = true;
|
||||
#endif // _HAS_CXX23
|
||||
|
||||
template <class _It, class _Se, ranges::subrange_kind _Ki>
|
||||
struct tuple_size<ranges::subrange<_It, _Se, _Ki>> : integral_constant<size_t, 2> {};
|
||||
|
||||
|
@ -498,6 +497,9 @@ struct iterator_traits : _Iterator_traits_base<_Iter> {}; // get traits from ite
|
|||
|
||||
template <class _Ty>
|
||||
struct iterator_traits<_Ty*> : _Iterator_traits_pointer_base<_Ty> {}; // get traits from pointer, if possible
|
||||
|
||||
template <class _Ty>
|
||||
constexpr bool _Integer_like = _Is_nonbool_integral<_Ty>;
|
||||
#endif // ^^^ !_HAS_CXX20 ^^^
|
||||
|
||||
_INLINE_VAR constexpr auto _Meta_npos = ~size_t{0};
|
||||
|
|
|
@ -1180,18 +1180,14 @@ namespace ranges {
|
|||
|
||||
template <input_range _Rng>
|
||||
struct _Phony_input_iterator {
|
||||
using iterator_category = input_iterator_tag;
|
||||
using value_type = range_value_t<_Rng>;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = add_pointer_t<range_reference_t<_Rng>>;
|
||||
using reference = range_reference_t<_Rng>;
|
||||
|
||||
reference operator*() const;
|
||||
pointer operator->() const;
|
||||
using value_type = range_value_t<_Rng>;
|
||||
using difference_type = ptrdiff_t;
|
||||
|
||||
// These member functions are never defined:
|
||||
range_reference_t<_Rng> operator*() const;
|
||||
add_pointer_t<range_reference_t<_Rng>> operator->() const;
|
||||
_Phony_input_iterator& operator++();
|
||||
_Phony_input_iterator operator++(int);
|
||||
|
||||
bool operator==(const _Phony_input_iterator&) const;
|
||||
};
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -19,6 +19,42 @@ _STL_DISABLE_CLANG_WARNINGS
|
|||
#pragma push_macro("new")
|
||||
#undef new
|
||||
|
||||
#if _USE_STD_VECTOR_ALGORITHMS
|
||||
extern "C" {
|
||||
// The "noalias" attribute tells the compiler optimizer that pointers going into these hand-vectorized algorithms
|
||||
// won't be stored beyond the lifetime of the function, and that the function will only reference arrays denoted by
|
||||
// those pointers. The optimizer also assumes in that case that a pointer parameter is not returned to the caller via
|
||||
// the return value, so functions using "noalias" must usually return void. This attribute is valuable because these
|
||||
// functions are in native code objects that the compiler cannot analyze. In the absence of the noalias attribute, the
|
||||
// compiler has to assume that the denoted arrays are "globally address taken", and that any later calls to
|
||||
// unanalyzable routines may modify those arrays.
|
||||
|
||||
__declspec(noalias) size_t __stdcall __std_find_last_of_trivial_pos_1(
|
||||
const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept;
|
||||
__declspec(noalias) size_t __stdcall __std_find_last_of_trivial_pos_2(
|
||||
const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept;
|
||||
|
||||
} // extern "C"
|
||||
|
||||
_STD_BEGIN
|
||||
|
||||
template <class _Ty1, class _Ty2>
|
||||
size_t _Find_last_of_pos_vectorized(const _Ty1* const _Haystack, const size_t _Haystack_length,
|
||||
const _Ty2* const _Needle, const size_t _Needle_length) noexcept {
|
||||
_STL_INTERNAL_STATIC_ASSERT(sizeof(_Ty1) == sizeof(_Ty2));
|
||||
if constexpr (sizeof(_Ty1) == 1) {
|
||||
return ::__std_find_last_of_trivial_pos_1(_Haystack, _Haystack_length, _Needle, _Needle_length);
|
||||
} else if constexpr (sizeof(_Ty1) == 2) {
|
||||
return ::__std_find_last_of_trivial_pos_2(_Haystack, _Haystack_length, _Needle, _Needle_length);
|
||||
} else {
|
||||
_STL_INTERNAL_STATIC_ASSERT(false); // unexpected size
|
||||
}
|
||||
}
|
||||
|
||||
_STD_END
|
||||
|
||||
#endif // _USE_STD_VECTOR_ALGORITHMS
|
||||
|
||||
_STD_BEGIN
|
||||
#ifdef __clang__
|
||||
#define _HAS_MEMCPY_MEMMOVE_INTRINSICS 1
|
||||
|
@ -628,38 +664,39 @@ constexpr size_t _Traits_rfind(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits
|
|||
return (_STD min)(_Start_at, _Hay_size); // empty string always matches
|
||||
}
|
||||
|
||||
if (_Needle_size <= _Hay_size) { // room for match, look for it
|
||||
for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - _Needle_size);; --_Match_try) {
|
||||
if (_Traits::eq(*_Match_try, *_Needle) && _Traits::compare(_Match_try, _Needle, _Needle_size) == 0) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
|
||||
if (_Match_try == _Haystack) {
|
||||
break; // at beginning, no more chance for match
|
||||
}
|
||||
}
|
||||
if (_Needle_size > _Hay_size) { // no room for match
|
||||
return static_cast<size_t>(-1);
|
||||
}
|
||||
|
||||
return static_cast<size_t>(-1); // no match
|
||||
for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - _Needle_size);; --_Match_try) {
|
||||
if (_Traits::eq(*_Match_try, *_Needle) && _Traits::compare(_Match_try, _Needle, _Needle_size) == 0) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
|
||||
if (_Match_try == _Haystack) {
|
||||
return static_cast<size_t>(-1); // at beginning, no more chance for match
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Traits>
|
||||
constexpr size_t _Traits_rfind_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits> _Haystack, const size_t _Hay_size,
|
||||
const size_t _Start_at, const _Traits_ch_t<_Traits> _Ch) noexcept {
|
||||
// search [_Haystack, _Haystack + _Hay_size) for _Ch before _Start_at
|
||||
if (_Hay_size != 0) { // room for match, look for it
|
||||
for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - 1);; --_Match_try) {
|
||||
if (_Traits::eq(*_Match_try, _Ch)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
|
||||
if (_Match_try == _Haystack) {
|
||||
break; // at beginning, no more chance for match
|
||||
}
|
||||
}
|
||||
if (_Hay_size == 0) { // no room for match
|
||||
return static_cast<size_t>(-1);
|
||||
}
|
||||
|
||||
return static_cast<size_t>(-1); // no match
|
||||
for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - 1);; --_Match_try) {
|
||||
if (_Traits::eq(*_Match_try, _Ch)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
|
||||
if (_Match_try == _Haystack) {
|
||||
return static_cast<size_t>(-1); // at beginning, no more chance for match
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Elem, bool = _Is_character<_Elem>::value>
|
||||
|
@ -676,7 +713,8 @@ public:
|
|||
}
|
||||
|
||||
constexpr bool _Match(const _Elem _Ch) const noexcept { // test if _Ch is in the bitmap
|
||||
return _Matches[static_cast<unsigned char>(_Ch)]; // lgtm [cpp/unclear-array-index-validation]
|
||||
// CodeQL [SM01954] This index is valid: we cast to unsigned char and the array has 256 elements.
|
||||
return _Matches[static_cast<unsigned char>(_Ch)];
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -713,133 +751,168 @@ private:
|
|||
bool _Matches[256] = {};
|
||||
};
|
||||
|
||||
template <class _Traits, bool _Special = _Is_implementation_handled_char_traits<_Traits>>
|
||||
template <class _Traits>
|
||||
constexpr size_t _Traits_find_first_of(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits> _Haystack,
|
||||
const size_t _Hay_size, const size_t _Start_at, _In_reads_(_Needle_size) const _Traits_ptr_t<_Traits> _Needle,
|
||||
const size_t _Needle_size) noexcept {
|
||||
// in [_Haystack, _Haystack + _Hay_size), look for one of [_Needle, _Needle + _Needle_size), at/after _Start_at
|
||||
if (_Needle_size != 0 && _Start_at < _Hay_size) { // room for match, look for it
|
||||
const auto _Hay_start = _Haystack + _Start_at;
|
||||
const auto _Hay_end = _Haystack + _Hay_size;
|
||||
if (_Needle_size == 0 || _Start_at >= _Hay_size) { // no match possible
|
||||
return static_cast<size_t>(-1);
|
||||
}
|
||||
|
||||
if constexpr (_Special) {
|
||||
if (!_STD _Is_constant_evaluated()) {
|
||||
using _Elem = typename _Traits::char_type;
|
||||
const auto _Hay_start = _Haystack + _Start_at;
|
||||
const auto _Hay_end = _Haystack + _Hay_size;
|
||||
|
||||
if constexpr (_Is_implementation_handled_char_traits<_Traits>) {
|
||||
if (!_STD _Is_constant_evaluated()) {
|
||||
using _Elem = typename _Traits::char_type;
|
||||
|
||||
#if _USE_STD_VECTOR_ALGORITHMS
|
||||
const bool _Try_vectorize = _Hay_size - _Start_at > _Threshold_find_first_of;
|
||||
const bool _Try_vectorize = _Hay_size - _Start_at > _Threshold_find_first_of;
|
||||
|
||||
// Additional condition for when the vectorization outperforms the table lookup
|
||||
const bool _Use_bitmap = !_Try_vectorize || (sizeof(_Elem) > 1 && sizeof(_Elem) * _Needle_size > 16);
|
||||
#else
|
||||
const bool _Use_bitmap = true;
|
||||
#endif // _USE_STD_VECTOR_ALGORITHMS
|
||||
// Additional condition for when the vectorization outperforms the table lookup
|
||||
constexpr size_t _Find_first_of_bitmap_threshold = sizeof(_Elem) == 1 ? 48 : sizeof(_Elem) == 8 ? 8 : 16;
|
||||
|
||||
if (_Use_bitmap) {
|
||||
_String_bitmap<_Elem> _Matches;
|
||||
const bool _Use_bitmap = !_Try_vectorize || _Needle_size > _Find_first_of_bitmap_threshold;
|
||||
#else // ^^^ _USE_STD_VECTOR_ALGORITHMS / !_USE_STD_VECTOR_ALGORITHMS vvv
|
||||
const bool _Use_bitmap = true;
|
||||
#endif // ^^^ !_USE_STD_VECTOR_ALGORITHMS ^^^
|
||||
|
||||
if (_Matches._Mark(_Needle, _Needle + _Needle_size)) {
|
||||
for (auto _Match_try = _Hay_start; _Match_try < _Hay_end; ++_Match_try) {
|
||||
if (_Matches._Match(*_Match_try)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
if (_Use_bitmap) {
|
||||
_String_bitmap<_Elem> _Matches;
|
||||
|
||||
if (_Matches._Mark(_Needle, _Needle + _Needle_size)) {
|
||||
for (auto _Match_try = _Hay_start; _Match_try < _Hay_end; ++_Match_try) {
|
||||
if (_Matches._Match(*_Match_try)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
return static_cast<size_t>(-1); // no match
|
||||
}
|
||||
|
||||
// couldn't put one of the characters into the bitmap, fall back to vectorized or serial algorithms
|
||||
return static_cast<size_t>(-1); // no match
|
||||
}
|
||||
|
||||
// couldn't put one of the characters into the bitmap, fall back to vectorized or serial algorithms
|
||||
}
|
||||
|
||||
#if _USE_STD_VECTOR_ALGORITHMS
|
||||
if (_Try_vectorize) {
|
||||
const _Traits_ptr_t<_Traits> _Found =
|
||||
_STD _Find_first_of_vectorized(_Hay_start, _Hay_end, _Needle, _Needle + _Needle_size);
|
||||
if (_Try_vectorize) {
|
||||
const _Traits_ptr_t<_Traits> _Found =
|
||||
_STD _Find_first_of_vectorized(_Hay_start, _Hay_end, _Needle, _Needle + _Needle_size);
|
||||
|
||||
if (_Found != _Hay_end) {
|
||||
return static_cast<size_t>(_Found - _Haystack); // found a match
|
||||
} else {
|
||||
return static_cast<size_t>(-1); // no match
|
||||
}
|
||||
if (_Found != _Hay_end) {
|
||||
return static_cast<size_t>(_Found - _Haystack); // found a match
|
||||
} else {
|
||||
return static_cast<size_t>(-1); // no match
|
||||
}
|
||||
}
|
||||
#endif // _USE_STD_VECTOR_ALGORITHMS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto _Match_try = _Hay_start; _Match_try < _Hay_end; ++_Match_try) {
|
||||
if (_Traits::find(_Needle, _Needle_size, *_Match_try)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
for (auto _Match_try = _Hay_start; _Match_try < _Hay_end; ++_Match_try) {
|
||||
if (_Traits::find(_Needle, _Needle_size, *_Match_try)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<size_t>(-1); // no match
|
||||
}
|
||||
|
||||
template <class _Traits, bool _Special = _Is_implementation_handled_char_traits<_Traits>>
|
||||
template <class _Traits>
|
||||
constexpr size_t _Traits_find_last_of(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits> _Haystack,
|
||||
const size_t _Hay_size, const size_t _Start_at, _In_reads_(_Needle_size) const _Traits_ptr_t<_Traits> _Needle,
|
||||
const size_t _Needle_size) noexcept {
|
||||
// in [_Haystack, _Haystack + _Hay_size), look for last of [_Needle, _Needle + _Needle_size), before _Start_at
|
||||
if (_Needle_size != 0 && _Hay_size != 0) { // worth searching, do it
|
||||
if constexpr (_Special) {
|
||||
_String_bitmap<typename _Traits::char_type> _Matches;
|
||||
if (!_Matches._Mark(_Needle, _Needle + _Needle_size)) { // couldn't put one of the characters into the
|
||||
// bitmap, fall back to the serial algorithm
|
||||
return _Traits_find_last_of<_Traits, false>(_Haystack, _Hay_size, _Start_at, _Needle, _Needle_size);
|
||||
}
|
||||
if (_Needle_size == 0 || _Hay_size == 0) { // not worth searching
|
||||
return static_cast<size_t>(-1);
|
||||
}
|
||||
|
||||
for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - 1);; --_Match_try) {
|
||||
if (_Matches._Match(*_Match_try)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
const auto _Hay_start = (_STD min)(_Start_at, _Hay_size - 1);
|
||||
|
||||
if constexpr (_Is_implementation_handled_char_traits<_Traits>) {
|
||||
if (!_STD _Is_constant_evaluated()) {
|
||||
using _Elem = typename _Traits::char_type;
|
||||
|
||||
bool _Use_bitmap = true;
|
||||
#if _USE_STD_VECTOR_ALGORITHMS
|
||||
bool _Try_vectorize = false;
|
||||
|
||||
if constexpr (sizeof(_Elem) <= 2) {
|
||||
_Try_vectorize = _Hay_start + 1 > _Threshold_find_first_of;
|
||||
// Additional condition for when the vectorization outperforms the table lookup
|
||||
constexpr size_t _Find_last_of_bitmap_threshold = sizeof(_Elem) == 1 ? 48 : 8;
|
||||
|
||||
_Use_bitmap = !_Try_vectorize || _Needle_size > _Find_last_of_bitmap_threshold;
|
||||
}
|
||||
#endif // _USE_STD_VECTOR_ALGORITHMS
|
||||
|
||||
if (_Use_bitmap) {
|
||||
_String_bitmap<_Elem> _Matches;
|
||||
if (_Matches._Mark(_Needle, _Needle + _Needle_size)) {
|
||||
for (auto _Match_try = _Haystack + _Hay_start;; --_Match_try) {
|
||||
if (_Matches._Match(*_Match_try)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
|
||||
if (_Match_try == _Haystack) {
|
||||
return static_cast<size_t>(-1); // at beginning, no more chance for match
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_Match_try == _Haystack) {
|
||||
break; // at beginning, no more chance for match
|
||||
}
|
||||
// couldn't put one of the characters into the bitmap, fall back to vectorized or serial algorithms
|
||||
}
|
||||
} else {
|
||||
for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - 1);; --_Match_try) {
|
||||
if (_Traits::find(_Needle, _Needle_size, *_Match_try)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
|
||||
if (_Match_try == _Haystack) {
|
||||
break; // at beginning, no more chance for match
|
||||
#if _USE_STD_VECTOR_ALGORITHMS
|
||||
if constexpr (sizeof(_Elem) <= 2) {
|
||||
if (_Try_vectorize) {
|
||||
return _STD _Find_last_of_pos_vectorized(_Haystack, _Hay_start + 1, _Needle, _Needle_size);
|
||||
}
|
||||
}
|
||||
#endif // _USE_STD_VECTOR_ALGORITHMS
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<size_t>(-1); // no match
|
||||
for (auto _Match_try = _Haystack + _Hay_start;; --_Match_try) {
|
||||
if (_Traits::find(_Needle, _Needle_size, *_Match_try)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
|
||||
if (_Match_try == _Haystack) {
|
||||
return static_cast<size_t>(-1); // at beginning, no more chance for match
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Traits, bool _Special = _Is_implementation_handled_char_traits<_Traits>>
|
||||
template <class _Traits>
|
||||
constexpr size_t _Traits_find_first_not_of(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits> _Haystack,
|
||||
const size_t _Hay_size, const size_t _Start_at, _In_reads_(_Needle_size) const _Traits_ptr_t<_Traits> _Needle,
|
||||
const size_t _Needle_size) noexcept {
|
||||
// in [_Haystack, _Haystack + _Hay_size), look for none of [_Needle, _Needle + _Needle_size), at/after _Start_at
|
||||
if (_Start_at < _Hay_size) { // room for match, look for it
|
||||
if constexpr (_Special) {
|
||||
_String_bitmap<typename _Traits::char_type> _Matches;
|
||||
if (!_Matches._Mark(_Needle, _Needle + _Needle_size)) { // couldn't put one of the characters into the
|
||||
// bitmap, fall back to the serial algorithm
|
||||
return _Traits_find_first_not_of<_Traits, false>(
|
||||
_Haystack, _Hay_size, _Start_at, _Needle, _Needle_size);
|
||||
}
|
||||
if (_Start_at >= _Hay_size) { // no room for match
|
||||
return static_cast<size_t>(-1);
|
||||
}
|
||||
|
||||
const auto _End = _Haystack + _Hay_size;
|
||||
for (auto _Match_try = _Haystack + _Start_at; _Match_try < _End; ++_Match_try) {
|
||||
const auto _Hay_start = _Haystack + _Start_at;
|
||||
const auto _Hay_end = _Haystack + _Hay_size;
|
||||
|
||||
if constexpr (_Is_implementation_handled_char_traits<_Traits>) {
|
||||
using _Elem = typename _Traits::char_type;
|
||||
_String_bitmap<_Elem> _Matches;
|
||||
if (_Matches._Mark(_Needle, _Needle + _Needle_size)) {
|
||||
for (auto _Match_try = _Hay_start; _Match_try < _Hay_end; ++_Match_try) {
|
||||
if (!_Matches._Match(*_Match_try)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const auto _End = _Haystack + _Hay_size;
|
||||
for (auto _Match_try = _Haystack + _Start_at; _Match_try < _End; ++_Match_try) {
|
||||
if (!_Traits::find(_Needle, _Needle_size, *_Match_try)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
}
|
||||
return static_cast<size_t>(-1); // no match
|
||||
}
|
||||
|
||||
// couldn't put one of the characters into the bitmap, fall back to the serial algorithm
|
||||
}
|
||||
|
||||
for (auto _Match_try = _Hay_start; _Match_try < _Hay_end; ++_Match_try) {
|
||||
if (!_Traits::find(_Needle, _Needle_size, *_Match_try)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -862,61 +935,63 @@ constexpr size_t _Traits_find_not_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_
|
|||
return static_cast<size_t>(-1); // no match
|
||||
}
|
||||
|
||||
template <class _Traits, bool _Special = _Is_implementation_handled_char_traits<_Traits>>
|
||||
template <class _Traits>
|
||||
constexpr size_t _Traits_find_last_not_of(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits> _Haystack,
|
||||
const size_t _Hay_size, const size_t _Start_at, _In_reads_(_Needle_size) const _Traits_ptr_t<_Traits> _Needle,
|
||||
const size_t _Needle_size) noexcept {
|
||||
// in [_Haystack, _Haystack + _Hay_size), look for none of [_Needle, _Needle + _Needle_size), before _Start_at
|
||||
if (_Hay_size != 0) { // worth searching, do it
|
||||
if constexpr (_Special) {
|
||||
_String_bitmap<typename _Traits::char_type> _Matches;
|
||||
if (!_Matches._Mark(_Needle, _Needle + _Needle_size)) { // couldn't put one of the characters into the
|
||||
// bitmap, fall back to the serial algorithm
|
||||
return _Traits_find_last_not_of<_Traits, false>(_Haystack, _Hay_size, _Start_at, _Needle, _Needle_size);
|
||||
}
|
||||
if (_Hay_size == 0) { // no match possible
|
||||
return static_cast<size_t>(-1);
|
||||
}
|
||||
|
||||
for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - 1);; --_Match_try) {
|
||||
const auto _Hay_start = (_STD min)(_Start_at, _Hay_size - 1);
|
||||
|
||||
if constexpr (_Is_implementation_handled_char_traits<_Traits>) {
|
||||
using _Elem = typename _Traits::char_type;
|
||||
_String_bitmap<_Elem> _Matches;
|
||||
if (_Matches._Mark(_Needle, _Needle + _Needle_size)) {
|
||||
for (auto _Match_try = _Haystack + _Hay_start;; --_Match_try) {
|
||||
if (!_Matches._Match(*_Match_try)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
|
||||
if (_Match_try == _Haystack) {
|
||||
break; // at beginning, no more chance for match
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - 1);; --_Match_try) {
|
||||
if (!_Traits::find(_Needle, _Needle_size, *_Match_try)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
|
||||
if (_Match_try == _Haystack) {
|
||||
break; // at beginning, no more chance for match
|
||||
return static_cast<size_t>(-1); // at beginning, no more chance for match
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// couldn't put one of the characters into the bitmap, fall back to the serial algorithm
|
||||
}
|
||||
|
||||
return static_cast<size_t>(-1); // no match
|
||||
for (auto _Match_try = _Haystack + _Hay_start;; --_Match_try) {
|
||||
if (!_Traits::find(_Needle, _Needle_size, *_Match_try)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
|
||||
if (_Match_try == _Haystack) {
|
||||
return static_cast<size_t>(-1); // at beginning, no more chance for match
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Traits>
|
||||
constexpr size_t _Traits_rfind_not_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits> _Haystack,
|
||||
const size_t _Hay_size, const size_t _Start_at, const _Traits_ch_t<_Traits> _Ch) noexcept {
|
||||
// search [_Haystack, _Haystack + _Hay_size) for any value other than _Ch before _Start_at
|
||||
if (_Hay_size != 0) { // room for match, look for it
|
||||
for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - 1);; --_Match_try) {
|
||||
if (!_Traits::eq(*_Match_try, _Ch)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
|
||||
if (_Match_try == _Haystack) {
|
||||
break; // at beginning, no more chance for match
|
||||
}
|
||||
}
|
||||
if (_Hay_size == 0) { // no room for match
|
||||
return static_cast<size_t>(-1);
|
||||
}
|
||||
|
||||
return static_cast<size_t>(-1); // no match
|
||||
for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - 1);; --_Match_try) {
|
||||
if (!_Traits::eq(*_Match_try, _Ch)) {
|
||||
return static_cast<size_t>(_Match_try - _Haystack); // found a match
|
||||
}
|
||||
|
||||
if (_Match_try == _Haystack) {
|
||||
return static_cast<size_t>(-1); // at beginning, no more chance for match
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Ty>
|
||||
|
@ -1337,7 +1412,9 @@ public:
|
|||
#if _CONTAINER_DEBUG_LEVEL > 0
|
||||
_STL_VERIFY(_Off < _Mysize, "string_view subscript out of range");
|
||||
#endif // _CONTAINER_DEBUG_LEVEL > 0
|
||||
return _Mydata[_Off]; // lgtm [cpp/unclear-array-index-validation]
|
||||
|
||||
// CodeQL [SM01954] This index is optionally validated above.
|
||||
return _Mydata[_Off];
|
||||
}
|
||||
|
||||
_NODISCARD constexpr const_reference at(const size_type _Off) const {
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -422,6 +422,8 @@ public:
|
|||
using reverse_iterator = _STD reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = _STD reverse_iterator<const_iterator>;
|
||||
|
||||
using _Library_defined = array;
|
||||
|
||||
#if _HAS_TR1_NAMESPACE
|
||||
_DEPRECATE_TR1_NAMESPACE void assign(const _Ty& _Value) {
|
||||
_STD fill_n(_Elems, _Size, _Value);
|
||||
|
@ -610,6 +612,8 @@ public:
|
|||
using reverse_iterator = _STD reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = _STD reverse_iterator<const_iterator>;
|
||||
|
||||
using _Library_defined = array;
|
||||
|
||||
#if _HAS_TR1_NAMESPACE
|
||||
_DEPRECATE_TR1_NAMESPACE void assign(const _Ty&) {}
|
||||
#endif // _HAS_TR1_NAMESPACE
|
||||
|
@ -844,10 +848,15 @@ _NODISCARD constexpr array<remove_cv_t<_Ty>, _Size> to_array(_Ty (&&_Array)[_Siz
|
|||
}
|
||||
#endif // _HAS_CXX20
|
||||
|
||||
template <class _Ty, class _Enable = void>
|
||||
constexpr bool _Is_library_defined = false;
|
||||
template <class _Ty>
|
||||
constexpr bool _Is_library_defined<_Ty, enable_if_t<is_same_v<typename _Ty::_Library_defined, _Ty>>> = true;
|
||||
|
||||
_EXPORT_STD template <size_t _Idx, class _Ty, size_t _Size>
|
||||
_NODISCARD constexpr _Ty& get(array<_Ty, _Size>& _Arr) noexcept {
|
||||
static_assert(_Idx < _Size, "array index out of bounds");
|
||||
if constexpr (_Has_unchecked_begin_end<array<_Ty, _Size>>) {
|
||||
if constexpr (_Is_library_defined<array<_Ty, _Size>>) {
|
||||
return _Arr._Elems[_Idx];
|
||||
} else {
|
||||
#if _HAS_CXX17
|
||||
|
@ -861,7 +870,7 @@ _NODISCARD constexpr _Ty& get(array<_Ty, _Size>& _Arr) noexcept {
|
|||
_EXPORT_STD template <size_t _Idx, class _Ty, size_t _Size>
|
||||
_NODISCARD constexpr const _Ty& get(const array<_Ty, _Size>& _Arr) noexcept {
|
||||
static_assert(_Idx < _Size, "array index out of bounds");
|
||||
if constexpr (_Has_unchecked_begin_end<array<_Ty, _Size>>) {
|
||||
if constexpr (_Is_library_defined<array<_Ty, _Size>>) {
|
||||
return _Arr._Elems[_Idx];
|
||||
} else {
|
||||
return _Arr[_Idx];
|
||||
|
@ -871,7 +880,7 @@ _NODISCARD constexpr const _Ty& get(const array<_Ty, _Size>& _Arr) noexcept {
|
|||
_EXPORT_STD template <size_t _Idx, class _Ty, size_t _Size>
|
||||
_NODISCARD constexpr _Ty&& get(array<_Ty, _Size>&& _Arr) noexcept {
|
||||
static_assert(_Idx < _Size, "array index out of bounds");
|
||||
if constexpr (_Has_unchecked_begin_end<array<_Ty, _Size>>) {
|
||||
if constexpr (_Is_library_defined<array<_Ty, _Size>>) {
|
||||
return _STD move(_Arr._Elems[_Idx]);
|
||||
} else {
|
||||
#if _HAS_CXX17
|
||||
|
@ -885,7 +894,7 @@ _NODISCARD constexpr _Ty&& get(array<_Ty, _Size>&& _Arr) noexcept {
|
|||
_EXPORT_STD template <size_t _Idx, class _Ty, size_t _Size>
|
||||
_NODISCARD constexpr const _Ty&& get(const array<_Ty, _Size>&& _Arr) noexcept {
|
||||
static_assert(_Idx < _Size, "array index out of bounds");
|
||||
if constexpr (_Has_unchecked_begin_end<array<_Ty, _Size>>) {
|
||||
if constexpr (_Is_library_defined<array<_Ty, _Size>>) {
|
||||
return _STD move(_Arr._Elems[_Idx]);
|
||||
} else {
|
||||
return _STD move(_Arr[_Idx]);
|
||||
|
|
|
@ -23,11 +23,19 @@ _STL_DISABLE_CLANG_WARNINGS
|
|||
#endif // !defined(_STD_BITSET_TO_STREAM_STACK_RESERVATION)
|
||||
|
||||
#if _USE_STD_VECTOR_ALGORITHMS
|
||||
// These bitset functions sometimes assume that the bit array has zero padding to a multiple of 2 or 4 bytes.
|
||||
// The assumptions hold true even for the vNext suggestion to use smaller types for small bitsets (see GH-1498)
|
||||
// due to vectorization thresholds.
|
||||
|
||||
extern "C" {
|
||||
__declspec(noalias) void __stdcall __std_bitset_to_string_1(
|
||||
char* _Dest, const void* _Src, size_t _Size_bits, char _Elem0, char _Elem1) noexcept;
|
||||
__declspec(noalias) void __stdcall __std_bitset_to_string_2(
|
||||
wchar_t* _Dest, const void* _Src, size_t _Size_bits, wchar_t _Elem0, wchar_t _Elem1) noexcept;
|
||||
__declspec(noalias) bool __stdcall __std_bitset_from_string_1(void* _Dest, const char* _Src, size_t _Size_bytes,
|
||||
size_t _Size_bits, size_t _Size_chars, char _Elem0, char _Elem1) noexcept;
|
||||
__declspec(noalias) bool __stdcall __std_bitset_from_string_2(void* _Dest, const wchar_t* _Src, size_t _Size_bytes,
|
||||
size_t _Size_bits, size_t _Size_chars, wchar_t _Elem0, wchar_t _Elem1) noexcept;
|
||||
} // extern "C"
|
||||
#endif // _USE_STD_VECTOR_ALGORITHMS
|
||||
|
||||
|
@ -115,6 +123,30 @@ public:
|
|||
private:
|
||||
template <class _Traits, class _Elem>
|
||||
_CONSTEXPR23 void _Construct(const _Elem* const _Ptr, size_t _Count, const _Elem _Elem0, const _Elem _Elem1) {
|
||||
#if _USE_STD_VECTOR_ALGORITHMS
|
||||
constexpr size_t _Bitset_from_string_vector_threshold = 16;
|
||||
if constexpr (_Bits >= _Bitset_from_string_vector_threshold
|
||||
&& _Is_implementation_handled_char_traits<_Traits> && sizeof(_Elem) <= 2) {
|
||||
if (!_STD _Is_constant_evaluated()) {
|
||||
bool _Result;
|
||||
|
||||
if constexpr (sizeof(_Elem) == 1) {
|
||||
_Result = __std_bitset_from_string_1(_Array, reinterpret_cast<const char*>(_Ptr), sizeof(_Array),
|
||||
_Bits, _Count, static_cast<char>(_Elem0), static_cast<char>(_Elem1));
|
||||
} else {
|
||||
_STL_INTERNAL_STATIC_ASSERT(sizeof(_Elem) == 2);
|
||||
_Result = __std_bitset_from_string_2(_Array, reinterpret_cast<const wchar_t*>(_Ptr), sizeof(_Array),
|
||||
_Bits, _Count, static_cast<wchar_t>(_Elem0), static_cast<wchar_t>(_Elem1));
|
||||
}
|
||||
|
||||
if (!_Result) {
|
||||
_Xinv();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif // _USE_STD_VECTOR_ALGORITHMS
|
||||
if (_Count > _Bits) {
|
||||
for (size_t _Idx = _Bits; _Idx < _Count; ++_Idx) {
|
||||
const auto _Ch = _Ptr[_Idx];
|
||||
|
@ -462,8 +494,8 @@ public:
|
|||
_CONSTEXPR23 void _To_string(
|
||||
_Elem* const _Buf, const size_t _Len, const _Elem _Elem0, const _Elem _Elem1) const noexcept {
|
||||
#if _USE_STD_VECTOR_ALGORITHMS
|
||||
constexpr size_t _Bitset_vector_threshold = 32;
|
||||
if constexpr (_Bits >= _Bitset_vector_threshold && is_integral_v<_Elem> && sizeof(_Elem) <= 2) {
|
||||
constexpr size_t _Bitset_to_string_vector_threshold = 32;
|
||||
if constexpr (_Bits >= _Bitset_to_string_vector_threshold && is_integral_v<_Elem> && sizeof(_Elem) <= 2) {
|
||||
if (!_Is_constant_evaluated()) {
|
||||
if constexpr (sizeof(_Elem) == 1) {
|
||||
__std_bitset_to_string_1(reinterpret_cast<char*>(_Buf), _Array, _Len, static_cast<char>(_Elem0),
|
||||
|
@ -585,19 +617,25 @@ basic_istream<_Elem, _Tr>& operator>>(basic_istream<_Elem, _Tr>& _Istr, bitset<_
|
|||
typename _Tr::int_type _Meta = _Istr.rdbuf()->sgetc();
|
||||
for (size_t _Count = _Right.size(); 0 < _Count; _Meta = _Istr.rdbuf()->snextc(), (void) --_Count) {
|
||||
// test _Meta
|
||||
_Elem _Char;
|
||||
if (_Tr::eq_int_type(_Tr::eof(), _Meta)) { // end of file, quit
|
||||
_State |= _Istr_t::eofbit;
|
||||
break;
|
||||
} else if ((_Char = _Tr::to_char_type(_Meta)) != _Elem0 && _Char != _Elem1) {
|
||||
}
|
||||
|
||||
const _Elem _Char = _Tr::to_char_type(_Meta);
|
||||
|
||||
if (!_Tr::eq(_Char, _Elem0) && !_Tr::eq(_Char, _Elem1)) {
|
||||
break; // invalid element
|
||||
} else if (_Str.max_size() <= _Str.size()) { // no room in string, give up (unlikely)
|
||||
}
|
||||
|
||||
if (_Str.max_size() <= _Str.size()) { // no room in string, give up (unlikely)
|
||||
_State |= _Istr_t::failbit;
|
||||
break;
|
||||
} else { // valid, append '0' or '1'
|
||||
_Str.push_back('0' + (_Char == _Elem1));
|
||||
_Changed = true;
|
||||
}
|
||||
|
||||
// valid, append '0' or '1'
|
||||
_Str.push_back('0' + _Tr::eq(_Char, _Elem1));
|
||||
_Changed = true;
|
||||
}
|
||||
_CATCH_IO_(_Istr_t, _Istr)
|
||||
}
|
||||
|
|
|
@ -228,7 +228,9 @@ _STL_INTERNAL_STATIC_ASSERT(_STD size(_Digit_from_byte) == 256);
|
|||
|
||||
_NODISCARD _CONSTEXPR23 unsigned char _Digit_from_char(const char _Ch) noexcept {
|
||||
// convert ['0', '9'] ['A', 'Z'] ['a', 'z'] to [0, 35], everything else to 255
|
||||
return _Digit_from_byte[static_cast<unsigned char>(_Ch)]; // lgtm [cpp/unclear-array-index-validation]
|
||||
|
||||
// CodeQL [SM01954] This index is valid: we cast to unsigned char and the array has 256 elements.
|
||||
return _Digit_from_byte[static_cast<unsigned char>(_Ch)];
|
||||
}
|
||||
|
||||
template <class _RawTy>
|
||||
|
@ -456,7 +458,9 @@ _NODISCARD inline uint32_t _Bit_scan_reverse(const _Big_integer_flt& _Xval) noex
|
|||
unsigned long _Index; // Intentionally uninitialized for better codegen
|
||||
|
||||
_STL_INTERNAL_CHECK(_Xval._Mydata[_Bx] != 0); // _Big_integer_flt should always be trimmed
|
||||
_BitScanReverse(&_Index, _Xval._Mydata[_Bx]); // lgtm [cpp/conditionallyuninitializedvariable]
|
||||
|
||||
// CodeQL [SM02313] _Index is always initialized: we've guaranteed that _Xval._Mydata[_Bx] is non-zero.
|
||||
_BitScanReverse(&_Index, _Xval._Mydata[_Bx]);
|
||||
|
||||
return _Index + 1 + _Bx * _Big_integer_flt::_Element_bits;
|
||||
}
|
||||
|
|
|
@ -2209,7 +2209,7 @@ namespace chrono {
|
|||
auto [_Icu_version, _Zones, _Links] = _Tzdb_generate_time_zones();
|
||||
auto [_Leap_sec, _All_ls_positive] = _Tzdb_generate_leap_seconds(0);
|
||||
auto _Version = _Icu_version + "." + _STD to_string(_Leap_sec.size());
|
||||
// TRANSITION, VSO-2228186, should call emplace_front with construction arguments
|
||||
// TRANSITION, NVCC (was DevCom-10732572), should call emplace_front with construction arguments
|
||||
_Tzdb_list.emplace_front(tzdb{
|
||||
_STD move(_Version), _STD move(_Zones), _STD move(_Links), _STD move(_Leap_sec), _All_ls_positive});
|
||||
}
|
||||
|
@ -2267,7 +2267,7 @@ namespace chrono {
|
|||
}
|
||||
|
||||
auto _Version = _Tzdb_update_version(_Tzdb.version, _Leap_sec.size());
|
||||
// TRANSITION, VSO-2228186, should call emplace_front with construction arguments
|
||||
// TRANSITION, NVCC (was DevCom-10732572), should call emplace_front with construction arguments
|
||||
_Tzdb_list.emplace_front(tzdb{
|
||||
_STD move(_Version), _STD move(_Zones), _STD move(_Links), _STD move(_Leap_sec), _All_ls_positive});
|
||||
}
|
||||
|
|
|
@ -669,9 +669,11 @@ _STD _Common_float_type_t<_Ty1, _Ty2> remquo(_Ty1 _Left, _Ty2 _Right, int* _Pquo
|
|||
_CLANG_BUILTIN2_ARG(NAME, double) \
|
||||
_CLANG_BUILTIN2_ARG(NAME, long double)
|
||||
|
||||
_STL_DISABLE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
_CLANG_BUILTIN1(isfinite)
|
||||
_CLANG_BUILTIN1(isinf)
|
||||
_CLANG_BUILTIN1(isnan)
|
||||
_STL_RESTORE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
_CLANG_BUILTIN1(isnormal)
|
||||
|
||||
_CLANG_BUILTIN2(isgreater)
|
||||
|
@ -679,14 +681,18 @@ _CLANG_BUILTIN2(isgreaterequal)
|
|||
_CLANG_BUILTIN2(isless)
|
||||
_CLANG_BUILTIN2(islessequal)
|
||||
_CLANG_BUILTIN2(islessgreater)
|
||||
_STL_DISABLE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
_CLANG_BUILTIN2(isunordered)
|
||||
_STL_RESTORE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
|
||||
_CLANG_BUILTIN2_TEMPLATED(isgreater)
|
||||
_CLANG_BUILTIN2_TEMPLATED(isgreaterequal)
|
||||
_CLANG_BUILTIN2_TEMPLATED(isless)
|
||||
_CLANG_BUILTIN2_TEMPLATED(islessequal)
|
||||
_CLANG_BUILTIN2_TEMPLATED(islessgreater)
|
||||
_STL_DISABLE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
_CLANG_BUILTIN2_TEMPLATED(isunordered)
|
||||
_STL_RESTORE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
|
||||
#undef _CLANG_BUILTIN1_ARG
|
||||
#undef _CLANG_BUILTIN2_ARG
|
||||
|
|
|
@ -2945,7 +2945,7 @@ struct _Static_partitioned_stable_sort3 {
|
|||
const size_t _Base = _Visitor._Base;
|
||||
const size_t _Mid = _Base + _Visitor._Shift;
|
||||
const size_t _End = _Mid + _Visitor._Shift;
|
||||
_STD _Merge_move(_Temp_buf._Get_first(_Base), _Temp_buf._Get_first(_Mid),
|
||||
_STD _Merge_move_unchecked(_Temp_buf._Get_first(_Base), _Temp_buf._Get_first(_Mid),
|
||||
_Temp_buf._Get_first(_End), _Basis._Get_first(_Base, _Team._Get_chunk_offset(_Base)), _Pred);
|
||||
}
|
||||
|
||||
|
@ -2963,7 +2963,7 @@ struct _Static_partitioned_stable_sort3 {
|
|||
const size_t _Base = _Visitor._Base;
|
||||
const size_t _Mid = _Base + _Visitor._Shift;
|
||||
const size_t _End = _Mid + _Visitor._Shift;
|
||||
_STD _Merge_move(_Basis._Get_first(_Base, _Team._Get_chunk_offset(_Base)),
|
||||
_STD _Merge_move_unchecked(_Basis._Get_first(_Base, _Team._Get_chunk_offset(_Base)),
|
||||
_Basis._Get_first(_Mid, _Team._Get_chunk_offset(_Mid)),
|
||||
_Basis._Get_first(_End, _Team._Get_chunk_offset(_End)), _Temp_buf._Get_first(_Base), _Pred);
|
||||
}
|
||||
|
|
1617
stl/inc/format
1617
stl/inc/format
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1208,12 +1208,12 @@ public:
|
|||
_Nodeptr* _Tail;
|
||||
};
|
||||
|
||||
auto remove(const _Ty& _Val) { // erase each element matching _Val
|
||||
_LIST_REMOVE_RETURN remove(const _Ty& _Val) { // erase each element matching _Val
|
||||
return remove_if([&](const _Ty& _Other) -> bool { return _Other == _Val; });
|
||||
}
|
||||
|
||||
template <class _Pr1>
|
||||
auto remove_if(_Pr1 _Pred) { // erase each element satisfying _Pr1
|
||||
_LIST_REMOVE_RETURN remove_if(_Pr1 _Pred) { // erase each element satisfying _Pr1
|
||||
_Flist_node_remove_op _Op(*this);
|
||||
auto _Firstb = _Unchecked_before_begin();
|
||||
size_type _Removed = 0;
|
||||
|
@ -1235,12 +1235,12 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
auto unique() { // erase each element matching previous
|
||||
_LIST_REMOVE_RETURN unique() { // erase each element matching previous
|
||||
return unique(equal_to<>{});
|
||||
}
|
||||
|
||||
template <class _Pr2>
|
||||
auto unique(_Pr2 _Pred) { // erase each element satisfying _Pred with previous
|
||||
_LIST_REMOVE_RETURN unique(_Pr2 _Pred) { // erase each element satisfying _Pred with previous
|
||||
_Flist_node_remove_op _Op(*this);
|
||||
auto _First = _Unchecked_begin();
|
||||
size_type _Removed = 0;
|
||||
|
|
|
@ -767,7 +767,10 @@ public:
|
|||
private:
|
||||
_Mybase* _Copy(void* _Where) const override {
|
||||
auto& _Myax = _Mypair._Get_first();
|
||||
if constexpr (_Is_large<_Func_impl>) {
|
||||
if constexpr (!is_copy_constructible_v<_Callable>) { // used exclusively for packaged_task
|
||||
(void) _Myax;
|
||||
_CSTD abort(); // shouldn't be called, see GH-3888
|
||||
} else if constexpr (_Is_large<_Func_impl>) {
|
||||
_Myalty _Rebound(_Myax);
|
||||
_Alloc_construct_ptr<_Myalty> _Constructor{_Rebound};
|
||||
_Constructor._Allocate();
|
||||
|
@ -854,7 +857,9 @@ public:
|
|||
|
||||
private:
|
||||
_Mybase* _Copy(void* _Where) const override {
|
||||
if constexpr (_Is_large<_Func_impl_no_alloc>) {
|
||||
if constexpr (!is_copy_constructible_v<_Callable>) { // used exclusively for packaged_task
|
||||
_CSTD abort(); // shouldn't be called, see GH-3888
|
||||
} else if constexpr (_Is_large<_Func_impl_no_alloc>) {
|
||||
return _STD _Global_new<_Func_impl_no_alloc>(_Callee);
|
||||
} else {
|
||||
return ::new (_Where) _Func_impl_no_alloc(_Callee);
|
||||
|
@ -1070,6 +1075,10 @@ _NON_MEMBER_CALL(_GET_FUNCTION_IMPL_NOEXCEPT, X1, X2, X3)
|
|||
#undef _GET_FUNCTION_IMPL_NOEXCEPT
|
||||
#endif // defined(__cpp_noexcept_function_type)
|
||||
|
||||
struct _Secret_copyability_ignoring_tag { // used exclusively for packaged_task
|
||||
explicit _Secret_copyability_ignoring_tag() = default;
|
||||
};
|
||||
|
||||
_EXPORT_STD template <class _Fty>
|
||||
class function : public _Get_function_impl<_Fty>::type { // wrapper for callable objects
|
||||
private:
|
||||
|
@ -1086,6 +1095,15 @@ public:
|
|||
|
||||
template <class _Fx, typename _Mybase::template _Enable_if_callable_t<_Fx, function> = 0>
|
||||
function(_Fx&& _Func) {
|
||||
static_assert(is_copy_constructible_v<decay_t<_Fx>>,
|
||||
"The target function object type must be copy constructible (N4988 [func.wrap.func.con]/10.1).");
|
||||
this->_Reset(_STD forward<_Fx>(_Func));
|
||||
}
|
||||
|
||||
template <class _SecretTag, class _Fx,
|
||||
enable_if_t<is_same_v<_SecretTag, _Secret_copyability_ignoring_tag>, int> = 0,
|
||||
typename _Mybase::template _Enable_if_callable_t<_Fx, function> = 0>
|
||||
explicit function(_SecretTag, _Fx&& _Func) { // used exclusively for packaged_task
|
||||
this->_Reset(_STD forward<_Fx>(_Func));
|
||||
}
|
||||
|
||||
|
@ -1103,6 +1121,16 @@ public:
|
|||
|
||||
template <class _Fx, class _Alloc, typename _Mybase::template _Enable_if_callable_t<_Fx, function> = 0>
|
||||
function(allocator_arg_t, const _Alloc& _Ax, _Fx&& _Func) {
|
||||
static_assert(is_copy_constructible_v<decay_t<_Fx>>,
|
||||
"The target function object type must be copy constructible (N4140 [func.wrap.func.con]/7).");
|
||||
this->_Reset_alloc(_STD forward<_Fx>(_Func), _Ax);
|
||||
}
|
||||
|
||||
template <class _SecretTag, class _Fx, class _Alloc,
|
||||
enable_if_t<is_same_v<_SecretTag, _Secret_copyability_ignoring_tag>, int> = 0,
|
||||
typename _Mybase::template _Enable_if_callable_t<_Fx, function> = 0>
|
||||
explicit function(_SecretTag, allocator_arg_t, const _Alloc& _Ax, _Fx&& _Func) {
|
||||
// used exclusively for packaged_task
|
||||
this->_Reset_alloc(_STD forward<_Fx>(_Func), _Ax);
|
||||
}
|
||||
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
|
||||
|
|
190
stl/inc/future
190
stl/inc/future
|
@ -459,29 +459,64 @@ void _State_deleter<_Ty, _Derived, _Alloc>::_Delete(_Associated_state<_Ty>* _Sta
|
|||
_STD _Delete_plain_internal(_Del_alloc, this);
|
||||
}
|
||||
|
||||
template <class _Fret>
|
||||
struct _P_arg_type { // type for functions returning T
|
||||
using type = _Fret;
|
||||
};
|
||||
|
||||
template <class _Fret>
|
||||
struct _P_arg_type<_Fret&> { // type for functions returning reference to T
|
||||
using type = _Fret*;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct _P_arg_type<void> { // type for functions returning void
|
||||
using type = int;
|
||||
};
|
||||
|
||||
template <class>
|
||||
class _Packaged_state;
|
||||
|
||||
// class for managing associated asynchronous state for packaged_task
|
||||
template <class _Ret, class... _ArgTypes>
|
||||
class _Packaged_state<_Ret(_ArgTypes...)>
|
||||
: public _Associated_state<_Ret> { // class for managing associated asynchronous state for packaged_task
|
||||
class _Packaged_state<_Ret(_ArgTypes...)> : public _Associated_state<typename _P_arg_type<_Ret>::type> {
|
||||
public:
|
||||
using _Mybase = _Associated_state<_Ret>;
|
||||
using _Mydel = typename _Mybase::_Mydel;
|
||||
using _Mybase = _Associated_state<typename _P_arg_type<_Ret>::type>;
|
||||
using _Mydel = typename _Mybase::_Mydel;
|
||||
using _Function_type = function<_Ret(_ArgTypes...)>; // TRANSITION, ABI, should not use std::function
|
||||
|
||||
template <class _Fty2>
|
||||
_Packaged_state(_Fty2&& _Fnarg) : _Fn(_STD forward<_Fty2>(_Fnarg)) {}
|
||||
explicit _Packaged_state(const _Function_type& _Fnarg) : _Fn(_Fnarg) {}
|
||||
|
||||
explicit _Packaged_state(_Function_type&& _Fnarg) noexcept : _Fn(_STD move(_Fnarg)) {}
|
||||
|
||||
template <class _Fty2, enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, _Function_type>, int> = 0>
|
||||
explicit _Packaged_state(_Fty2&& _Fnarg) : _Fn(_Secret_copyability_ignoring_tag{}, _STD forward<_Fty2>(_Fnarg)) {}
|
||||
|
||||
#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
|
||||
template <class _Fty2, class _Alloc>
|
||||
template <class _Alloc>
|
||||
_Packaged_state(const _Function_type& _Fnarg, const _Alloc& _Al, _Mydel* _Dp)
|
||||
: _Mybase(_Dp), _Fn(allocator_arg, _Al, _Fnarg) {}
|
||||
|
||||
template <class _Alloc>
|
||||
_Packaged_state(_Function_type&& _Fnarg, const _Alloc& _Al, _Mydel* _Dp)
|
||||
: _Mybase(_Dp), _Fn(allocator_arg, _Al, _STD move(_Fnarg)) {}
|
||||
|
||||
template <class _Fty2, class _Alloc, enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, _Function_type>, int> = 0>
|
||||
_Packaged_state(_Fty2&& _Fnarg, const _Alloc& _Al, _Mydel* _Dp)
|
||||
: _Mybase(_Dp), _Fn(allocator_arg, _Al, _STD forward<_Fty2>(_Fnarg)) {}
|
||||
: _Mybase(_Dp), _Fn(_Secret_copyability_ignoring_tag{}, allocator_arg, _Al, _STD forward<_Fty2>(_Fnarg)) {}
|
||||
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
|
||||
|
||||
void _Call_deferred(_ArgTypes... _Args) { // set deferred call
|
||||
_TRY_BEGIN
|
||||
// call function object and catch exceptions
|
||||
this->_Set_value(_Fn(_STD forward<_ArgTypes>(_Args)...), true);
|
||||
if constexpr (is_same_v<_Ret, void>) {
|
||||
_Fn(_STD forward<_ArgTypes>(_Args)...);
|
||||
this->_Set_value(1, true);
|
||||
} else if constexpr (is_lvalue_reference_v<_Ret>) {
|
||||
this->_Set_value(_STD addressof(_Fn(_STD forward<_ArgTypes>(_Args)...)), true);
|
||||
} else {
|
||||
this->_Set_value(_Fn(_STD forward<_ArgTypes>(_Args)...), true);
|
||||
}
|
||||
_CATCH_ALL
|
||||
// function object threw exception; record result
|
||||
this->_Set_exception(_STD current_exception(), true);
|
||||
|
@ -491,109 +526,29 @@ public:
|
|||
void _Call_immediate(_ArgTypes... _Args) { // call function object
|
||||
_TRY_BEGIN
|
||||
// call function object and catch exceptions
|
||||
this->_Set_value(_Fn(_STD forward<_ArgTypes>(_Args)...), false);
|
||||
if constexpr (is_same_v<_Ret, void>) {
|
||||
_Fn(_STD forward<_ArgTypes>(_Args)...);
|
||||
this->_Set_value(1, false);
|
||||
} else if constexpr (is_lvalue_reference_v<_Ret>) {
|
||||
this->_Set_value(_STD addressof(_Fn(_STD forward<_ArgTypes>(_Args)...)), false);
|
||||
} else {
|
||||
this->_Set_value(_Fn(_STD forward<_ArgTypes>(_Args)...), false);
|
||||
}
|
||||
_CATCH_ALL
|
||||
// function object threw exception; record result
|
||||
this->_Set_exception(_STD current_exception(), false);
|
||||
_CATCH_END
|
||||
}
|
||||
|
||||
const auto& _Get_fn() const {
|
||||
const auto& _Get_fn() const& {
|
||||
return _Fn;
|
||||
}
|
||||
auto&& _Get_fn() && noexcept {
|
||||
return _STD move(_Fn);
|
||||
}
|
||||
|
||||
private:
|
||||
function<_Ret(_ArgTypes...)> _Fn;
|
||||
};
|
||||
|
||||
template <class _Ret, class... _ArgTypes>
|
||||
class _Packaged_state<_Ret&(_ArgTypes...)>
|
||||
: public _Associated_state<_Ret*> { // class for managing associated asynchronous state for packaged_task
|
||||
public:
|
||||
using _Mybase = _Associated_state<_Ret*>;
|
||||
using _Mydel = typename _Mybase::_Mydel;
|
||||
|
||||
template <class _Fty2>
|
||||
_Packaged_state(_Fty2&& _Fnarg) : _Fn(_STD forward<_Fty2>(_Fnarg)) {}
|
||||
|
||||
#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
|
||||
template <class _Fty2, class _Alloc>
|
||||
_Packaged_state(_Fty2&& _Fnarg, const _Alloc& _Al, _Mydel* _Dp)
|
||||
: _Mybase(_Dp), _Fn(allocator_arg, _Al, _STD forward<_Fty2>(_Fnarg)) {}
|
||||
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
|
||||
|
||||
void _Call_deferred(_ArgTypes... _Args) { // set deferred call
|
||||
_TRY_BEGIN
|
||||
// call function object and catch exceptions
|
||||
this->_Set_value(_STD addressof(_Fn(_STD forward<_ArgTypes>(_Args)...)), true);
|
||||
_CATCH_ALL
|
||||
// function object threw exception; record result
|
||||
this->_Set_exception(_STD current_exception(), true);
|
||||
_CATCH_END
|
||||
}
|
||||
|
||||
void _Call_immediate(_ArgTypes... _Args) { // call function object
|
||||
_TRY_BEGIN
|
||||
// call function object and catch exceptions
|
||||
this->_Set_value(_STD addressof(_Fn(_STD forward<_ArgTypes>(_Args)...)), false);
|
||||
_CATCH_ALL
|
||||
// function object threw exception; record result
|
||||
this->_Set_exception(_STD current_exception(), false);
|
||||
_CATCH_END
|
||||
}
|
||||
|
||||
const auto& _Get_fn() const {
|
||||
return _Fn;
|
||||
}
|
||||
|
||||
private:
|
||||
function<_Ret&(_ArgTypes...)> _Fn;
|
||||
};
|
||||
|
||||
template <class... _ArgTypes>
|
||||
class _Packaged_state<void(_ArgTypes...)>
|
||||
: public _Associated_state<int> { // class for managing associated asynchronous state for packaged_task
|
||||
public:
|
||||
using _Mybase = _Associated_state<int>;
|
||||
using _Mydel = typename _Mybase::_Mydel;
|
||||
|
||||
template <class _Fty2>
|
||||
_Packaged_state(_Fty2&& _Fnarg) : _Fn(_STD forward<_Fty2>(_Fnarg)) {}
|
||||
|
||||
#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
|
||||
template <class _Fty2, class _Alloc>
|
||||
_Packaged_state(_Fty2&& _Fnarg, const _Alloc& _Al, _Mydel* _Dp)
|
||||
: _Mybase(_Dp), _Fn(allocator_arg, _Al, _STD forward<_Fty2>(_Fnarg)) {}
|
||||
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
|
||||
|
||||
void _Call_deferred(_ArgTypes... _Args) { // set deferred call
|
||||
_TRY_BEGIN
|
||||
// call function object and catch exceptions
|
||||
_Fn(_STD forward<_ArgTypes>(_Args)...);
|
||||
this->_Set_value(1, true);
|
||||
_CATCH_ALL
|
||||
// function object threw exception; record result
|
||||
this->_Set_exception(_STD current_exception(), true);
|
||||
_CATCH_END
|
||||
}
|
||||
|
||||
void _Call_immediate(_ArgTypes... _Args) { // call function object
|
||||
_TRY_BEGIN
|
||||
// call function object and catch exceptions
|
||||
_Fn(_STD forward<_ArgTypes>(_Args)...);
|
||||
this->_Set_value(1, false);
|
||||
_CATCH_ALL
|
||||
// function object threw exception; record result
|
||||
this->_Set_exception(_STD current_exception(), false);
|
||||
_CATCH_END
|
||||
}
|
||||
|
||||
const auto& _Get_fn() const {
|
||||
return _Fn;
|
||||
}
|
||||
|
||||
private:
|
||||
function<void(_ArgTypes...)> _Fn;
|
||||
_Function_type _Fn;
|
||||
};
|
||||
|
||||
template <class _Ty, class _Alloc>
|
||||
|
@ -1235,21 +1190,6 @@ void swap(promise<_Ty>& _Left, promise<_Ty>& _Right) noexcept {
|
|||
_Left.swap(_Right);
|
||||
}
|
||||
|
||||
template <class _Fret>
|
||||
struct _P_arg_type { // type for functions returning T
|
||||
using type = _Fret;
|
||||
};
|
||||
|
||||
template <class _Fret>
|
||||
struct _P_arg_type<_Fret&> { // type for functions returning reference to T
|
||||
using type = _Fret*;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct _P_arg_type<void> { // type for functions returning void
|
||||
using type = int;
|
||||
};
|
||||
|
||||
_EXPORT_STD template <class>
|
||||
class packaged_task; // not defined
|
||||
|
||||
|
@ -1266,7 +1206,10 @@ public:
|
|||
packaged_task() = default;
|
||||
|
||||
template <class _Fty2, enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, packaged_task>, int> = 0>
|
||||
explicit packaged_task(_Fty2&& _Fnarg) : _MyPromise(new _MyStateType(_STD forward<_Fty2>(_Fnarg))) {}
|
||||
explicit packaged_task(_Fty2&& _Fnarg) : _MyPromise(new _MyStateType(_STD forward<_Fty2>(_Fnarg))) {
|
||||
static_assert(_Is_invocable_r<_Ret, decay_t<_Fty2>&, _ArgTypes...>::value, // per LWG-4154
|
||||
"The function object must be callable with _ArgTypes... and return _Ret (N4988 [futures.task.members]/3).");
|
||||
}
|
||||
|
||||
packaged_task(packaged_task&&) noexcept = default;
|
||||
|
||||
|
@ -1275,7 +1218,10 @@ public:
|
|||
#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
|
||||
template <class _Fty2, class _Alloc, enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, packaged_task>, int> = 0>
|
||||
packaged_task(allocator_arg_t, const _Alloc& _Al, _Fty2&& _Fnarg)
|
||||
: _MyPromise(_STD _Make_packaged_state<_MyStateType>(_STD forward<_Fty2>(_Fnarg), _Al)) {}
|
||||
: _MyPromise(_STD _Make_packaged_state<_MyStateType>(_STD forward<_Fty2>(_Fnarg), _Al)) {
|
||||
static_assert(_Is_invocable_r<_Ret, decay_t<_Fty2>&, _ArgTypes...>::value, // per LWG-4154
|
||||
"The function object must be callable with _ArgTypes... and return _Ret (N4140 [futures.task.members]/2).");
|
||||
}
|
||||
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
|
||||
|
||||
~packaged_task() noexcept {
|
||||
|
@ -1319,9 +1265,9 @@ public:
|
|||
}
|
||||
|
||||
void reset() { // reset to newly constructed state
|
||||
_MyStateManagerType& _State = _MyPromise._Get_state_for_set();
|
||||
_MyStateType* _MyState = static_cast<_MyStateType*>(_State._Ptr());
|
||||
_MyPromiseType _New_promise(new _MyStateType(_MyState->_Get_fn()));
|
||||
_MyStateManagerType& _State_mgr = _MyPromise._Get_state_for_set();
|
||||
_MyStateType& _MyState = *static_cast<_MyStateType*>(_State_mgr._Ptr());
|
||||
_MyPromiseType _New_promise(new _MyStateType(_STD move(_MyState)._Get_fn()));
|
||||
_MyPromise._Get_state()._Abandon();
|
||||
_MyPromise._Swap(_New_promise);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
"__msvc_ostream.hpp",
|
||||
"__msvc_print.hpp",
|
||||
"__msvc_ranges_to.hpp",
|
||||
"__msvc_ranges_tuple_formatter.hpp",
|
||||
"__msvc_sanitizer_annotate_container.hpp",
|
||||
"__msvc_string_view.hpp",
|
||||
"__msvc_system_error_abi.hpp",
|
||||
|
|
|
@ -875,6 +875,7 @@ public:
|
|||
return FLT_TRUE_MIN;
|
||||
}
|
||||
|
||||
_STL_DISABLE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
_NODISCARD static constexpr float infinity() noexcept {
|
||||
return __builtin_huge_valf();
|
||||
}
|
||||
|
@ -886,6 +887,7 @@ public:
|
|||
_NODISCARD static constexpr float signaling_NaN() noexcept {
|
||||
return __builtin_nansf("1");
|
||||
}
|
||||
_STL_RESTORE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
|
||||
static constexpr int digits = FLT_MANT_DIG;
|
||||
static constexpr int digits10 = FLT_DIG;
|
||||
|
@ -923,6 +925,7 @@ public:
|
|||
return DBL_TRUE_MIN;
|
||||
}
|
||||
|
||||
_STL_DISABLE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
_NODISCARD static constexpr double infinity() noexcept {
|
||||
return __builtin_huge_val();
|
||||
}
|
||||
|
@ -934,6 +937,7 @@ public:
|
|||
_NODISCARD static constexpr double signaling_NaN() noexcept {
|
||||
return __builtin_nans("1");
|
||||
}
|
||||
_STL_RESTORE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
|
||||
static constexpr int digits = DBL_MANT_DIG;
|
||||
static constexpr int digits10 = DBL_DIG;
|
||||
|
@ -971,6 +975,7 @@ public:
|
|||
return LDBL_TRUE_MIN;
|
||||
}
|
||||
|
||||
_STL_DISABLE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
_NODISCARD static constexpr long double infinity() noexcept {
|
||||
return __builtin_huge_val();
|
||||
}
|
||||
|
@ -982,6 +987,7 @@ public:
|
|||
_NODISCARD static constexpr long double signaling_NaN() noexcept {
|
||||
return __builtin_nans("1");
|
||||
}
|
||||
_STL_RESTORE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
|
||||
static constexpr int digits = LDBL_MANT_DIG;
|
||||
static constexpr int digits10 = LDBL_DIG;
|
||||
|
|
16
stl/inc/list
16
stl/inc/list
|
@ -751,6 +751,10 @@ private:
|
|||
template <class _Traits>
|
||||
class _Hash;
|
||||
|
||||
struct _Move_allocator_tag {
|
||||
explicit _Move_allocator_tag() = default;
|
||||
};
|
||||
|
||||
_EXPORT_STD template <class _Ty, class _Alloc = allocator<_Ty>>
|
||||
class list { // bidirectional linked list
|
||||
private:
|
||||
|
@ -804,8 +808,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
template <class _Any_alloc>
|
||||
explicit list(_Move_allocator_tag, _Any_alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _STD move(_Al)) {
|
||||
template <class _Tag, class _Any_alloc, enable_if_t<is_same_v<_Tag, _Move_allocator_tag>, int> = 0>
|
||||
explicit list(_Tag, _Any_alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _STD move(_Al)) {
|
||||
_Alloc_sentinel_and_proxy();
|
||||
}
|
||||
|
||||
|
@ -1662,12 +1666,12 @@ public:
|
|||
_Nodeptr* _Tail;
|
||||
};
|
||||
|
||||
auto remove(const _Ty& _Val) { // erase each element matching _Val
|
||||
_LIST_REMOVE_RETURN remove(const _Ty& _Val) { // erase each element matching _Val
|
||||
return remove_if([&](const _Ty& _Other) -> bool { return _Other == _Val; });
|
||||
}
|
||||
|
||||
template <class _Pr1>
|
||||
auto remove_if(_Pr1 _Pred) { // erase each element satisfying _Pred
|
||||
_LIST_REMOVE_RETURN remove_if(_Pr1 _Pred) { // erase each element satisfying _Pred
|
||||
auto& _My_data = _Mypair._Myval2;
|
||||
_List_node_remove_op _Op(*this);
|
||||
const auto _Last = _My_data._Myhead;
|
||||
|
@ -1688,12 +1692,12 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
auto unique() { // erase each element matching previous
|
||||
_LIST_REMOVE_RETURN unique() { // erase each element matching previous
|
||||
return unique(equal_to<>{});
|
||||
}
|
||||
|
||||
template <class _Pr2>
|
||||
auto unique(_Pr2 _Pred) { // erase each element satisfying _Pred with previous
|
||||
_LIST_REMOVE_RETURN unique(_Pr2 _Pred) { // erase each element satisfying _Pred with previous
|
||||
_List_node_remove_op _Op(*this);
|
||||
const _Nodeptr _Phead = _Mypair._Myval2._Myhead;
|
||||
_Nodeptr _Pprev = _Phead->_Next;
|
||||
|
|
|
@ -645,8 +645,7 @@ namespace ranges {
|
|||
template <_No_throw_input_iterator _It>
|
||||
requires destructible<iter_value_t<_It>>
|
||||
_STATIC_CALL_OPERATOR constexpr _It operator()(
|
||||
_It _First, const iter_difference_t<_It> _Count_raw) _CONST_CALL_OPERATOR noexcept {
|
||||
_Algorithm_int_t<iter_difference_t<_It>> _Count = _Count_raw;
|
||||
_It _First, iter_difference_t<_It> _Count) _CONST_CALL_OPERATOR noexcept {
|
||||
if (_Count <= 0) {
|
||||
return _First;
|
||||
}
|
||||
|
|
|
@ -40,15 +40,12 @@ struct _NODISCARD _Stream_lock_guard {
|
|||
|
||||
class _Print_to_stream_it {
|
||||
public:
|
||||
using iterator_category = output_iterator_tag;
|
||||
using value_type = void;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = void;
|
||||
using reference = void;
|
||||
using difference_type = ptrdiff_t;
|
||||
|
||||
explicit _Print_to_stream_it(FILE* const _Stream_) noexcept : _Stream(_Stream_) {}
|
||||
|
||||
_Print_to_stream_it& operator=(char); // These members are intentionally not defined
|
||||
// These member functions are never defined:
|
||||
_Print_to_stream_it& operator=(char);
|
||||
_Print_to_stream_it& operator*();
|
||||
_Print_to_stream_it& operator++();
|
||||
_Print_to_stream_it operator++(int);
|
||||
|
@ -79,16 +76,13 @@ struct _Fmt_iterator_flush<_Print_to_stream_it> {
|
|||
|
||||
class _Print_to_unicode_console_it {
|
||||
public:
|
||||
using iterator_category = output_iterator_tag;
|
||||
using value_type = void;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = void;
|
||||
using reference = void;
|
||||
using difference_type = ptrdiff_t;
|
||||
|
||||
explicit _Print_to_unicode_console_it(const __std_unicode_console_handle _Console_handle_) noexcept
|
||||
: _Console_handle(_Console_handle_) {}
|
||||
|
||||
_Print_to_unicode_console_it& operator=(char); // These members are intentionally not defined
|
||||
// These member functions are never defined:
|
||||
_Print_to_unicode_console_it& operator=(char);
|
||||
_Print_to_unicode_console_it& operator*();
|
||||
_Print_to_unicode_console_it& operator++();
|
||||
_Print_to_unicode_console_it operator++(int);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#if _HAS_CXX23
|
||||
#include <__msvc_ranges_to.hpp>
|
||||
#include <format>
|
||||
#include <__msvc_ranges_tuple_formatter.hpp>
|
||||
#include <iterator>
|
||||
#endif // _HAS_CXX23
|
||||
|
||||
|
@ -135,7 +135,7 @@ public:
|
|||
#endif // _HAS_CXX23
|
||||
|
||||
template <class... _Valty>
|
||||
_CONTAINER_EMPLACE_RETURN emplace(_Valty&&... _Val) {
|
||||
_ADAPTOR_EMPLACE_RETURN emplace(_Valty&&... _Val) {
|
||||
#if _HAS_CXX17
|
||||
return c.emplace_back(_STD forward<_Valty>(_Val)...);
|
||||
#else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv
|
||||
|
|
|
@ -7158,7 +7158,7 @@ namespace ranges {
|
|||
private:
|
||||
friend zip_view;
|
||||
|
||||
#ifdef __clang__ // TRANSITION, need to reduce and report (was thought to be LLVM-61763)
|
||||
#if defined(__clang__) && __clang_major__ <= 18 // TRANSITION, Clang 19 (was thought to be LLVM-61763)
|
||||
public:
|
||||
#else // ^^^ workaround / no workaround vvv
|
||||
template <class _Func, class... _OtherViews>
|
||||
|
@ -7983,7 +7983,7 @@ namespace ranges {
|
|||
private:
|
||||
friend adjacent_view;
|
||||
|
||||
#ifdef __clang__ // TRANSITION, need to reduce and report (was thought to be LLVM-61763)
|
||||
#if defined(__clang__) && __clang_major__ <= 18 // TRANSITION, Clang 19 (was thought to be LLVM-61763)
|
||||
public:
|
||||
#else // ^^^ workaround / no workaround vvv
|
||||
template <class _Vw2, class _Fn, size_t _Nx2>
|
||||
|
|
|
@ -239,7 +239,7 @@ public:
|
|||
// the buffer may already be full, and the terminating char is not '\0'.
|
||||
// In that case, copy the string as usual.
|
||||
_NODISCARD _Mystr str() && {
|
||||
_Mystr _Result{_String_constructor_rvalue_allocator_tag{}, _STD move(_Al)};
|
||||
_Mystr _Result{_Al};
|
||||
const auto _View = _Get_buffer_view();
|
||||
// _Size cannot be larger than _Res, but it could be equal,
|
||||
// because basic_stringbuf doesn't allocate for the terminating '\0'.
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#if _HAS_CXX23
|
||||
#include <__msvc_ranges_to.hpp>
|
||||
#include <format>
|
||||
#include <__msvc_ranges_tuple_formatter.hpp>
|
||||
#include <iterator>
|
||||
#endif // _HAS_CXX23
|
||||
|
||||
|
@ -120,7 +120,7 @@ public:
|
|||
#endif // _HAS_CXX23
|
||||
|
||||
template <class... _Valty>
|
||||
_CONTAINER_EMPLACE_RETURN emplace(_Valty&&... _Val) {
|
||||
_ADAPTOR_EMPLACE_RETURN emplace(_Valty&&... _Val) {
|
||||
#if _HAS_CXX17
|
||||
return c.emplace_back(_STD forward<_Valty>(_Val)...);
|
||||
#else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
_EMIT_STL_WARNING(STL4038, "The contents of <stacktrace> are available only with C++23 or later.");
|
||||
#else // ^^^ !_HAS_CXX23 / _HAS_CXX23 vvv
|
||||
|
||||
#include <__msvc_formatter.hpp>
|
||||
#include <cstdint>
|
||||
#include <format>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
@ -341,7 +341,8 @@ ostream& operator<<(ostream& _Os, const basic_stacktrace<_Alloc>& _St) {
|
|||
|
||||
template <>
|
||||
struct formatter<stacktrace_entry> {
|
||||
constexpr format_parse_context::iterator parse(format_parse_context& _Parse_ctx) {
|
||||
template <class _ParseContext = basic_format_parse_context<char>> // improves throughput, see GH-5003
|
||||
constexpr _ParseContext::iterator parse(type_identity_t<_ParseContext&> _Parse_ctx) {
|
||||
return _Impl._Parse(_Parse_ctx);
|
||||
}
|
||||
|
||||
|
@ -361,7 +362,8 @@ inline constexpr bool enable_nonlocking_formatter_optimization<stacktrace_entry>
|
|||
|
||||
template <class _Alloc>
|
||||
struct formatter<basic_stacktrace<_Alloc>> {
|
||||
constexpr format_parse_context::iterator parse(format_parse_context& _Parse_ctx) {
|
||||
template <class _ParseContext = basic_format_parse_context<char>> // improves throughput, see GH-5003
|
||||
constexpr _ParseContext::iterator parse(type_identity_t<_ParseContext&> _Parse_ctx) {
|
||||
const auto _First = _Parse_ctx.begin();
|
||||
if (_First != _Parse_ctx.end() && *_First != '}') {
|
||||
_Throw_format_error("For formatter<basic_stacktrace<Allocator>>, format-spec must be empty.");
|
||||
|
|
|
@ -573,13 +573,14 @@ public:
|
|||
|
||||
_NODISCARD string message(int _Errcode) const override {
|
||||
const _System_error_message _Msg(static_cast<unsigned long>(_Errcode));
|
||||
if (_Msg._Length == 0) {
|
||||
|
||||
if (_Msg._Str && _Msg._Length != 0) {
|
||||
// CodeQL [SM02310] _Msg's ctor inits _Str(nullptr) before doing work, then we test _Msg._Str above.
|
||||
return string{_Msg._Str, _Msg._Length};
|
||||
} else {
|
||||
static constexpr char _Unknown_error[] = "unknown error";
|
||||
constexpr size_t _Unknown_error_length = sizeof(_Unknown_error) - 1; // TRANSITION, DevCom-906503
|
||||
return string{_Unknown_error, _Unknown_error_length};
|
||||
} else {
|
||||
_STL_INTERNAL_CHECK(_Msg._Str != nullptr);
|
||||
return string{_Msg._Str, _Msg._Length}; // lgtm [cpp/uninitializedptrfield]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#endif // _HAS_CXX20
|
||||
|
||||
#if _HAS_CXX23
|
||||
#include <format>
|
||||
#include <__msvc_formatter.hpp>
|
||||
#endif // _HAS_CXX23
|
||||
|
||||
#pragma pack(push, _CRT_PACKING)
|
||||
|
@ -309,11 +309,8 @@ basic_ostream<_Ch, _Tr>& operator<<(basic_ostream<_Ch, _Tr>& _Str, thread::id _I
|
|||
// constrained to character types supported by `format`.
|
||||
template <_Format_supported_charT _CharT>
|
||||
struct formatter<thread::id, _CharT> {
|
||||
private:
|
||||
using _Pc = basic_format_parse_context<_CharT>;
|
||||
|
||||
public:
|
||||
constexpr _Pc::iterator parse(_Pc& _Parse_ctx) {
|
||||
template <class _Pc = basic_format_parse_context<_CharT>> // improves throughput, see GH-5003
|
||||
constexpr _Pc::iterator parse(type_identity_t<_Pc&> _Parse_ctx) {
|
||||
return _Impl._Parse(_Parse_ctx);
|
||||
}
|
||||
|
||||
|
|
|
@ -177,13 +177,12 @@ constexpr bool _Can_construct_values_from_tuple_like_v<tuple<_Types...>, _Other,
|
|||
|
||||
#ifdef __EDG__ // TRANSITION, VSO-1900279
|
||||
template <class _TupleLike, class _Tuple>
|
||||
concept _Can_construct_from_tuple_like =
|
||||
_Different_from<_TupleLike, _Tuple> && _Tuple_like<_TupleLike> && !_Is_subrange_v<remove_cvref_t<_TupleLike>>
|
||||
&& (tuple_size_v<_Tuple> == tuple_size_v<remove_cvref_t<_TupleLike>>) //
|
||||
&&_Can_construct_values_from_tuple_like_v<_Tuple, _TupleLike>
|
||||
&& (tuple_size_v<_Tuple> != 1
|
||||
|| (!is_convertible_v<_TupleLike, tuple_element_t<0, _Tuple>>
|
||||
&& !is_constructible_v<tuple_element_t<0, _Tuple>, _TupleLike>) );
|
||||
concept _Can_construct_from_tuple_like = _Different_from<_TupleLike, _Tuple> && _Tuple_like_non_subrange<_TupleLike>
|
||||
&& (tuple_size_v<_Tuple> == tuple_size_v<remove_cvref_t<_TupleLike>>)
|
||||
&& _Can_construct_values_from_tuple_like_v<_Tuple, _TupleLike>
|
||||
&& (tuple_size_v<_Tuple> != 1
|
||||
|| (!is_convertible_v<_TupleLike, tuple_element_t<0, _Tuple>>
|
||||
&& !is_constructible_v<tuple_element_t<0, _Tuple>, _TupleLike>) );
|
||||
#endif // ^^^ workaround ^^^
|
||||
|
||||
template <class _TTuple, class _UTuple, class _Indices = make_index_sequence<tuple_size_v<_UTuple>>>
|
||||
|
@ -421,8 +420,7 @@ public:
|
|||
template <class _Other, enable_if_t<_Can_construct_from_tuple_like<_Other, tuple>, int> = 0>
|
||||
#else // ^^^ workaround / no workaround vvv
|
||||
template <_Different_from<tuple> _Other>
|
||||
requires _Tuple_like<_Other> && (!_Is_subrange_v<remove_cvref_t<_Other>>)
|
||||
&& (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
|
||||
requires _Tuple_like_non_subrange<_Other> && (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
|
||||
&& _Can_construct_values_from_tuple_like_v<tuple, _Other>
|
||||
&& (sizeof...(_Rest) != 0 || (!is_convertible_v<_Other, _This> && !is_constructible_v<_This, _Other>) )
|
||||
#endif // ^^^ no workaround ^^^
|
||||
|
@ -527,8 +525,7 @@ public:
|
|||
template <class _Alloc, class _Other, enable_if_t<_Can_construct_from_tuple_like<_Other, tuple>, int> = 0>
|
||||
#else // ^^^ workaround / no workaround vvv
|
||||
template <class _Alloc, _Different_from<tuple> _Other>
|
||||
requires _Tuple_like<_Other> && (!_Is_subrange_v<remove_cvref_t<_Other>>)
|
||||
&& (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
|
||||
requires _Tuple_like_non_subrange<_Other> && (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
|
||||
&& _Can_construct_values_from_tuple_like_v<tuple, _Other>
|
||||
&& (sizeof...(_Rest) != 0 || (!is_convertible_v<_Other, _This> && !is_constructible_v<_This, _Other>) )
|
||||
#endif // ^^^ no workaround ^^^
|
||||
|
@ -692,8 +689,7 @@ public:
|
|||
}
|
||||
|
||||
template <_Different_from<tuple> _Other>
|
||||
requires _Tuple_like<_Other> && (!_Is_subrange_v<remove_cvref_t<_Other>>)
|
||||
&& (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
|
||||
requires _Tuple_like_non_subrange<_Other> && (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
|
||||
&& _Can_assign_values_from_tuple_like_v<false, _Other>
|
||||
constexpr tuple& operator=(_Other&& _Right) {
|
||||
_Assign_tuple_like(_STD forward<_Other>(_Right), make_index_sequence<1 + sizeof...(_Rest)>{});
|
||||
|
@ -701,8 +697,7 @@ public:
|
|||
}
|
||||
|
||||
template <_Different_from<tuple> _Other>
|
||||
requires _Tuple_like<_Other> && (!_Is_subrange_v<remove_cvref_t<_Other>>)
|
||||
&& (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
|
||||
requires _Tuple_like_non_subrange<_Other> && (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
|
||||
&& _Can_assign_values_from_tuple_like_v<true, _Other>
|
||||
constexpr const tuple& operator=(_Other&& _Right) const {
|
||||
_Assign_tuple_like(_STD forward<_Other>(_Right), make_index_sequence<1 + sizeof...(_Rest)>{});
|
||||
|
|
|
@ -205,28 +205,31 @@ constexpr bool _Is_subrange_v = false;
|
|||
|
||||
#if _HAS_CXX23
|
||||
template <class>
|
||||
constexpr bool _Tuple_like_impl = false;
|
||||
constexpr bool _Tuple_like_non_subrange_impl = false;
|
||||
|
||||
template <class... _Types>
|
||||
constexpr bool _Tuple_like_impl<tuple<_Types...>> = true;
|
||||
constexpr bool _Tuple_like_non_subrange_impl<tuple<_Types...>> = true;
|
||||
|
||||
template <class _Ty1, class _Ty2>
|
||||
constexpr bool _Tuple_like_impl<pair<_Ty1, _Ty2>> = true;
|
||||
constexpr bool _Tuple_like_non_subrange_impl<pair<_Ty1, _Ty2>> = true;
|
||||
|
||||
template <class _Ty, size_t _Size>
|
||||
constexpr bool _Tuple_like_impl<array<_Ty, _Size>> = true;
|
||||
constexpr bool _Tuple_like_non_subrange_impl<array<_Ty, _Size>> = true;
|
||||
|
||||
template <class _Ty>
|
||||
concept _Tuple_like = _Tuple_like_impl<remove_cvref_t<_Ty>>;
|
||||
concept _Tuple_like_non_subrange = _Tuple_like_non_subrange_impl<remove_cvref_t<_Ty>>;
|
||||
|
||||
template <class _Ty>
|
||||
concept _Pair_like = _Tuple_like<_Ty> && tuple_size_v<remove_cvref_t<_Ty>> == 2;
|
||||
concept _Tuple_like = _Tuple_like_non_subrange<_Ty> || _Is_subrange_v<remove_cvref_t<_Ty>>;
|
||||
|
||||
template <class _Ty>
|
||||
concept _Pair_like_non_subrange = _Tuple_like_non_subrange<_Ty> && tuple_size_v<remove_cvref_t<_Ty>> == 2;
|
||||
|
||||
#ifdef __EDG__ // TRANSITION, VSO-1900279
|
||||
template <class _PairLike, class _Ty1, class _Ty2>
|
||||
concept _Can_construct_from_pair_like = _Pair_like<_PairLike> && !_Is_subrange_v<remove_cvref_t<_PairLike>>
|
||||
&& is_constructible_v<_Ty1, decltype(_STD get<0>(_STD declval<_PairLike>()))>
|
||||
&& is_constructible_v<_Ty2, decltype(_STD get<1>(_STD declval<_PairLike>()))>;
|
||||
concept _Can_construct_from_pair_like =
|
||||
_Pair_like_non_subrange<_PairLike> && is_constructible_v<_Ty1, decltype(_STD get<0>(_STD declval<_PairLike>()))>
|
||||
&& is_constructible_v<_Ty2, decltype(_STD get<1>(_STD declval<_PairLike>()))>;
|
||||
#endif // ^^^ workaround ^^^
|
||||
#endif // _HAS_CXX23
|
||||
#endif // _HAS_CXX20
|
||||
|
@ -302,9 +305,8 @@ struct pair { // store a pair of values
|
|||
#ifdef __EDG__ // TRANSITION, VSO-1900279
|
||||
template <class _Other, enable_if_t<_Can_construct_from_pair_like<_Other, _Ty1, _Ty2>, int> = 0>
|
||||
#else // ^^^ workaround / no workaround vvv
|
||||
template <_Pair_like _Other>
|
||||
requires conjunction_v<bool_constant<!_Is_subrange_v<remove_cvref_t<_Other>>>,
|
||||
is_constructible<_Ty1, decltype(_STD get<0>(_STD declval<_Other>()))>,
|
||||
template <_Pair_like_non_subrange _Other>
|
||||
requires conjunction_v<is_constructible<_Ty1, decltype(_STD get<0>(_STD declval<_Other>()))>,
|
||||
is_constructible<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>>
|
||||
#endif // ^^^ no workaround ^^^
|
||||
constexpr explicit(!conjunction_v<is_convertible<decltype(_STD get<0>(_STD declval<_Other>())), _Ty1>,
|
||||
|
@ -315,11 +317,6 @@ struct pair { // store a pair of values
|
|||
}
|
||||
#endif // _HAS_CXX23
|
||||
|
||||
template <class _Tuple1, class _Tuple2, size_t... _Indices1, size_t... _Indices2>
|
||||
constexpr pair(_Tuple1& _Val1, _Tuple2& _Val2, index_sequence<_Indices1...>, index_sequence<_Indices2...>)
|
||||
: first(_STD _Tuple_get<_Indices1>(_STD move(_Val1))...),
|
||||
second(_STD _Tuple_get<_Indices2>(_STD move(_Val2))...) {}
|
||||
|
||||
template <class... _Types1, class... _Types2>
|
||||
_CONSTEXPR20 pair(piecewise_construct_t, tuple<_Types1...> _Val1, tuple<_Types2...> _Val2)
|
||||
: pair(_Val1, _Val2, index_sequence_for<_Types1...>{}, index_sequence_for<_Types2...>{}) {}
|
||||
|
@ -422,9 +419,8 @@ struct pair { // store a pair of values
|
|||
return *this;
|
||||
}
|
||||
|
||||
template <_Pair_like _Other>
|
||||
requires _Different_from<_Other, pair> && (!_Is_subrange_v<remove_cvref_t<_Other>>)
|
||||
&& is_assignable_v<_Ty1&, decltype(_STD get<0>(_STD declval<_Other>()))>
|
||||
template <_Pair_like_non_subrange _Other>
|
||||
requires _Different_from<_Other, pair> && is_assignable_v<_Ty1&, decltype(_STD get<0>(_STD declval<_Other>()))>
|
||||
&& is_assignable_v<_Ty2&, decltype(_STD get<1>(_STD declval<_Other>()))>
|
||||
constexpr pair& operator=(_Other&& _Right)
|
||||
noexcept(is_nothrow_assignable_v<_Ty1&, decltype(_STD get<0>(_STD declval<_Other>()))>
|
||||
|
@ -434,8 +430,8 @@ struct pair { // store a pair of values
|
|||
return *this;
|
||||
}
|
||||
|
||||
template <_Pair_like _Other>
|
||||
requires _Different_from<_Other, pair> && (!_Is_subrange_v<remove_cvref_t<_Other>>)
|
||||
template <_Pair_like_non_subrange _Other>
|
||||
requires _Different_from<_Other, pair>
|
||||
&& is_assignable_v<const _Ty1&, decltype(_STD get<0>(_STD declval<_Other>()))>
|
||||
&& is_assignable_v<const _Ty2&, decltype(_STD get<1>(_STD declval<_Other>()))>
|
||||
constexpr const pair& operator=(_Other&& _Right) const noexcept(
|
||||
|
@ -466,6 +462,12 @@ struct pair { // store a pair of values
|
|||
|
||||
_Ty1 first; // the first stored value
|
||||
_Ty2 second; // the second stored value
|
||||
|
||||
private:
|
||||
template <class _Tuple1, class _Tuple2, size_t... _Indices1, size_t... _Indices2>
|
||||
constexpr pair(_Tuple1& _Val1, _Tuple2& _Val2, index_sequence<_Indices1...>, index_sequence<_Indices2...>)
|
||||
: first(_STD _Tuple_get<_Indices1>(_STD move(_Val1))...),
|
||||
second(_STD _Tuple_get<_Indices2>(_STD move(_Val2))...) {}
|
||||
};
|
||||
|
||||
#if _HAS_CXX17
|
||||
|
|
|
@ -934,12 +934,13 @@ public:
|
|||
: _Mybase(in_place_index<0>) {} // value-initialize alternative 0
|
||||
|
||||
template <class _Ty,
|
||||
enable_if_t<sizeof...(_Types) != 0 //
|
||||
&& !is_same_v<_Remove_cvref_t<_Ty>, variant> //
|
||||
&& !_Is_specialization_v<_Remove_cvref_t<_Ty>, in_place_type_t> //
|
||||
&& !_Is_in_place_index_specialization<_Remove_cvref_t<_Ty>> //
|
||||
&& is_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty>, //
|
||||
int> = 0>
|
||||
enable_if_t<sizeof...(_Types) != 0 && !is_same_v<_Remove_cvref_t<_Ty>, variant>
|
||||
&& !_Is_specialization_v<_Remove_cvref_t<_Ty>, in_place_type_t>
|
||||
&& !_Is_in_place_index_specialization<_Remove_cvref_t<_Ty>>,
|
||||
int> = 0,
|
||||
// These enable_if_t constraints are distinct to enable short-circuiting and avoid
|
||||
// substitution into _Variant_init_type when the first constraint is not satisfied.
|
||||
enable_if_t<is_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty>, int> = 0>
|
||||
constexpr variant(_Ty&& _Obj) noexcept(is_nothrow_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty>)
|
||||
: _Mybase(in_place_index<_Variant_init_index<_Ty, _Types...>::value>, static_cast<_Ty&&>(_Obj)) {
|
||||
// initialize to the type selected by passing _Obj to the overload set f(Types)...
|
||||
|
@ -976,10 +977,12 @@ public:
|
|||
// initialize alternative _Idx from _Ilist and _Args...
|
||||
}
|
||||
|
||||
template <class _Ty, enable_if_t<!is_same_v<_Remove_cvref_t<_Ty>, variant>
|
||||
&& is_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty>
|
||||
&& is_assignable_v<_Variant_init_type<_Ty, _Types...>&, _Ty>,
|
||||
int> = 0>
|
||||
template <class _Ty, enable_if_t<!is_same_v<_Remove_cvref_t<_Ty>, variant>, int> = 0,
|
||||
// These enable_if_t constraints are distinct to enable short-circuiting and avoid
|
||||
// substitution into _Variant_init_type when the first constraint is not satisfied.
|
||||
enable_if_t<is_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty>
|
||||
&& is_assignable_v<_Variant_init_type<_Ty, _Types...>&, _Ty>,
|
||||
int> = 0>
|
||||
_CONSTEXPR20 variant& operator=(_Ty&& _Obj)
|
||||
noexcept(is_nothrow_assignable_v<_Variant_init_type<_Ty, _Types...>&, _Ty>
|
||||
&& is_nothrow_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty>) {
|
||||
|
|
140
stl/inc/vector
140
stl/inc/vector
|
@ -592,6 +592,60 @@ private:
|
|||
using _Scary_val = _Vector_val<conditional_t<_Is_simple_alloc_v<_Alty>, _Simple_types<_Ty>,
|
||||
_Vec_iter_types<_Ty, size_type, difference_type, pointer, const_pointer>>>;
|
||||
|
||||
struct _NODISCARD _Reallocation_guard {
|
||||
_Alloc& _Al;
|
||||
pointer _New_begin;
|
||||
size_type _New_capacity;
|
||||
pointer _Constructed_first;
|
||||
pointer _Constructed_last;
|
||||
|
||||
_Reallocation_guard& operator=(const _Reallocation_guard&) = delete;
|
||||
_Reallocation_guard& operator=(_Reallocation_guard&&) = delete;
|
||||
|
||||
_CONSTEXPR20 ~_Reallocation_guard() noexcept {
|
||||
if (_New_begin != nullptr) {
|
||||
_STD _Destroy_range(_Constructed_first, _Constructed_last, _Al);
|
||||
_Al.deallocate(_New_begin, _New_capacity);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct _NODISCARD _Simple_reallocation_guard {
|
||||
_Alloc& _Al;
|
||||
pointer _New_begin;
|
||||
size_type _New_capacity;
|
||||
|
||||
_Simple_reallocation_guard& operator=(const _Simple_reallocation_guard&) = delete;
|
||||
_Simple_reallocation_guard& operator=(_Simple_reallocation_guard&&) = delete;
|
||||
|
||||
_CONSTEXPR20 ~_Simple_reallocation_guard() noexcept {
|
||||
if (_New_begin != nullptr) {
|
||||
_Al.deallocate(_New_begin, _New_capacity);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct _NODISCARD _Vaporization_guard { // vaporize the detached piece
|
||||
vector* _Target;
|
||||
pointer _Vaporized_first;
|
||||
pointer _Vaporized_last;
|
||||
pointer _Destroyed_first;
|
||||
|
||||
_Vaporization_guard& operator=(const _Vaporization_guard&) = delete;
|
||||
_Vaporization_guard& operator=(_Vaporization_guard&&) = delete;
|
||||
|
||||
~_Vaporization_guard() noexcept {
|
||||
if (_Target != nullptr) {
|
||||
auto& _Al = _Target->_Getal();
|
||||
auto& _Mylast = _Target->_Mypair._Myval2._Mylast;
|
||||
|
||||
_Target->_Orphan_range(_Vaporized_first, _Vaporized_last);
|
||||
_STD _Destroy_range(_Destroyed_first, _Mylast, _Al);
|
||||
_Mylast = _Vaporized_first;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
using iterator = _Vector_iterator<_Scary_val>;
|
||||
using const_iterator = _Vector_const_iterator<_Scary_val>;
|
||||
|
@ -824,9 +878,10 @@ private:
|
|||
|
||||
const pointer _Newvec = _STD _Allocate_at_least_helper(_Al, _Newcapacity);
|
||||
const pointer _Constructed_last = _Newvec + _Whereoff + 1;
|
||||
pointer _Constructed_first = _Constructed_last;
|
||||
|
||||
_TRY_BEGIN
|
||||
_Reallocation_guard _Guard{_Al, _Newvec, _Newcapacity, _Constructed_last, _Constructed_last};
|
||||
auto& _Constructed_first = _Guard._Constructed_first;
|
||||
|
||||
_Alty_traits::construct(_Al, _STD _Unfancy(_Newvec + _Whereoff), _STD forward<_Valty>(_Val)...);
|
||||
_Constructed_first = _Newvec + _Whereoff;
|
||||
|
||||
|
@ -841,12 +896,8 @@ private:
|
|||
_Constructed_first = _Newvec;
|
||||
_STD _Uninitialized_move(_Whereptr, _Mylast, _Newvec + _Whereoff + 1, _Al);
|
||||
}
|
||||
_CATCH_ALL
|
||||
_STD _Destroy_range(_Constructed_first, _Constructed_last, _Al);
|
||||
_Al.deallocate(_Newvec, _Newcapacity);
|
||||
_RERAISE;
|
||||
_CATCH_END
|
||||
|
||||
_Guard._New_begin = nullptr;
|
||||
_Change_array(_Newvec, _Newsize, _Newcapacity);
|
||||
return _Newvec + _Whereoff;
|
||||
}
|
||||
|
@ -911,9 +962,10 @@ private:
|
|||
|
||||
const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity);
|
||||
const pointer _Constructed_last = _Newvec + _Oldsize + _Count;
|
||||
pointer _Constructed_first = _Constructed_last;
|
||||
|
||||
_TRY_BEGIN
|
||||
_Reallocation_guard _Guard{_Al, _Newvec, _Newcapacity, _Constructed_last, _Constructed_last};
|
||||
auto& _Constructed_first = _Guard._Constructed_first;
|
||||
|
||||
_Uninitialized_copy_n(_STD move(_First), _Count, _Newvec + _Oldsize, _Al);
|
||||
_Constructed_first = _Newvec + _Oldsize;
|
||||
|
||||
|
@ -926,12 +978,8 @@ private:
|
|||
} else { // provide basic guarantee
|
||||
_Uninitialized_move(_Oldfirst, _Oldlast, _Newvec, _Al);
|
||||
}
|
||||
_CATCH_ALL
|
||||
_Destroy_range(_Constructed_first, _Constructed_last, _Al);
|
||||
_Al.deallocate(_Newvec, _Newcapacity);
|
||||
_RERAISE;
|
||||
_CATCH_END
|
||||
|
||||
_Guard._New_begin = nullptr;
|
||||
_Change_array(_Newvec, _Newsize, _Newcapacity);
|
||||
} else { // Provide the strong guarantee.
|
||||
// Performance note: except for one-at-back, the strong guarantee is unnecessary here.
|
||||
|
@ -1032,9 +1080,10 @@ public:
|
|||
|
||||
const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity);
|
||||
const pointer _Constructed_last = _Newvec + _Whereoff + _Count;
|
||||
pointer _Constructed_first = _Constructed_last;
|
||||
|
||||
_TRY_BEGIN
|
||||
_Reallocation_guard _Guard{_Al, _Newvec, _Newcapacity, _Constructed_last, _Constructed_last};
|
||||
auto& _Constructed_first = _Guard._Constructed_first;
|
||||
|
||||
_Uninitialized_fill_n(_Newvec + _Whereoff, _Count, _Val, _Al);
|
||||
_Constructed_first = _Newvec + _Whereoff;
|
||||
|
||||
|
@ -1049,12 +1098,8 @@ public:
|
|||
_Constructed_first = _Newvec;
|
||||
_Uninitialized_move(_Whereptr, _Oldlast, _Newvec + _Whereoff + _Count, _Al);
|
||||
}
|
||||
_CATCH_ALL
|
||||
_Destroy_range(_Constructed_first, _Constructed_last, _Al);
|
||||
_Al.deallocate(_Newvec, _Newcapacity);
|
||||
_RERAISE;
|
||||
_CATCH_END
|
||||
|
||||
_Guard._New_begin = nullptr;
|
||||
_Change_array(_Newvec, _Newsize, _Newcapacity);
|
||||
} else if (_One_at_back) { // provide strong guarantee
|
||||
_Emplace_back_with_unused_capacity(_Val);
|
||||
|
@ -1128,9 +1173,10 @@ private:
|
|||
const pointer _Newvec = _STD _Allocate_at_least_helper(_Al, _Newcapacity);
|
||||
const auto _Whereoff = static_cast<size_type>(_Whereptr - _Oldfirst);
|
||||
const pointer _Constructed_last = _Newvec + _Whereoff + _Count;
|
||||
pointer _Constructed_first = _Constructed_last;
|
||||
|
||||
_TRY_BEGIN
|
||||
_Reallocation_guard _Guard{_Al, _Newvec, _Newcapacity, _Constructed_last, _Constructed_last};
|
||||
auto& _Constructed_first = _Guard._Constructed_first;
|
||||
|
||||
_STD _Uninitialized_copy_n(_STD move(_First), _Count, _Newvec + _Whereoff, _Al);
|
||||
_Constructed_first = _Newvec + _Whereoff;
|
||||
|
||||
|
@ -1145,12 +1191,8 @@ private:
|
|||
_Constructed_first = _Newvec;
|
||||
_STD _Uninitialized_move(_Whereptr, _Oldlast, _Newvec + _Whereoff + _Count, _Al);
|
||||
}
|
||||
_CATCH_ALL
|
||||
_STD _Destroy_range(_Constructed_first, _Constructed_last, _Al);
|
||||
_Al.deallocate(_Newvec, _Newcapacity);
|
||||
_RERAISE;
|
||||
_CATCH_END
|
||||
|
||||
_Guard._New_begin = nullptr;
|
||||
_Change_array(_Newvec, _Newsize, _Newcapacity);
|
||||
} else { // Attempt to provide the strong guarantee for EmplaceConstructible failure.
|
||||
// If we encounter copy/move construction/assignment failure, provide the basic guarantee.
|
||||
|
@ -1169,15 +1211,9 @@ private:
|
|||
_CATCH_ALL
|
||||
// glue the broken pieces back together
|
||||
|
||||
_TRY_BEGIN
|
||||
_Vaporization_guard _Guard{this, _Whereptr, _Oldlast, _Whereptr + _Count};
|
||||
_STD _Uninitialized_move(_Whereptr + _Count, _Whereptr + 2 * _Count, _Whereptr, _Al);
|
||||
_CATCH_ALL
|
||||
// vaporize the detached piece
|
||||
_Orphan_range(_Whereptr, _Oldlast);
|
||||
_STD _Destroy_range(_Whereptr + _Count, _Mylast, _Al);
|
||||
_Mylast = _Whereptr;
|
||||
_RERAISE;
|
||||
_CATCH_END
|
||||
_Guard._Target = nullptr;
|
||||
|
||||
_STD _Move_unchecked(_Whereptr + 2 * _Count, _Mylast, _Whereptr + _Count);
|
||||
_STD _Destroy_range(_Oldlast, _Mylast, _Al);
|
||||
|
@ -1194,15 +1230,9 @@ private:
|
|||
_CATCH_ALL
|
||||
// glue the broken pieces back together
|
||||
|
||||
_TRY_BEGIN
|
||||
_Vaporization_guard _Guard{this, _Whereptr, _Oldlast, _Relocated};
|
||||
_STD _Uninitialized_move(_Relocated, _Mylast, _Whereptr, _Al);
|
||||
_CATCH_ALL
|
||||
// vaporize the detached piece
|
||||
_Orphan_range(_Whereptr, _Oldlast);
|
||||
_STD _Destroy_range(_Relocated, _Mylast, _Al);
|
||||
_Mylast = _Whereptr;
|
||||
_RERAISE;
|
||||
_CATCH_END
|
||||
_Guard._Target = nullptr;
|
||||
|
||||
_STD _Destroy_range(_Relocated, _Mylast, _Al);
|
||||
_Mylast = _Oldlast;
|
||||
|
@ -1517,9 +1547,10 @@ private:
|
|||
|
||||
const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity);
|
||||
const pointer _Appended_first = _Newvec + _Oldsize;
|
||||
pointer _Appended_last = _Appended_first;
|
||||
|
||||
_TRY_BEGIN
|
||||
_Reallocation_guard _Guard{_Al, _Newvec, _Newcapacity, _Appended_first, _Appended_first};
|
||||
auto& _Appended_last = _Guard._Constructed_last;
|
||||
|
||||
if constexpr (is_same_v<_Ty2, _Ty>) {
|
||||
_Appended_last = _Uninitialized_fill_n(_Appended_first, _Newsize - _Oldsize, _Val, _Al);
|
||||
} else {
|
||||
|
@ -1532,12 +1563,8 @@ private:
|
|||
} else {
|
||||
_Uninitialized_copy(_Myfirst, _Mylast, _Newvec, _Al);
|
||||
}
|
||||
_CATCH_ALL
|
||||
_Destroy_range(_Appended_first, _Appended_last, _Al);
|
||||
_Al.deallocate(_Newvec, _Newcapacity);
|
||||
_RERAISE;
|
||||
_CATCH_END
|
||||
|
||||
_Guard._New_begin = nullptr;
|
||||
_Change_array(_Newvec, _Newsize, _Newcapacity);
|
||||
}
|
||||
|
||||
|
@ -1612,17 +1639,15 @@ private:
|
|||
_Newvec = _Al.allocate(_Newcapacity);
|
||||
}
|
||||
|
||||
_TRY_BEGIN
|
||||
_Simple_reallocation_guard _Guard{_Al, _Newvec, _Newcapacity};
|
||||
|
||||
if constexpr (is_nothrow_move_constructible_v<_Ty> || !is_copy_constructible_v<_Ty>) {
|
||||
_Uninitialized_move(_Myfirst, _Mylast, _Newvec, _Al);
|
||||
} else {
|
||||
_Uninitialized_copy(_Myfirst, _Mylast, _Newvec, _Al);
|
||||
}
|
||||
_CATCH_ALL
|
||||
_Al.deallocate(_Newvec, _Newcapacity);
|
||||
_RERAISE;
|
||||
_CATCH_END
|
||||
|
||||
_Guard._New_begin = nullptr;
|
||||
_Change_array(_Newvec, _Size, _Newcapacity);
|
||||
}
|
||||
|
||||
|
@ -2013,7 +2038,8 @@ private:
|
|||
_Buy_raw(_Newcapacity);
|
||||
}
|
||||
|
||||
_CONSTEXPR20 void _Change_array(const pointer _Newvec, const size_type _Newsize, const size_type _Newcapacity) {
|
||||
_CONSTEXPR20 void _Change_array(
|
||||
const pointer _Newvec, const size_type _Newsize, const size_type _Newcapacity) noexcept {
|
||||
// orphan all iterators, discard old array, acquire new array
|
||||
auto& _Al = _Getal();
|
||||
auto& _My_data = _Mypair._Myval2;
|
||||
|
|
|
@ -37,9 +37,11 @@ _NODISCARD inline unsigned long _Floor_of_log_2(size_t _Value) noexcept { // ret
|
|||
}
|
||||
#else // ^^^ defined(_M_CEE_PURE) / !defined(_M_CEE_PURE) vvv
|
||||
#ifdef _WIN64
|
||||
_BitScanReverse64(&_Result, _Value); // lgtm [cpp/conditionallyuninitializedvariable]
|
||||
// CodeQL [SM02313] _Result is always initialized: the code above guarantees that _Value is non-zero.
|
||||
_BitScanReverse64(&_Result, _Value);
|
||||
#else // ^^^ 64-bit / 32-bit vvv
|
||||
_BitScanReverse(&_Result, _Value); // lgtm [cpp/conditionallyuninitializedvariable]
|
||||
// CodeQL [SM02313] _Result is always initialized: the code above guarantees that _Value is non-zero.
|
||||
_BitScanReverse(&_Result, _Value);
|
||||
#endif // ^^^ 32-bit ^^^
|
||||
#endif // ^^^ !defined(_M_CEE_PURE) ^^^
|
||||
|
||||
|
|
|
@ -106,29 +106,6 @@ protected:
|
|||
_Tidy();
|
||||
}
|
||||
|
||||
template <class _Elem2>
|
||||
void _Getvals(_Elem2, const lconv* _Ptr) { // get values
|
||||
_Currencysign = _Maklocstr(
|
||||
_International ? _Ptr->int_curr_symbol : _Ptr->currency_symbol, static_cast<_Elem2*>(nullptr), _Cvt);
|
||||
_Plussign = _Maklocstr(4 < static_cast<unsigned int>(_Ptr->p_sign_posn) ? "" : _Ptr->positive_sign,
|
||||
static_cast<_Elem2*>(nullptr), _Cvt);
|
||||
_Minussign = _Maklocstr(4 < static_cast<unsigned int>(_Ptr->n_sign_posn) ? "-" : _Ptr->negative_sign,
|
||||
static_cast<_Elem2*>(nullptr), _Cvt);
|
||||
_Decimalpoint = _Maklocchr(_Ptr->mon_decimal_point[0], static_cast<_Elem2*>(nullptr), _Cvt);
|
||||
_Kseparator = _Maklocchr(_Ptr->mon_thousands_sep[0], static_cast<_Elem2*>(nullptr), _Cvt);
|
||||
}
|
||||
|
||||
void _Getvals(wchar_t, const lconv* _Ptr) { // get values
|
||||
_Currencysign = reinterpret_cast<const _Elem*>(
|
||||
_Maklocwcs(_International ? _Ptr->_W_int_curr_symbol : _Ptr->_W_currency_symbol));
|
||||
_Plussign = reinterpret_cast<const _Elem*>(
|
||||
_Maklocwcs(4 < static_cast<unsigned int>(_Ptr->p_sign_posn) ? L"" : _Ptr->_W_positive_sign));
|
||||
_Minussign = reinterpret_cast<const _Elem*>(
|
||||
_Maklocwcs(4 < static_cast<unsigned int>(_Ptr->n_sign_posn) ? L"-" : _Ptr->_W_negative_sign));
|
||||
_Decimalpoint = static_cast<_Elem>(_Ptr->_W_mon_decimal_point[0]);
|
||||
_Kseparator = static_cast<_Elem>(_Ptr->_W_mon_thousands_sep[0]);
|
||||
}
|
||||
|
||||
void _Init(const _Locinfo& _Lobj, bool _Isdef = false) { // initialize from _Lobj
|
||||
_Cvt = _Lobj._Getcvt();
|
||||
const lconv* _Ptr = _Lobj._Getlconv();
|
||||
|
@ -140,7 +117,23 @@ protected:
|
|||
|
||||
_Tidy_guard<_Mpunct> _Guard{this};
|
||||
_Grouping = _Maklocstr(_Ptr->mon_grouping, static_cast<char*>(nullptr), _Cvt);
|
||||
_Getvals(_Elem{}, _Ptr);
|
||||
if constexpr (is_same_v<_Elem, wchar_t>) {
|
||||
_Currencysign = _Maklocwcs(_International ? _Ptr->_W_int_curr_symbol : _Ptr->_W_currency_symbol);
|
||||
_Plussign = _Maklocwcs(4 < static_cast<unsigned int>(_Ptr->p_sign_posn) ? L"" : _Ptr->_W_positive_sign);
|
||||
_Minussign = _Maklocwcs(4 < static_cast<unsigned int>(_Ptr->n_sign_posn) ? L"-" : _Ptr->_W_negative_sign);
|
||||
_Decimalpoint = _Ptr->_W_mon_decimal_point[0];
|
||||
_Kseparator = _Ptr->_W_mon_thousands_sep[0];
|
||||
} else {
|
||||
_Currencysign = _Maklocstr(
|
||||
_International ? _Ptr->int_curr_symbol : _Ptr->currency_symbol, static_cast<_Elem*>(nullptr), _Cvt);
|
||||
_Plussign = _Maklocstr(4 < static_cast<unsigned int>(_Ptr->p_sign_posn) ? "" : _Ptr->positive_sign,
|
||||
static_cast<_Elem*>(nullptr), _Cvt);
|
||||
_Minussign = _Maklocstr(4 < static_cast<unsigned int>(_Ptr->n_sign_posn) ? "-" : _Ptr->negative_sign,
|
||||
static_cast<_Elem*>(nullptr), _Cvt);
|
||||
_Decimalpoint = _Maklocchr(_Ptr->mon_decimal_point[0], static_cast<_Elem*>(nullptr), _Cvt);
|
||||
_Kseparator = _Maklocchr(_Ptr->mon_thousands_sep[0], static_cast<_Elem*>(nullptr), _Cvt);
|
||||
}
|
||||
|
||||
_Guard._Target = nullptr;
|
||||
|
||||
_Fracdigits = _International ? _Ptr->int_frac_digits : _Ptr->frac_digits;
|
||||
|
|
|
@ -149,17 +149,6 @@ protected:
|
|||
_END_LOCINFO()
|
||||
}
|
||||
|
||||
template <class _Elem2>
|
||||
void _Getvals(_Elem2, const lconv* _Ptr, _Locinfo::_Cvtvec _Cvt) { // get values
|
||||
_Dp = _Maklocchr(_Ptr->decimal_point[0], static_cast<_Elem2*>(nullptr), _Cvt);
|
||||
_Kseparator = _Maklocchr(_Ptr->thousands_sep[0], static_cast<_Elem2*>(nullptr), _Cvt);
|
||||
}
|
||||
|
||||
void _Getvals(wchar_t, const lconv* _Ptr, _Locinfo::_Cvtvec) { // get values
|
||||
_Dp = static_cast<_Elem>(_Ptr->_W_decimal_point[0]);
|
||||
_Kseparator = static_cast<_Elem>(_Ptr->_W_thousands_sep[0]);
|
||||
}
|
||||
|
||||
void _Init(const _Locinfo& _Lobj, bool _Isdef = false) { // initialize from _Lobj
|
||||
const lconv* _Ptr = _Lobj._Getlconv();
|
||||
_Locinfo::_Cvtvec _Cvt = _Lobj._Getcvt(); // conversion information
|
||||
|
@ -169,17 +158,22 @@ protected:
|
|||
_Truename = nullptr;
|
||||
|
||||
_Tidy_guard<numpunct> _Guard{this};
|
||||
_Grouping = _Maklocstr(_Isdef ? "" : _Ptr->grouping, static_cast<char*>(nullptr), _Lobj._Getcvt());
|
||||
_Grouping = _Maklocstr(_Isdef ? "" : _Ptr->grouping, static_cast<char*>(nullptr), _Cvt);
|
||||
_Falsename = _Maklocstr(_Lobj._Getfalse(), static_cast<_Elem*>(nullptr), _Cvt);
|
||||
_Truename = _Maklocstr(_Lobj._Gettrue(), static_cast<_Elem*>(nullptr), _Cvt);
|
||||
_Guard._Target = nullptr;
|
||||
|
||||
if (_Isdef) { // apply defaults for required facets
|
||||
// _Grouping = _Maklocstr("", static_cast<char *>(nullptr), _Cvt);
|
||||
_Dp = _Maklocchr('.', static_cast<_Elem*>(nullptr), _Cvt);
|
||||
_Kseparator = _Maklocchr(',', static_cast<_Elem*>(nullptr), _Cvt);
|
||||
} else {
|
||||
_Getvals(_Elem{}, _Ptr, _Cvt);
|
||||
if constexpr (is_same_v<_Elem, wchar_t>) {
|
||||
_Dp = _Ptr->_W_decimal_point[0];
|
||||
_Kseparator = _Ptr->_W_thousands_sep[0];
|
||||
} else {
|
||||
_Dp = _Maklocchr(_Ptr->decimal_point[0], static_cast<_Elem*>(nullptr), _Cvt);
|
||||
_Kseparator = _Maklocchr(_Ptr->thousands_sep[0], static_cast<_Elem*>(nullptr), _Cvt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ protected:
|
|||
void __CLR_OR_THIS_CALL _Getvals(_Elem2, const _Locinfo& _Lobj) { // get values
|
||||
_Cvt = _Lobj._Getcvt();
|
||||
|
||||
if (is_same_v<_Elem2, wchar_t>) {
|
||||
if constexpr (is_same_v<_Elem2, wchar_t>) {
|
||||
_Days = reinterpret_cast<const _Elem*>(_Maklocwcs(reinterpret_cast<const wchar_t*>(_Lobj._W_Getdays())));
|
||||
_Months =
|
||||
reinterpret_cast<const _Elem*>(_Maklocwcs(reinterpret_cast<const wchar_t*>(_Lobj._W_Getmonths())));
|
||||
|
|
|
@ -92,30 +92,24 @@ _NODISCARD constexpr size_t _Get_size_of_n(const size_t _Count) {
|
|||
template <class _Ty>
|
||||
constexpr size_t _New_alignof = (_STD max)(alignof(_Ty), __STDCPP_DEFAULT_NEW_ALIGNMENT__);
|
||||
|
||||
struct _Default_allocate_traits {
|
||||
__declspec(allocator) static
|
||||
#ifdef __clang__ // Clang and MSVC implement P0784R7 differently; see GH-1532
|
||||
_CONSTEXPR20
|
||||
#endif // defined(__clang__)
|
||||
void*
|
||||
_Allocate(const size_t _Bytes) {
|
||||
#define _CLANG_CONSTEXPR20 _CONSTEXPR20
|
||||
#else // ^^^ Clang / Other vvv
|
||||
#define _CLANG_CONSTEXPR20
|
||||
#endif // ^^^ Other ^^^
|
||||
|
||||
struct _Default_allocate_traits {
|
||||
__declspec(allocator) static _CLANG_CONSTEXPR20 void* _Allocate(const size_t _Bytes) {
|
||||
return ::operator new(_Bytes);
|
||||
}
|
||||
|
||||
#ifdef __cpp_aligned_new
|
||||
__declspec(allocator) static
|
||||
#ifdef __clang__ // Clang and MSVC implement P0784R7 differently; see GH-1532
|
||||
_CONSTEXPR20
|
||||
#endif // defined(__clang__)
|
||||
void*
|
||||
_Allocate_aligned(const size_t _Bytes, const size_t _Align) {
|
||||
#ifdef __clang__ // Clang and MSVC implement P0784R7 differently; see GH-1532
|
||||
#if _HAS_CXX20
|
||||
__declspec(allocator) static _CLANG_CONSTEXPR20 void* _Allocate_aligned(const size_t _Bytes, const size_t _Align) {
|
||||
#if defined(__clang__) && _HAS_CXX20 // Ditto, "Clang and MSVC implement P0784R7 differently"
|
||||
if (_STD is_constant_evaluated()) {
|
||||
return ::operator new(_Bytes);
|
||||
} else
|
||||
#endif // _HAS_CXX20
|
||||
#endif // defined(__clang__)
|
||||
#endif // ^^^ defined(__clang__) && _HAS_CXX20 ^^^
|
||||
{
|
||||
return ::operator new(_Bytes, align_val_t{_Align});
|
||||
}
|
||||
|
@ -123,6 +117,8 @@ struct _Default_allocate_traits {
|
|||
#endif // defined(__cpp_aligned_new)
|
||||
};
|
||||
|
||||
#undef _CLANG_CONSTEXPR20
|
||||
|
||||
constexpr bool _Is_pow_2(const size_t _Value) noexcept {
|
||||
return _Value != 0 && (_Value & (_Value - 1)) == 0;
|
||||
}
|
||||
|
@ -681,7 +677,8 @@ struct _Default_allocator_traits { // traits for std::allocator
|
|||
}
|
||||
#endif // _HAS_CXX23
|
||||
|
||||
static _CONSTEXPR20 void deallocate(_Alloc& _Al, const pointer _Ptr, const size_type _Count) {
|
||||
static _CONSTEXPR20 void deallocate(_Alloc& _Al, const pointer _Ptr, const size_type _Count) noexcept
|
||||
/* strengthened */ {
|
||||
// no overflow check on the following multiply; we assume _Allocate did that check
|
||||
#if _HAS_CXX20 // TRANSITION, GH-1532
|
||||
if (_STD is_constant_evaluated()) {
|
||||
|
@ -945,7 +942,7 @@ public:
|
|||
_CONSTEXPR20 ~allocator() = default;
|
||||
_CONSTEXPR20 allocator& operator=(const allocator&) = default;
|
||||
|
||||
_CONSTEXPR20 void deallocate(_Ty* const _Ptr, const size_t _Count) {
|
||||
_CONSTEXPR20 void deallocate(_Ty* const _Ptr, const size_t _Count) noexcept /* strengthened */ {
|
||||
_STL_ASSERT(_Ptr != nullptr || _Count == 0, "null pointer cannot point to a block of non-zero size");
|
||||
// no overflow check on the following multiply; we assume _Allocate did that check
|
||||
_STD _Deallocate<_New_alignof<_Ty>>(_Ptr, sizeof(_Ty) * _Count);
|
||||
|
@ -1535,10 +1532,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct _Move_allocator_tag {
|
||||
explicit _Move_allocator_tag() = default;
|
||||
};
|
||||
|
||||
template <class _Ty>
|
||||
pair<_Ty*, ptrdiff_t> _Get_temporary_buffer(ptrdiff_t _Count) noexcept {
|
||||
if (static_cast<size_t>(_Count) <= static_cast<size_t>(-1) / sizeof(_Ty)) {
|
||||
|
@ -1800,6 +1793,10 @@ _CONSTEXPR20 _Alloc_ptr_t<_Alloc> _Uninitialized_copy(
|
|||
// note: only called internally from elsewhere in the STL
|
||||
using _Ptrval = typename _Alloc::value_type*;
|
||||
|
||||
#ifdef _ENABLE_STL_INTERNAL_CHECK
|
||||
_STD _Adl_verify_range(_First, _Last);
|
||||
#endif // ^^^ defined(_ENABLE_STL_INTERNAL_CHECK) ^^^
|
||||
|
||||
#if _HAS_CXX20
|
||||
auto _UFirst = _RANGES _Unwrap_iter<_Se>(_STD move(_First));
|
||||
auto _ULast = _RANGES _Unwrap_sent<_InIt>(_STD move(_Last));
|
||||
|
@ -1845,7 +1842,11 @@ _CONSTEXPR20 _Alloc_ptr_t<_Alloc> _Uninitialized_copy_n(
|
|||
// note: only called internally from elsewhere in the STL
|
||||
using _Ptrval = typename _Alloc::value_type*;
|
||||
|
||||
#ifdef _ENABLE_STL_INTERNAL_CHECK
|
||||
auto _UFirst = _STD _Get_unwrapped_n(_STD move(_First), _Count);
|
||||
#else // ^^^ Checking / No checking vvv
|
||||
auto _UFirst = _STD _Get_unwrapped(_STD move(_First));
|
||||
#endif // ^^^ No checking ^^^
|
||||
|
||||
constexpr bool _Can_memmove =
|
||||
conjunction_v<bool_constant<_Iter_copy_cat<decltype(_UFirst), _Ptrval>::_Bitcopy_constructible>,
|
||||
|
@ -1906,6 +1907,9 @@ _CONSTEXPR20 _Alloc_ptr_t<_Alloc> _Uninitialized_move(
|
|||
const _InIt _First, const _InIt _Last, _Alloc_ptr_t<_Alloc> _Dest, _Alloc& _Al) {
|
||||
// move [_First, _Last) to raw _Dest, using _Al
|
||||
// note: only called internally from elsewhere in the STL
|
||||
#ifdef _ENABLE_STL_INTERNAL_CHECK
|
||||
_STD _Adl_verify_range(_First, _Last);
|
||||
#endif // ^^^ defined(_ENABLE_STL_INTERNAL_CHECK) ^^^
|
||||
using _Ptrval = typename _Alloc::value_type*;
|
||||
auto _UFirst = _STD _Get_unwrapped(_First);
|
||||
const auto _ULast = _STD _Get_unwrapped(_Last);
|
||||
|
@ -2435,7 +2439,7 @@ _NODISCARD constexpr auto uses_allocator_construction_args(
|
|||
_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, _Usable_for_pair_like_overload _Uty>
|
||||
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Uty&& _Ux) noexcept {
|
||||
#if _HAS_CXX23
|
||||
if constexpr (_Pair_like<_Uty> && !_Is_subrange_v<remove_cvref_t<_Uty>>) {
|
||||
if constexpr (_Pair_like_non_subrange<_Uty>) {
|
||||
// equivalent to
|
||||
// return _STD uses_allocator_construction_args<_Ty>(_Al, piecewise_construct,
|
||||
// _STD forward_as_tuple(_STD get<0>(_STD forward<_Uty>(_Ux)),
|
||||
|
@ -2643,12 +2647,24 @@ _NODISCARD _Elem* _UIntegral_to_buff(_Elem* _RNext, _UTy _UVal) { // used by bot
|
|||
}
|
||||
_STD_END
|
||||
|
||||
#if _HAS_CXX17
|
||||
#define _ADAPTOR_EMPLACE_RETURN decltype(auto)
|
||||
#else // ^^^ _HAS_CXX17 ^^^ / vvv !_HAS_CXX17 vvv
|
||||
#define _ADAPTOR_EMPLACE_RETURN void
|
||||
#endif // ^^^ !_HAS_CXX17 ^^^
|
||||
|
||||
#if _HAS_CXX17
|
||||
#define _CONTAINER_EMPLACE_RETURN reference
|
||||
#else // ^^^ _HAS_CXX17 ^^^ / vvv !_HAS_CXX17 vvv
|
||||
#define _CONTAINER_EMPLACE_RETURN void
|
||||
#endif // ^^^ !_HAS_CXX17 ^^^
|
||||
|
||||
#if _HAS_CXX20
|
||||
#define _LIST_REMOVE_RETURN size_type
|
||||
#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv
|
||||
#define _LIST_REMOVE_RETURN void
|
||||
#endif // ^^^ !_HAS_CXX20 ^^^
|
||||
|
||||
#pragma pop_macro("new")
|
||||
_STL_RESTORE_CLANG_WARNINGS
|
||||
#pragma warning(pop)
|
||||
|
|
|
@ -508,11 +508,6 @@ struct _String_constructor_concat_tag {
|
|||
explicit _String_constructor_concat_tag() = default;
|
||||
};
|
||||
|
||||
struct _String_constructor_rvalue_allocator_tag {
|
||||
// tag to select constructors used by basic_stringbuf's rvalue str()
|
||||
explicit _String_constructor_rvalue_allocator_tag() = default;
|
||||
};
|
||||
|
||||
[[noreturn]] inline void _Xlen_string() {
|
||||
_Xlength_error("string too long");
|
||||
}
|
||||
|
@ -1145,12 +1140,6 @@ public:
|
|||
#endif // _HAS_CXX17
|
||||
|
||||
#if _HAS_CXX20
|
||||
basic_string(_String_constructor_rvalue_allocator_tag, _Alloc&& _Al)
|
||||
: _Mypair(_One_then_variadic_args_t{}, _STD move(_Al)) {
|
||||
// Used exclusively by basic_stringbuf
|
||||
_Construct_empty();
|
||||
}
|
||||
|
||||
_NODISCARD bool _Move_assign_from_buffer(
|
||||
_Elem* const _Right, const size_type _Size, const size_type _Actual_allocation_size) {
|
||||
// Move assign from a buffer, used exclusively by basic_stringbuf; returns _Large_mode_engaged()
|
||||
|
|
155
stl/inc/xutility
155
stl/inc/xutility
|
@ -777,13 +777,6 @@ struct _Unused_parameter { // generic unused parameter struct
|
|||
constexpr _Unused_parameter(_Ty&&) noexcept {}
|
||||
};
|
||||
|
||||
template <class _Ty, class = void> // checks whether a container/view is a non-customized specialization
|
||||
constexpr bool _Has_unchecked_begin_end = false;
|
||||
|
||||
template <class _Ty>
|
||||
constexpr bool _Has_unchecked_begin_end<_Ty,
|
||||
void_t<decltype(_STD declval<_Ty&>()._Unchecked_begin()), decltype(_STD declval<_Ty&>()._Unchecked_end())>> = true;
|
||||
|
||||
template <class _Ty>
|
||||
using _Algorithm_int_t = conditional_t<is_integral_v<_Ty>, _Ty, ptrdiff_t>;
|
||||
|
||||
|
@ -1409,6 +1402,12 @@ struct _Distance_unknown {
|
|||
}
|
||||
};
|
||||
|
||||
struct _Distance_unbounded {
|
||||
_NODISCARD constexpr _Distance_unbounded operator-() const noexcept {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Diff>
|
||||
constexpr _Diff _Max_possible_v{static_cast<_Make_unsigned_like_t<_Diff>>(-1) >> 1};
|
||||
|
||||
|
@ -1430,7 +1429,7 @@ template <class _Iter, class _Diff>
|
|||
_NODISCARD constexpr decltype(auto) _Get_unwrapped_n(_Iter&& _It, const _Diff _Off) {
|
||||
if constexpr (is_pointer_v<decay_t<_Iter>>) {
|
||||
return _It + 0;
|
||||
} else if constexpr (_Unwrappable_for_offset_v<_Iter> && is_integral_v<_Diff>) {
|
||||
} else if constexpr (_Unwrappable_for_offset_v<_Iter> && _Integer_like<_Diff>) {
|
||||
// ask an iterator to assert that the iterator moved _Off positions is valid, and unwrap
|
||||
using _IDiff = _Iter_diff_t<_Remove_cvref_t<_Iter>>;
|
||||
using _CDiff = common_type_t<_Diff, _IDiff>;
|
||||
|
@ -1533,15 +1532,35 @@ using _Enable_if_execution_policy_t = typename remove_reference_t<_ExPo>::_Stand
|
|||
|
||||
#endif // _HAS_CXX17
|
||||
|
||||
#if _HAS_CXX20
|
||||
_EXPORT_STD struct unreachable_sentinel_t;
|
||||
|
||||
template <class _Checked, class _Iter, class _Sent>
|
||||
_NODISCARD constexpr auto _Idl_distance(const _Iter& _First, const _Sent& _Last) {
|
||||
// Returns the distance between _First and _Last,
|
||||
// an indicator that the distance is infinite, or
|
||||
// an indicator that the distance cannot be determined in O(1).
|
||||
_STL_INTERNAL_STATIC_ASSERT(same_as<_Unwrapped_t<_Checked>, _Iter>);
|
||||
|
||||
if constexpr (sized_sentinel_for<_Sent, _Iter>) {
|
||||
return static_cast<iter_difference_t<_Checked>>(_Last - _First);
|
||||
} else if constexpr (same_as<_Sent, unreachable_sentinel_t>) {
|
||||
return _Distance_unbounded{};
|
||||
} else {
|
||||
return _Distance_unknown{};
|
||||
}
|
||||
}
|
||||
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
|
||||
template <class _Checked, class _Iter>
|
||||
_NODISCARD constexpr auto _Idl_distance(const _Iter& _First, const _Iter& _Last) {
|
||||
// tries to get the distance between _First and _Last if they are random-access iterators
|
||||
if constexpr (_Is_ranges_random_iter_v<_Iter>) {
|
||||
_STL_INTERNAL_STATIC_ASSERT(is_same_v<_Unwrapped_t<_Checked>, _Iter>);
|
||||
if constexpr (_Is_cpp17_random_iter_v<_Iter>) {
|
||||
return static_cast<_Iter_diff_t<_Checked>>(_Last - _First);
|
||||
} else {
|
||||
return _Distance_unknown{};
|
||||
}
|
||||
}
|
||||
#endif // ^^^ !_HAS_CXX20 ^^^
|
||||
|
||||
template <class _Elem, bool _Is_enum = is_enum_v<_Elem>>
|
||||
struct _Unwrap_enum { // if _Elem is an enum, gets its underlying type; otherwise leaves _Elem unchanged
|
||||
|
@ -3563,6 +3582,20 @@ namespace ranges {
|
|||
|
||||
_EXPORT_STD inline constexpr _Distance_fn distance;
|
||||
|
||||
template <range _Rng>
|
||||
_NODISCARD constexpr auto _Idl_distance(_Rng& _Range) {
|
||||
// Returns the length of _Range if it is finite and can be determined in O(1), or
|
||||
// an indicator that the length is infinite, or
|
||||
// an indicator that the length cannot be determined in O(1).
|
||||
if constexpr (sized_range<_Rng>) {
|
||||
return _RANGES distance(_Range);
|
||||
} else if constexpr (same_as<sentinel_t<_Rng>, unreachable_sentinel_t>) {
|
||||
return _Distance_unbounded{};
|
||||
} else {
|
||||
return _Distance_unknown{};
|
||||
}
|
||||
}
|
||||
|
||||
class _Ssize_fn {
|
||||
public:
|
||||
template <class _Rng>
|
||||
|
@ -3874,6 +3907,21 @@ namespace ranges {
|
|||
};
|
||||
} // namespace ranges
|
||||
|
||||
#if _HAS_CXX23
|
||||
template <class _Ty>
|
||||
concept _Pair_like = _Tuple_like<_Ty> && tuple_size_v<remove_cvref_t<_Ty>> == 2;
|
||||
#else // ^^^ _HAS_CXX23 / !_HAS_CXX23 vvv
|
||||
template <class _Ty>
|
||||
concept _Pair_like = !is_reference_v<_Ty> && requires(_Ty __t) {
|
||||
typename tuple_size<_Ty>::type;
|
||||
requires derived_from<tuple_size<_Ty>, integral_constant<size_t, 2>>;
|
||||
typename tuple_element_t<0, remove_const_t<_Ty>>;
|
||||
typename tuple_element_t<1, remove_const_t<_Ty>>;
|
||||
{ _STD get<0>(__t) } -> convertible_to<const tuple_element_t<0, _Ty>&>;
|
||||
{ _STD get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Ty>&>;
|
||||
};
|
||||
#endif // ^^^ !_HAS_CXX23 ^^^
|
||||
|
||||
namespace ranges {
|
||||
template <class _From, class _To>
|
||||
concept _Uses_nonqualification_pointer_conversion =
|
||||
|
@ -3884,18 +3932,6 @@ namespace ranges {
|
|||
concept _Convertible_to_non_slicing =
|
||||
convertible_to<_From, _To> && !_Uses_nonqualification_pointer_conversion<decay_t<_From>, decay_t<_To>>;
|
||||
|
||||
#if !_HAS_CXX23
|
||||
template <class _Ty>
|
||||
concept _Pair_like = !is_reference_v<_Ty> && requires(_Ty __t) {
|
||||
typename tuple_size<_Ty>::type;
|
||||
requires derived_from<tuple_size<_Ty>, integral_constant<size_t, 2>>;
|
||||
typename tuple_element_t<0, remove_const_t<_Ty>>;
|
||||
typename tuple_element_t<1, remove_const_t<_Ty>>;
|
||||
{ _STD get<0>(__t) } -> convertible_to<const tuple_element_t<0, _Ty>&>;
|
||||
{ _STD get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Ty>&>;
|
||||
};
|
||||
#endif // !_HAS_CXX23
|
||||
|
||||
template <class _Ty, class _First, class _Second>
|
||||
concept _Pair_like_convertible_from = !range<_Ty>
|
||||
#if _HAS_CXX23
|
||||
|
@ -3963,12 +3999,15 @@ namespace ranges {
|
|||
template <_Convertible_to_non_slicing<_It> _It2>
|
||||
constexpr subrange(_It2 _First_, _Se _Last_)
|
||||
requires (!_Store_size<_It, _Se, _Ki>)
|
||||
: _First(_STD move(_First_)), _Last(_STD move(_Last_)) {}
|
||||
: _First(_STD move(_First_)), _Last(_STD move(_Last_)) {
|
||||
_STD _Adl_verify_range(_First, _Last);
|
||||
}
|
||||
|
||||
template <_Convertible_to_non_slicing<_It> _It2>
|
||||
constexpr subrange(_It2 _First_, _Se _Last_, const _Size_type _Size_)
|
||||
requires (_Ki == subrange_kind::sized)
|
||||
: _Subrange_base<_It, _Se, _Ki>(_Size_), _First(_STD move(_First_)), _Last(_STD move(_Last_)) {
|
||||
_STD _Adl_verify_range(_First, _Last);
|
||||
if constexpr (sized_sentinel_for<_Se, _It>) {
|
||||
_STL_ASSERT(_Size_ == static_cast<_Size_type>(_Last - _First),
|
||||
"This constructor's third argument should be equal to the distance "
|
||||
|
@ -3989,10 +4028,10 @@ namespace ranges {
|
|||
requires (_Ki == subrange_kind::sized)
|
||||
: subrange{_RANGES begin(_Val), _RANGES end(_Val), _Count} {}
|
||||
|
||||
template <_Different_from<subrange> _Pair_like>
|
||||
requires _Pair_like_convertible_from<_Pair_like, const _It&, const _Se&>
|
||||
constexpr operator _Pair_like() const {
|
||||
return _Pair_like(_First, _Last);
|
||||
template <_Different_from<subrange> _PairLike>
|
||||
requires _Pair_like_convertible_from<_PairLike, const _It&, const _Se&>
|
||||
constexpr operator _PairLike() const {
|
||||
return _PairLike(_First, _Last);
|
||||
}
|
||||
|
||||
_NODISCARD constexpr _It begin() const
|
||||
|
@ -4520,16 +4559,12 @@ template <class _Iter1, class _Iter2>
|
|||
requires (!sized_sentinel_for<_Iter1, _Iter2>)
|
||||
constexpr bool disable_sized_sentinel_for<move_iterator<_Iter1>, move_iterator<_Iter2>> = true;
|
||||
|
||||
_EXPORT_STD struct unreachable_sentinel_t;
|
||||
namespace _Unreachable_sentinel_detail {
|
||||
struct _Base {
|
||||
template <weakly_incrementable _Winc>
|
||||
_NODISCARD friend constexpr bool operator==(const unreachable_sentinel_t&, const _Winc&) noexcept {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} // namespace _Unreachable_sentinel_detail
|
||||
_EXPORT_STD struct unreachable_sentinel_t : _Unreachable_sentinel_detail::_Base {}; // TRANSITION, /permissive-
|
||||
_EXPORT_STD struct unreachable_sentinel_t {
|
||||
template <weakly_incrementable _Ty>
|
||||
_NODISCARD constexpr bool operator==(const _Ty&) const noexcept {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
_EXPORT_STD inline constexpr unreachable_sentinel_t unreachable_sentinel{};
|
||||
#endif // _HAS_CXX20
|
||||
|
@ -4684,7 +4719,8 @@ _OutCtgIt _Copy_memmove(_CtgIt _First, _CtgIt _Last, _OutCtgIt _Dest) {
|
|||
const auto _Count = static_cast<size_t>(_Last_ch - _First_ch);
|
||||
_CSTD memmove(_Dest_ch, _First_ch, _Count);
|
||||
if constexpr (is_pointer_v<_OutCtgIt>) {
|
||||
return reinterpret_cast<_OutCtgIt>(_Dest_ch + _Count); // lgtm [cpp/incorrect-string-type-conversion]
|
||||
// CodeQL [SM02986] This cast is correct: we're bypassing pointer arithmetic for performance.
|
||||
return reinterpret_cast<_OutCtgIt>(_Dest_ch + _Count);
|
||||
} else {
|
||||
return _Dest + static_cast<_Iter_diff_t<_OutCtgIt>>(_LastPtr - _FirstPtr);
|
||||
}
|
||||
|
@ -4895,50 +4931,55 @@ namespace ranges {
|
|||
|
||||
template <input_iterator _It, sentinel_for<_It> _Se, weakly_incrementable _Out>
|
||||
requires indirectly_copyable<_It, _Out>
|
||||
_NODISCARD constexpr copy_result<_It, _Out> _Copy_unchecked(_It _First, _Se _Last, _Out _Result) {
|
||||
_NODISCARD constexpr copy_result<_It, _Out> _Copy_unchecked(_It _First, _Se _Last, _Out _Output) {
|
||||
if constexpr (_Sent_copy_cat<_It, _Se, _Out>::_Bitcopy_assignable) {
|
||||
if (!_STD is_constant_evaluated()) {
|
||||
if constexpr (is_same_v<_It, _Se>) {
|
||||
_Result = _STD _Copy_memmove(_STD move(_First), _Last, _STD move(_Result));
|
||||
return {_STD move(_Last), _STD move(_Result)};
|
||||
_Output = _STD _Copy_memmove(_STD move(_First), _Last, _STD move(_Output));
|
||||
return {_STD move(_Last), _STD move(_Output)};
|
||||
} else {
|
||||
const auto _Count = static_cast<size_t>(_Last - _First);
|
||||
_Result = _STD _Copy_memmove_n(_First, _Count, _STD move(_Result));
|
||||
_Output = _STD _Copy_memmove_n(_First, _Count, _STD move(_Output));
|
||||
_First += _Count;
|
||||
return {_STD move(_First), _STD move(_Result)};
|
||||
return {_STD move(_First), _STD move(_Output)};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (; _First != _Last; ++_First, (void) ++_Result) {
|
||||
*_Result = *_First;
|
||||
for (; _First != _Last; ++_First, (void) ++_Output) {
|
||||
*_Output = *_First;
|
||||
}
|
||||
|
||||
return {_STD move(_First), _STD move(_Result)};
|
||||
return {_STD move(_First), _STD move(_Output)};
|
||||
}
|
||||
|
||||
class _Copy_fn {
|
||||
public:
|
||||
struct _Copy_fn {
|
||||
template <input_iterator _It, sentinel_for<_It> _Se, weakly_incrementable _Out>
|
||||
requires indirectly_copyable<_It, _Out>
|
||||
_STATIC_CALL_OPERATOR constexpr copy_result<_It, _Out> operator()(
|
||||
_It _First, _Se _Last, _Out _Result) _CONST_CALL_OPERATOR {
|
||||
_It _First, _Se _Last, _Out _Output) _CONST_CALL_OPERATOR {
|
||||
_STD _Adl_verify_range(_First, _Last);
|
||||
auto _UResult = _RANGES _Copy_unchecked(_RANGES _Unwrap_iter<_Se>(_STD move(_First)),
|
||||
_RANGES _Unwrap_sent<_It>(_STD move(_Last)), _STD move(_Result));
|
||||
auto _UFirst = _RANGES _Unwrap_iter<_Se>(_STD move(_First));
|
||||
auto _ULast = _RANGES _Unwrap_sent<_It>(_STD move(_Last));
|
||||
const auto _Count = _STD _Idl_distance<_It>(_UFirst, _ULast);
|
||||
auto _UResult = _RANGES _Copy_unchecked(
|
||||
_STD move(_UFirst), _STD move(_ULast), _STD _Get_unwrapped_n(_STD move(_Output), _Count));
|
||||
_STD _Seek_wrapped(_First, _STD move(_UResult.in));
|
||||
return {_STD move(_First), _STD move(_UResult.out)};
|
||||
_STD _Seek_wrapped(_Output, _STD move(_UResult.out));
|
||||
return {_STD move(_First), _STD move(_Output)};
|
||||
}
|
||||
|
||||
template <input_range _Rng, weakly_incrementable _Out>
|
||||
requires indirectly_copyable<iterator_t<_Rng>, _Out>
|
||||
_STATIC_CALL_OPERATOR constexpr copy_result<borrowed_iterator_t<_Rng>, _Out> operator()(
|
||||
_Rng&& _Range, _Out _Result) _CONST_CALL_OPERATOR {
|
||||
auto _First = _RANGES begin(_Range);
|
||||
auto _UResult = _RANGES _Copy_unchecked(
|
||||
_RANGES _Unwrap_range_iter<_Rng>(_STD move(_First)), _Uend(_Range), _STD move(_Result));
|
||||
_Rng&& _Range, _Out _Output) _CONST_CALL_OPERATOR {
|
||||
const auto _Count = _RANGES _Idl_distance(_Range);
|
||||
auto _First = _RANGES begin(_Range);
|
||||
auto _UResult = _RANGES _Copy_unchecked(_RANGES _Unwrap_range_iter<_Rng>(_STD move(_First)), _Uend(_Range),
|
||||
_STD _Get_unwrapped_n(_STD move(_Output), _Count));
|
||||
_STD _Seek_wrapped(_First, _STD move(_UResult.in));
|
||||
return {_STD move(_First), _STD move(_UResult.out)};
|
||||
_STD _Seek_wrapped(_Output, _STD move(_UResult.out));
|
||||
return {_STD move(_First), _STD move(_Output)};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -861,6 +861,30 @@
|
|||
#endif // ^^^ !defined(__clang__) ^^^
|
||||
#endif // !defined(_STL_RESTORE_CLANG_WARNINGS)
|
||||
|
||||
// warning: use of NaN is undefined behavior due to the currently enabled
|
||||
// floating-point options [-Wnan-infinity-disabled]
|
||||
// warning: use of infinity is undefined behavior due to the currently enabled
|
||||
// floating-point options [-Wnan-infinity-disabled]
|
||||
#ifndef _STL_DISABLE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
#ifdef __clang__
|
||||
// clang-format off
|
||||
#define _STL_DISABLE_CLANG_WARNING_NAN_INF_DISABLED \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Wnan-infinity-disabled\"")
|
||||
// clang-format on
|
||||
#else // ^^^ defined(__clang__) / !defined(__clang__) vvv
|
||||
#define _STL_DISABLE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
#endif // ^^^ !defined(__clang__) ^^^
|
||||
#endif // !defined(_STL_DISABLE_CLANG_WARNING_NAN_INF_DISABLED)
|
||||
|
||||
#ifndef _STL_RESTORE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
#ifdef __clang__
|
||||
#define _STL_RESTORE_CLANG_WARNING_NAN_INF_DISABLED _Pragma("clang diagnostic pop")
|
||||
#else // ^^^ defined(__clang__) / !defined(__clang__) vvv
|
||||
#define _STL_RESTORE_CLANG_WARNING_NAN_INF_DISABLED
|
||||
#endif // ^^^ !defined(__clang__) ^^^
|
||||
#endif // !defined(_STL_RESTORE_CLANG_WARNING_NAN_INF_DISABLED)
|
||||
|
||||
// clang-format off
|
||||
#ifndef _STL_DISABLE_DEPRECATED_WARNING
|
||||
#ifdef __clang__
|
||||
|
@ -891,7 +915,7 @@
|
|||
|
||||
#define _CPPLIB_VER 650
|
||||
#define _MSVC_STL_VERSION 143
|
||||
#define _MSVC_STL_UPDATE 202409L
|
||||
#define _MSVC_STL_UPDATE 202410L
|
||||
|
||||
#ifndef _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH
|
||||
#if defined(__CUDACC__) && defined(__CUDACC_VER_MAJOR__)
|
||||
|
@ -905,8 +929,8 @@ _EMIT_STL_ERROR(STL1002, "Unexpected compiler version, expected CUDA 12.4 or new
|
|||
_EMIT_STL_ERROR(STL1000, "Unexpected compiler version, expected Clang 18.0.0 or newer.");
|
||||
#endif // ^^^ old Clang ^^^
|
||||
#elif defined(_MSC_VER)
|
||||
#if _MSC_VER < 1941 // Coarse-grained, not inspecting _MSC_FULL_VER
|
||||
_EMIT_STL_ERROR(STL1001, "Unexpected compiler version, expected MSVC 19.41 or newer.");
|
||||
#if _MSC_VER < 1942 // Coarse-grained, not inspecting _MSC_FULL_VER
|
||||
_EMIT_STL_ERROR(STL1001, "Unexpected compiler version, expected MSVC 19.42 or newer.");
|
||||
#endif // ^^^ old MSVC ^^^
|
||||
#else // vvv other compilers vvv
|
||||
// not attempting to detect other compilers
|
||||
|
|
|
@ -82,7 +82,8 @@ extern "C" _CRTIMP2 int __cdecl __crtLCMapStringA(_In_opt_z_ LPCWSTR LocaleName,
|
|||
return retval;
|
||||
}
|
||||
|
||||
const auto wide_dest = reinterpret_cast<LPWSTR>(lpDestStr); // lgtm [cpp/incorrect-string-type-conversion]
|
||||
// CodeQL [SM02986] This cast is correct: LCMAP_SORTKEY stores "an opaque array of bytes".
|
||||
const auto wide_dest = reinterpret_cast<LPWSTR>(lpDestStr);
|
||||
|
||||
// do string mapping
|
||||
if (0
|
||||
|
|
|
@ -548,9 +548,10 @@ namespace {
|
|||
|
||||
#ifndef _M_ARM64EC
|
||||
struct _Minmax_traits_sse_base {
|
||||
static constexpr bool _Vectorized = true;
|
||||
static constexpr size_t _Vec_size = 16;
|
||||
static constexpr size_t _Vec_mask = 0xF;
|
||||
static constexpr bool _Vectorized = true;
|
||||
static constexpr size_t _Vec_size = 16;
|
||||
static constexpr size_t _Vec_mask = 0xF;
|
||||
static constexpr size_t _Tail_mask = 0;
|
||||
|
||||
static __m128i _Zero() noexcept {
|
||||
return _mm_setzero_si128();
|
||||
|
@ -596,6 +597,18 @@ namespace {
|
|||
_mm256_zeroupper();
|
||||
}
|
||||
};
|
||||
|
||||
struct _Minmax_traits_avx_i_base : _Minmax_traits_avx_base {
|
||||
static constexpr size_t _Tail_mask = 0x1C;
|
||||
|
||||
static __m256i _Blendval(const __m256i _Px1, const __m256i _Px2, const __m256i _Msk) noexcept {
|
||||
return _mm256_blendv_epi8(_Px1, _Px2, _Msk);
|
||||
}
|
||||
|
||||
static __m256i _Load_mask(const void* _Src, const __m256i _Mask) noexcept {
|
||||
return _mm256_maskload_epi32(reinterpret_cast<const int*>(_Src), _Mask);
|
||||
}
|
||||
};
|
||||
#endif // !defined(_M_ARM64EC)
|
||||
|
||||
struct _Minmax_traits_1_base {
|
||||
|
@ -702,7 +715,7 @@ namespace {
|
|||
}
|
||||
};
|
||||
|
||||
struct _Minmax_traits_1_avx : _Minmax_traits_1_base, _Minmax_traits_avx_base {
|
||||
struct _Minmax_traits_1_avx : _Minmax_traits_1_base, _Minmax_traits_avx_i_base {
|
||||
static __m256i _Load(const void* _Src) noexcept {
|
||||
return _mm256_loadu_si256(reinterpret_cast<const __m256i*>(_Src));
|
||||
}
|
||||
|
@ -898,7 +911,7 @@ namespace {
|
|||
}
|
||||
};
|
||||
|
||||
struct _Minmax_traits_2_avx : _Minmax_traits_2_base, _Minmax_traits_avx_base {
|
||||
struct _Minmax_traits_2_avx : _Minmax_traits_2_base, _Minmax_traits_avx_i_base {
|
||||
static __m256i _Load(const void* _Src) noexcept {
|
||||
return _mm256_loadu_si256(reinterpret_cast<const __m256i*>(_Src));
|
||||
}
|
||||
|
@ -1091,7 +1104,7 @@ namespace {
|
|||
}
|
||||
};
|
||||
|
||||
struct _Minmax_traits_4_avx : _Minmax_traits_4_base, _Minmax_traits_avx_base {
|
||||
struct _Minmax_traits_4_avx : _Minmax_traits_4_base, _Minmax_traits_avx_i_base {
|
||||
static __m256i _Load(const void* _Src) noexcept {
|
||||
return _mm256_loadu_si256(reinterpret_cast<const __m256i*>(_Src));
|
||||
}
|
||||
|
@ -1279,7 +1292,7 @@ namespace {
|
|||
}
|
||||
};
|
||||
|
||||
struct _Minmax_traits_8_avx : _Minmax_traits_8_base, _Minmax_traits_avx_base {
|
||||
struct _Minmax_traits_8_avx : _Minmax_traits_8_base, _Minmax_traits_avx_i_base {
|
||||
static __m256i _Load(const void* _Src) noexcept {
|
||||
return _mm256_loadu_si256(reinterpret_cast<const __m256i*>(_Src));
|
||||
}
|
||||
|
@ -1471,10 +1484,20 @@ namespace {
|
|||
};
|
||||
|
||||
struct _Minmax_traits_f_avx : _Minmax_traits_f_base, _Minmax_traits_avx_base {
|
||||
static constexpr size_t _Tail_mask = 0x1C;
|
||||
|
||||
static __m256 _Blendval(const __m256 _Px1, const __m256 _Px2, const __m256i _Msk) noexcept {
|
||||
return _mm256_blendv_ps(_Px1, _Px2, _mm256_castsi256_ps(_Msk));
|
||||
}
|
||||
|
||||
static __m256 _Load(const void* _Src) noexcept {
|
||||
return _mm256_loadu_ps(reinterpret_cast<const float*>(_Src));
|
||||
}
|
||||
|
||||
static __m256 _Load_mask(const void* _Src, const __m256i _Mask) noexcept {
|
||||
return _mm256_maskload_ps(reinterpret_cast<const float*>(_Src), _Mask);
|
||||
}
|
||||
|
||||
static __m256 _Sign_correction(const __m256 _Val, bool) noexcept {
|
||||
return _Val;
|
||||
}
|
||||
|
@ -1629,10 +1652,20 @@ namespace {
|
|||
};
|
||||
|
||||
struct _Minmax_traits_d_avx : _Minmax_traits_d_base, _Minmax_traits_avx_base {
|
||||
static constexpr size_t _Tail_mask = 0x18;
|
||||
|
||||
static __m256d _Blendval(const __m256d _Px1, const __m256d _Px2, const __m256i _Msk) noexcept {
|
||||
return _mm256_blendv_pd(_Px1, _Px2, _mm256_castsi256_pd(_Msk));
|
||||
}
|
||||
|
||||
static __m256d _Load(const void* _Src) noexcept {
|
||||
return _mm256_loadu_pd(reinterpret_cast<const double*>(_Src));
|
||||
}
|
||||
|
||||
static __m256d _Load_mask(const void* _Src, const __m256i _Mask) noexcept {
|
||||
return _mm256_maskload_pd(reinterpret_cast<const double*>(_Src), _Mask);
|
||||
}
|
||||
|
||||
static __m256d _Sign_correction(const __m256d _Val, bool) noexcept {
|
||||
return _Val;
|
||||
}
|
||||
|
@ -1779,6 +1812,39 @@ namespace {
|
|||
auto _Cur_idx_max = _Traits::_Zero(); // vector of vertical maximum indices
|
||||
auto _Cur_idx = _Traits::_Zero(); // current vector of indices
|
||||
|
||||
const auto _Update_min_max = [&](const auto _Cur_vals, [[maybe_unused]] const auto _Blend_idx_0,
|
||||
const auto _Blend_idx_1) noexcept {
|
||||
if constexpr ((_Mode & _Mode_min) != 0) {
|
||||
// Looking for the first occurrence of minimum, don't overwrite with newly found occurrences
|
||||
const auto _Is_less = _Traits::_Cmp_gt(_Cur_vals_min, _Cur_vals); // _Cur_vals < _Cur_vals_min
|
||||
// Remember their vertical indices
|
||||
_Cur_idx_min = _Blend_idx_1(_Cur_idx_min, _Cur_idx, _Traits::_Mask_cast(_Is_less));
|
||||
_Cur_vals_min = _Traits::_Min(_Cur_vals_min, _Cur_vals, _Is_less); // Update the current minimum
|
||||
}
|
||||
|
||||
if constexpr (_Mode == _Mode_max) {
|
||||
// Looking for the first occurrence of maximum, don't overwrite with newly found occurrences
|
||||
const auto _Is_greater = _Traits::_Cmp_gt(_Cur_vals, _Cur_vals_max); // _Cur_vals > _Cur_vals_max
|
||||
// Remember their vertical indices
|
||||
_Cur_idx_max = _Blend_idx_1(_Cur_idx_max, _Cur_idx, _Traits::_Mask_cast(_Is_greater));
|
||||
_Cur_vals_max = _Traits::_Max(_Cur_vals_max, _Cur_vals, _Is_greater); // Update the current maximum
|
||||
} else if constexpr (_Mode == _Mode_both) {
|
||||
// Looking for the last occurrence of maximum, do overwrite with newly found occurrences
|
||||
const auto _Is_less = _Traits::_Cmp_gt(_Cur_vals_max, _Cur_vals); // !(_Cur_vals >= _Cur_vals_max)
|
||||
// Remember their vertical indices
|
||||
_Cur_idx_max = _Blend_idx_0(_Cur_idx_max, _Cur_idx, _Traits::_Mask_cast(_Is_less));
|
||||
_Cur_vals_max = _Traits::_Max(_Cur_vals, _Cur_vals_max, _Is_less); // Update the current maximum
|
||||
}
|
||||
};
|
||||
|
||||
const auto _Blend_idx_0 = [](const auto _Prev, const auto _Cur, const auto _Mask) noexcept {
|
||||
return _Traits::_Blend(_Cur, _Prev, _Mask);
|
||||
};
|
||||
|
||||
const auto _Blend_idx_1 = [](const auto _Prev, const auto _Cur, const auto _Mask) noexcept {
|
||||
return _Traits::_Blend(_Prev, _Cur, _Mask);
|
||||
};
|
||||
|
||||
for (;;) {
|
||||
_Advance_bytes(_First, _Traits::_Vec_size);
|
||||
|
||||
|
@ -1791,31 +1857,41 @@ namespace {
|
|||
// Load values and if unsigned adjust them to be signed (for signed vector comparisons)
|
||||
_Cur_vals = _Traits::_Sign_correction(_Traits::_Load(_First), _Sign);
|
||||
|
||||
if constexpr ((_Mode & _Mode_min) != 0) {
|
||||
// Looking for the first occurrence of minimum, don't overwrite with newly found occurrences
|
||||
const auto _Is_less = _Traits::_Cmp_gt(_Cur_vals_min, _Cur_vals); // _Cur_vals < _Cur_vals_min
|
||||
_Cur_idx_min = _Traits::_Blend(
|
||||
_Cur_idx_min, _Cur_idx, _Traits::_Mask_cast(_Is_less)); // Remember their vertical indices
|
||||
_Cur_vals_min = _Traits::_Min(_Cur_vals_min, _Cur_vals, _Is_less); // Update the current minimum
|
||||
_Update_min_max(_Cur_vals, _Blend_idx_0, _Blend_idx_1);
|
||||
} else {
|
||||
if constexpr (_Traits::_Tail_mask != 0) {
|
||||
const size_t _Remaining_byte_size = _Byte_length(_First, _Last);
|
||||
bool _Last_portion;
|
||||
|
||||
if constexpr (_Traits::_Has_portion_max) {
|
||||
_Last_portion = (_Remaining_byte_size & ~_Traits::_Vec_mask) == 0;
|
||||
} else {
|
||||
_Last_portion = true;
|
||||
}
|
||||
|
||||
const size_t _Tail_byte_size = _Remaining_byte_size & _Traits::_Tail_mask;
|
||||
|
||||
if (_Last_portion && _Tail_byte_size != 0) {
|
||||
const auto _Tail_mask = _Avx2_tail_mask_32(_Tail_byte_size >> 2);
|
||||
const auto _Tail_vals =
|
||||
_Traits::_Sign_correction(_Traits::_Load_mask(_First, _Tail_mask), _Sign);
|
||||
_Cur_vals = _Traits::_Blendval(_Cur_vals, _Tail_vals, _Tail_mask);
|
||||
|
||||
const auto _Blend_idx_0_mask = [_Tail_mask](const auto _Prev, const auto _Cur,
|
||||
const auto _Mask) noexcept {
|
||||
return _Traits::_Blend(_Prev, _Cur, _mm256_andnot_si256(_Mask, _Tail_mask));
|
||||
};
|
||||
|
||||
const auto _Blend_idx_1_mask = [_Tail_mask](const auto _Prev, const auto _Cur,
|
||||
const auto _Mask) noexcept {
|
||||
return _Traits::_Blend(_Prev, _Cur, _mm256_and_si256(_Tail_mask, _Mask));
|
||||
};
|
||||
|
||||
_Update_min_max(_Cur_vals, _Blend_idx_0_mask, _Blend_idx_1_mask);
|
||||
_Advance_bytes(_First, _Tail_byte_size);
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (_Mode == _Mode_max) {
|
||||
// Looking for the first occurrence of maximum, don't overwrite with newly found occurrences
|
||||
const auto _Is_greater =
|
||||
_Traits::_Cmp_gt(_Cur_vals, _Cur_vals_max); // _Cur_vals > _Cur_vals_max
|
||||
_Cur_idx_max = _Traits::_Blend(_Cur_idx_max, _Cur_idx,
|
||||
_Traits::_Mask_cast(_Is_greater)); // Remember their vertical indices
|
||||
_Cur_vals_max =
|
||||
_Traits::_Max(_Cur_vals_max, _Cur_vals, _Is_greater); // Update the current maximum
|
||||
} else if constexpr (_Mode == _Mode_both) {
|
||||
// Looking for the last occurrence of maximum, do overwrite with newly found occurrences
|
||||
const auto _Is_less =
|
||||
_Traits::_Cmp_gt(_Cur_vals_max, _Cur_vals); // !(_Cur_vals >= _Cur_vals_max)
|
||||
_Cur_idx_max = _Traits::_Blend(_Cur_idx, _Cur_idx_max,
|
||||
_Traits::_Mask_cast(_Is_less)); // Remember their vertical indices
|
||||
_Cur_vals_max = _Traits::_Max(_Cur_vals, _Cur_vals_max, _Is_less); // Update the current maximum
|
||||
}
|
||||
} else {
|
||||
// Reached end or indices wrap around point.
|
||||
// Compute horizontal min and/or max. Determine horizontal and vertical position of it.
|
||||
|
||||
|
@ -1837,7 +1913,9 @@ namespace {
|
|||
unsigned long _H_pos;
|
||||
|
||||
// Find the smallest horizontal index
|
||||
_BitScanForward(&_H_pos, _Mask); // lgtm [cpp/conditionallyuninitializedvariable]
|
||||
|
||||
// CodeQL [SM02313] _H_pos is always initialized: element exists, so _Mask is non-zero.
|
||||
_BitScanForward(&_H_pos, _Mask);
|
||||
|
||||
const auto _V_pos = _Traits::_Get_v_pos(_Cur_idx_min, _H_pos); // Extract its vertical index
|
||||
// Finally, compute the pointer
|
||||
|
@ -1869,7 +1947,9 @@ namespace {
|
|||
_Mask &= _Traits::_Mask(_Traits::_Cmp_eq_idx(_Idx_max, _Idx_max_val));
|
||||
|
||||
// Find the largest horizontal index
|
||||
_BitScanReverse(&_H_pos, _Mask); // lgtm [cpp/conditionallyuninitializedvariable]
|
||||
|
||||
// CodeQL [SM02313] _H_pos is always initialized: element exists, so _Mask is non-zero.
|
||||
_BitScanReverse(&_H_pos, _Mask);
|
||||
|
||||
_H_pos -= sizeof(_Cur_max_val) - 1; // Correct from highest val bit to lowest
|
||||
} else {
|
||||
|
@ -1882,7 +1962,9 @@ namespace {
|
|||
_Mask &= _Traits::_Mask(_Traits::_Cmp_eq_idx(_Idx_max, _Idx_max_val));
|
||||
|
||||
// Find the smallest horizontal index
|
||||
_BitScanForward(&_H_pos, _Mask); // lgtm [cpp/conditionallyuninitializedvariable]
|
||||
|
||||
// CodeQL [SM02313] _H_pos is always initialized: element exists, so _Mask is non-zero.
|
||||
_BitScanForward(&_H_pos, _Mask);
|
||||
}
|
||||
|
||||
const auto _V_pos = _Traits::_Get_v_pos(_Cur_idx_max, _H_pos); // Extract its vertical index
|
||||
|
@ -1992,10 +2074,11 @@ namespace {
|
|||
#ifdef _M_ARM64EC
|
||||
static_assert(false, "No vectorization for _M_ARM64EC yet");
|
||||
#else // ^^^ defined(_M_ARM64EC) / !defined(_M_ARM64EC) vvv
|
||||
const size_t _Sse_byte_size = _Byte_length(_First, _Last) & ~_Traits::_Vec_mask;
|
||||
const size_t _Total_size_bytes = _Byte_length(_First, _Last);
|
||||
const size_t _Vec_byte_size = _Total_size_bytes & ~_Traits::_Vec_mask;
|
||||
|
||||
const void* _Stop_at = _First;
|
||||
_Advance_bytes(_Stop_at, _Sse_byte_size);
|
||||
_Advance_bytes(_Stop_at, _Vec_byte_size);
|
||||
|
||||
auto _Cur_vals = _Traits::_Load(_First);
|
||||
|
||||
|
@ -2009,6 +2092,24 @@ namespace {
|
|||
auto _Cur_vals_min = _Cur_vals; // vector of vertical minimum values
|
||||
auto _Cur_vals_max = _Cur_vals; // vector of vertical maximum values
|
||||
|
||||
const auto _Update_min_max = [&](const auto _Cur_vals) noexcept {
|
||||
if constexpr ((_Mode & _Mode_min) != 0) {
|
||||
if constexpr (_Sign || _Sign_correction) {
|
||||
_Cur_vals_min = _Traits::_Min(_Cur_vals_min, _Cur_vals); // Update the current minimum
|
||||
} else {
|
||||
_Cur_vals_min = _Traits::_Min_u(_Cur_vals_min, _Cur_vals); // Update the current minimum
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr ((_Mode & _Mode_max) != 0) {
|
||||
if constexpr (_Sign || _Sign_correction) {
|
||||
_Cur_vals_max = _Traits::_Max(_Cur_vals_max, _Cur_vals); // Update the current maximum
|
||||
} else {
|
||||
_Cur_vals_max = _Traits::_Max_u(_Cur_vals_max, _Cur_vals); // Update the current maximum
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (;;) {
|
||||
_Advance_bytes(_First, _Traits::_Vec_size);
|
||||
|
||||
|
@ -2021,22 +2122,26 @@ namespace {
|
|||
_Cur_vals = _Traits::_Sign_correction(_Cur_vals, false);
|
||||
}
|
||||
|
||||
if constexpr ((_Mode & _Mode_min) != 0) {
|
||||
if constexpr (_Sign || _Sign_correction) {
|
||||
_Cur_vals_min = _Traits::_Min(_Cur_vals_min, _Cur_vals); // Update the current minimum
|
||||
} else {
|
||||
_Cur_vals_min = _Traits::_Min_u(_Cur_vals_min, _Cur_vals); // Update the current minimum
|
||||
_Update_min_max(_Cur_vals);
|
||||
} else {
|
||||
if constexpr (_Traits::_Tail_mask != 0) {
|
||||
const size_t _Tail_byte_size = _Total_size_bytes & _Traits::_Tail_mask;
|
||||
if (_Tail_byte_size != 0) {
|
||||
const auto _Tail_mask = _Avx2_tail_mask_32(_Tail_byte_size >> 2);
|
||||
auto _Tail_vals = _Traits::_Load_mask(_First, _Tail_mask);
|
||||
|
||||
if constexpr (_Sign_correction) {
|
||||
_Tail_vals = _Traits::_Sign_correction(_Tail_vals, false);
|
||||
}
|
||||
|
||||
_Tail_vals = _Traits::_Blendval(_Cur_vals, _Tail_vals, _Tail_mask);
|
||||
|
||||
_Update_min_max(_Tail_vals);
|
||||
|
||||
_Advance_bytes(_First, _Tail_byte_size);
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr ((_Mode & _Mode_max) != 0) {
|
||||
if constexpr (_Sign || _Sign_correction) {
|
||||
_Cur_vals_max = _Traits::_Max(_Cur_vals_max, _Cur_vals); // Update the current maximum
|
||||
} else {
|
||||
_Cur_vals_max = _Traits::_Max_u(_Cur_vals_max, _Cur_vals); // Update the current maximum
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Reached end. Compute horizontal min and/or max.
|
||||
|
||||
if constexpr ((_Mode & _Mode_min) != 0) {
|
||||
|
@ -2495,7 +2600,8 @@ namespace {
|
|||
|
||||
if (_Bingo != 0) {
|
||||
unsigned long _Offset;
|
||||
_BitScanForward(&_Offset, _Bingo); // lgtm [cpp/conditionallyuninitializedvariable]
|
||||
// CodeQL [SM02313] _Offset is always initialized: we just tested `if (_Bingo != 0)`.
|
||||
_BitScanForward(&_Offset, _Bingo);
|
||||
_Advance_bytes(_First, _Offset);
|
||||
return _First;
|
||||
}
|
||||
|
@ -2565,7 +2671,8 @@ namespace {
|
|||
|
||||
if (_Bingo != 0) {
|
||||
unsigned long _Offset;
|
||||
_BitScanReverse(&_Offset, _Bingo); // lgtm [cpp/conditionallyuninitializedvariable]
|
||||
// CodeQL [SM02313] _Offset is always initialized: we just tested `if (_Bingo != 0)`.
|
||||
_BitScanReverse(&_Offset, _Bingo);
|
||||
_Advance_bytes(_Last, _Offset - (sizeof(_Ty) - 1));
|
||||
return _Last;
|
||||
}
|
||||
|
@ -2840,9 +2947,13 @@ namespace {
|
|||
constexpr int _Part_size_el = sizeof(_Ty) == 1 ? 16 : 8;
|
||||
const size_t _Needle_length = _Byte_length(_First2, _Last2);
|
||||
|
||||
const size_t _Haystack_length = _Byte_length(_First1, _Last1);
|
||||
const void* _Stop_at = _First1;
|
||||
_Advance_bytes(_Stop_at, _Haystack_length & ~size_t{0xF});
|
||||
|
||||
if (_Needle_length <= 16) {
|
||||
// Special handling of small needle
|
||||
// The generic branch could also handle it but with slightly worse performance
|
||||
// The generic branch could also be modified to handle it, but with slightly worse performance
|
||||
|
||||
const int _Needle_length_el = static_cast<int>(_Needle_length / sizeof(_Ty));
|
||||
|
||||
|
@ -2850,10 +2961,6 @@ namespace {
|
|||
memcpy(_Tmp2, _First2, _Needle_length);
|
||||
const __m128i _Data2 = _mm_load_si128(reinterpret_cast<const __m128i*>(_Tmp2));
|
||||
|
||||
const size_t _Haystack_length = _Byte_length(_First1, _Last1);
|
||||
const void* _Stop_at = _First1;
|
||||
_Advance_bytes(_Stop_at, _Haystack_length & ~size_t{0xF});
|
||||
|
||||
while (_First1 != _Stop_at) {
|
||||
const __m128i _Data1 = _mm_loadu_si128(static_cast<const __m128i*>(_First1));
|
||||
if (_mm_cmpestrc(_Data2, _Needle_length_el, _Data1, _Part_size_el, _Op)) {
|
||||
|
@ -2895,33 +3002,34 @@ namespace {
|
|||
|
||||
int _Found_pos = _Not_found;
|
||||
|
||||
const size_t _Haystack_length = _Byte_length(_First1, _Last1);
|
||||
const void* _Stop_at = _First1;
|
||||
_Advance_bytes(_Stop_at, _Haystack_length & ~size_t{0xF});
|
||||
const auto _Step = [&_Found_pos](const __m128i _Data2, const int _Size2, const __m128i _Data1,
|
||||
const int _Size1) noexcept {
|
||||
if (_mm_cmpestrc(_Data2, _Size2, _Data1, _Size1, _Op)) {
|
||||
const int _Pos = _mm_cmpestri(_Data2, _Size2, _Data1, _Size1, _Op);
|
||||
if (_Pos < _Found_pos) {
|
||||
_Found_pos = _Pos;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4324) // structure was padded due to alignment specifier
|
||||
const auto _Test_whole_needle = [=](const __m128i _Data1, const int _Size1) noexcept {
|
||||
const void* _Cur_needle = _First2;
|
||||
do {
|
||||
const __m128i _Data2 = _mm_loadu_si128(static_cast<const __m128i*>(_Cur_needle));
|
||||
_Step(_Data2, _Part_size_el, _Data1, _Size1);
|
||||
_Advance_bytes(_Cur_needle, 16);
|
||||
} while (_Cur_needle != _Last_needle);
|
||||
|
||||
if (_Last_needle_length_el != 0) {
|
||||
_Step(_Last_needle_val, _Last_needle_length_el, _Data1, _Size1);
|
||||
}
|
||||
};
|
||||
#pragma warning(pop)
|
||||
|
||||
while (_First1 != _Stop_at) {
|
||||
const __m128i _Data1 = _mm_loadu_si128(static_cast<const __m128i*>(_First1));
|
||||
|
||||
for (const void* _Cur_needle = _First2; _Cur_needle != _Last_needle;
|
||||
_Advance_bytes(_Cur_needle, 16)) {
|
||||
const __m128i _Data2 = _mm_loadu_si128(static_cast<const __m128i*>(_Cur_needle));
|
||||
if (_mm_cmpestrc(_Data2, _Part_size_el, _Data1, _Part_size_el, _Op)) {
|
||||
const int _Pos = _mm_cmpestri(_Data2, _Part_size_el, _Data1, _Part_size_el, _Op);
|
||||
if (_Pos < _Found_pos) {
|
||||
_Found_pos = _Pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (const int _Needle_length_el = _Last_needle_length_el; _Needle_length_el != 0) {
|
||||
const __m128i _Data2 = _Last_needle_val;
|
||||
if (_mm_cmpestrc(_Data2, _Needle_length_el, _Data1, _Part_size_el, _Op)) {
|
||||
const int _Pos = _mm_cmpestri(_Data2, _Needle_length_el, _Data1, _Part_size_el, _Op);
|
||||
if (_Pos < _Found_pos) {
|
||||
_Found_pos = _Pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
_Test_whole_needle(_mm_loadu_si128(static_cast<const __m128i*>(_First1)), _Part_size_el);
|
||||
|
||||
if (_Found_pos != _Not_found) {
|
||||
_Advance_bytes(_First1, _Found_pos * sizeof(_Ty));
|
||||
|
@ -2940,27 +3048,7 @@ namespace {
|
|||
|
||||
_Found_pos = _Last_part_size_el;
|
||||
|
||||
for (const void* _Cur_needle = _First2; _Cur_needle != _Last_needle;
|
||||
_Advance_bytes(_Cur_needle, 16)) {
|
||||
const __m128i _Data2 = _mm_loadu_si128(static_cast<const __m128i*>(_Cur_needle));
|
||||
|
||||
if (_mm_cmpestrc(_Data2, _Part_size_el, _Data1, _Last_part_size_el, _Op)) {
|
||||
const int _Pos = _mm_cmpestri(_Data2, _Part_size_el, _Data1, _Last_part_size_el, _Op);
|
||||
if (_Pos < _Found_pos) {
|
||||
_Found_pos = _Pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (const int _Needle_length_el = _Last_needle_length_el; _Needle_length_el != 0) {
|
||||
const __m128i _Data2 = _Last_needle_val;
|
||||
if (_mm_cmpestrc(_Data2, _Needle_length_el, _Data1, _Last_part_size_el, _Op)) {
|
||||
const int _Pos = _mm_cmpestri(_Data2, _Needle_length_el, _Data1, _Last_part_size_el, _Op);
|
||||
if (_Pos < _Found_pos) {
|
||||
_Found_pos = _Pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
_Test_whole_needle(_Data1, _Last_part_size_el);
|
||||
|
||||
_Advance_bytes(_First1, _Found_pos * sizeof(_Ty));
|
||||
return _First1;
|
||||
|
@ -3187,6 +3275,126 @@ namespace {
|
|||
}
|
||||
} // namespace __std_find_first_of
|
||||
|
||||
template <class _Ty>
|
||||
size_t __stdcall __std_find_last_of_pos_impl(const void* const _Haystack, const size_t _Haystack_length,
|
||||
const void* const _Needle, const size_t _Needle_length) noexcept {
|
||||
#ifndef _M_ARM64EC
|
||||
const size_t _Haystack_length_bytes = _Haystack_length * sizeof(_Ty);
|
||||
if (_Use_sse42() && _Haystack_length_bytes >= 16) {
|
||||
constexpr int _Op =
|
||||
(sizeof(_Ty) == 1 ? _SIDD_UBYTE_OPS : _SIDD_UWORD_OPS) | _SIDD_CMP_EQUAL_ANY | _SIDD_MOST_SIGNIFICANT;
|
||||
constexpr int _Part_size_el = sizeof(_Ty) == 1 ? 16 : 8;
|
||||
|
||||
const size_t _Last_part_size = _Haystack_length_bytes & 0xF;
|
||||
|
||||
const void* _Stop_at = _Haystack;
|
||||
_Advance_bytes(_Stop_at, _Last_part_size);
|
||||
|
||||
const void* _Cur = _Haystack;
|
||||
_Advance_bytes(_Cur, _Haystack_length_bytes);
|
||||
|
||||
const size_t _Needle_length_bytes = _Needle_length * sizeof(_Ty);
|
||||
|
||||
if (_Needle_length_bytes <= 16) {
|
||||
// Special handling of small needle
|
||||
// The generic branch could also be modified to handle it, but with slightly worse performance
|
||||
const int _Needle_length_el = static_cast<int>(_Needle_length);
|
||||
|
||||
alignas(16) uint8_t _Tmp2[16];
|
||||
memcpy(_Tmp2, _Needle, _Needle_length_bytes);
|
||||
const __m128i _Data2 = _mm_load_si128(reinterpret_cast<const __m128i*>(_Tmp2));
|
||||
|
||||
while (_Cur != _Stop_at) {
|
||||
_Rewind_bytes(_Cur, 16);
|
||||
const __m128i _Data1 = _mm_loadu_si128(static_cast<const __m128i*>(_Cur));
|
||||
if (_mm_cmpestrc(_Data2, _Needle_length_el, _Data1, _Part_size_el, _Op)) {
|
||||
const int _Pos = _mm_cmpestri(_Data2, _Needle_length_el, _Data1, _Part_size_el, _Op);
|
||||
return _Byte_length(_Haystack, _Cur) / sizeof(_Ty) + _Pos;
|
||||
}
|
||||
}
|
||||
|
||||
const int _Last_part_size_el = static_cast<int>(_Last_part_size / sizeof(_Ty));
|
||||
const __m128i _Data1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(_Haystack));
|
||||
|
||||
if (_mm_cmpestrc(_Data2, _Needle_length_el, _Data1, _Last_part_size_el, _Op)) {
|
||||
return _mm_cmpestri(_Data2, _Needle_length_el, _Data1, _Last_part_size_el, _Op);
|
||||
}
|
||||
|
||||
return static_cast<size_t>(-1);
|
||||
} else {
|
||||
const void* _Last_needle = _Needle;
|
||||
_Advance_bytes(_Last_needle, _Needle_length_bytes & ~size_t{0xF});
|
||||
|
||||
const int _Last_needle_length = static_cast<int>(_Needle_length_bytes & 0xF);
|
||||
|
||||
alignas(16) uint8_t _Tmp2[16];
|
||||
memcpy(_Tmp2, _Last_needle, _Last_needle_length);
|
||||
const __m128i _Last_needle_val = _mm_load_si128(reinterpret_cast<const __m128i*>(_Tmp2));
|
||||
const int _Last_needle_length_el = _Last_needle_length / sizeof(_Ty);
|
||||
|
||||
constexpr int _Not_found = -1; // equal to npos when treated as size_t; also less than any found value
|
||||
int _Found_pos = _Not_found;
|
||||
|
||||
const auto _Step = [&_Found_pos](const __m128i _Data2, const int _Size2, const __m128i _Data1,
|
||||
const int _Size1) noexcept {
|
||||
if (_mm_cmpestrc(_Data2, _Size2, _Data1, _Size1, _Op)) {
|
||||
const int _Pos = _mm_cmpestri(_Data2, _Size2, _Data1, _Size1, _Op);
|
||||
if (_Pos > _Found_pos) {
|
||||
_Found_pos = _Pos;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4324) // structure was padded due to alignment specifier
|
||||
const auto _Test_whole_needle = [=](const __m128i _Data1, const int _Size1) noexcept {
|
||||
const void* _Cur_needle = _Needle;
|
||||
do {
|
||||
const __m128i _Data2 = _mm_loadu_si128(static_cast<const __m128i*>(_Cur_needle));
|
||||
_Step(_Data2, _Part_size_el, _Data1, _Size1);
|
||||
_Advance_bytes(_Cur_needle, 16);
|
||||
} while (_Cur_needle != _Last_needle);
|
||||
|
||||
if (_Last_needle_length_el != 0) {
|
||||
_Step(_Last_needle_val, _Last_needle_length_el, _Data1, _Size1);
|
||||
}
|
||||
};
|
||||
#pragma warning(pop)
|
||||
|
||||
while (_Cur != _Stop_at) {
|
||||
_Rewind_bytes(_Cur, 16);
|
||||
_Test_whole_needle(_mm_loadu_si128(static_cast<const __m128i*>(_Cur)), _Part_size_el);
|
||||
|
||||
if (_Found_pos != _Not_found) {
|
||||
return _Byte_length(_Haystack, _Cur) / sizeof(_Ty) + _Found_pos;
|
||||
}
|
||||
}
|
||||
|
||||
const int _Last_part_size_el = static_cast<int>(_Last_part_size / sizeof(_Ty));
|
||||
const __m128i _Data1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(_Haystack));
|
||||
_Test_whole_needle(_Data1, _Last_part_size_el);
|
||||
|
||||
return static_cast<size_t>(_Found_pos);
|
||||
}
|
||||
}
|
||||
#endif // !_M_ARM64EC
|
||||
const auto _Ptr_haystack = static_cast<const _Ty*>(_Haystack);
|
||||
size_t _Pos = _Haystack_length;
|
||||
const auto _Needle_end = static_cast<const _Ty*>(_Needle) + _Needle_length;
|
||||
|
||||
while (_Pos != 0) {
|
||||
--_Pos;
|
||||
|
||||
for (auto _Ptr = static_cast<const _Ty*>(_Needle); _Ptr != _Needle_end; ++_Ptr) {
|
||||
if (_Ptr_haystack[_Pos] == *_Ptr) {
|
||||
return _Pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<size_t>(-1);
|
||||
}
|
||||
|
||||
template <class _Traits, class _Ty>
|
||||
__declspec(noalias) size_t __stdcall __std_mismatch_impl(
|
||||
const void* const _First1, const void* const _First2, const size_t _Count) noexcept {
|
||||
|
@ -3242,7 +3450,8 @@ namespace {
|
|||
static_cast<unsigned int>(_mm_movemask_epi8(_Traits::_Cmp_sse(_Elem1, _Elem2))) ^ 0xFFFF;
|
||||
if (_Bingo != 0) {
|
||||
unsigned long _Offset;
|
||||
_BitScanForward(&_Offset, _Bingo); // lgtm [cpp/conditionallyuninitializedvariable]
|
||||
// CodeQL [SM02313] _Offset is always initialized: we just tested `if (_Bingo != 0)`.
|
||||
_BitScanForward(&_Offset, _Bingo);
|
||||
return (_Result + _Offset) / sizeof(_Ty);
|
||||
}
|
||||
}
|
||||
|
@ -3494,25 +3703,35 @@ __declspec(noalias) size_t __stdcall __std_count_trivial_8(
|
|||
}
|
||||
|
||||
const void* __stdcall __std_find_first_of_trivial_1(
|
||||
const void* _First1, const void* _Last1, const void* _First2, const void* _Last2) noexcept {
|
||||
const void* const _First1, const void* const _Last1, const void* const _First2, const void* const _Last2) noexcept {
|
||||
return __std_find_first_of::_Impl_pcmpestri<uint8_t>(_First1, _Last1, _First2, _Last2);
|
||||
}
|
||||
|
||||
const void* __stdcall __std_find_first_of_trivial_2(
|
||||
const void* _First1, const void* _Last1, const void* _First2, const void* _Last2) noexcept {
|
||||
const void* const _First1, const void* const _Last1, const void* const _First2, const void* const _Last2) noexcept {
|
||||
return __std_find_first_of::_Impl_pcmpestri<uint16_t>(_First1, _Last1, _First2, _Last2);
|
||||
}
|
||||
|
||||
const void* __stdcall __std_find_first_of_trivial_4(
|
||||
const void* _First1, const void* _Last1, const void* _First2, const void* _Last2) noexcept {
|
||||
const void* const _First1, const void* const _Last1, const void* const _First2, const void* const _Last2) noexcept {
|
||||
return __std_find_first_of::_Impl_4_8<__std_find_first_of::_Traits_4>(_First1, _Last1, _First2, _Last2);
|
||||
}
|
||||
|
||||
const void* __stdcall __std_find_first_of_trivial_8(
|
||||
const void* _First1, const void* _Last1, const void* _First2, const void* _Last2) noexcept {
|
||||
const void* const _First1, const void* const _Last1, const void* const _First2, const void* const _Last2) noexcept {
|
||||
return __std_find_first_of::_Impl_4_8<__std_find_first_of::_Traits_8>(_First1, _Last1, _First2, _Last2);
|
||||
}
|
||||
|
||||
__declspec(noalias) size_t __stdcall __std_find_last_of_trivial_pos_1(const void* const _Haystack,
|
||||
const size_t _Haystack_length, const void* const _Needle, const size_t _Needle_length) noexcept {
|
||||
return __std_find_last_of_pos_impl<uint8_t>(_Haystack, _Haystack_length, _Needle, _Needle_length);
|
||||
}
|
||||
|
||||
__declspec(noalias) size_t __stdcall __std_find_last_of_trivial_pos_2(const void* const _Haystack,
|
||||
const size_t _Haystack_length, const void* const _Needle, const size_t _Needle_length) noexcept {
|
||||
return __std_find_last_of_pos_impl<uint16_t>(_Haystack, _Haystack_length, _Needle, _Needle_length);
|
||||
}
|
||||
|
||||
const void* __stdcall __std_search_1(
|
||||
const void* const _First1, const void* const _Last1, const void* const _First2, const size_t _Count2) noexcept {
|
||||
return __std_search_impl<_Find_traits_1, uint8_t>(_First1, _Last1, _First2, _Count2);
|
||||
|
@ -3694,8 +3913,8 @@ __declspec(noalias) void __stdcall __std_bitset_to_string_1(
|
|||
|
||||
if (_Size_bits > 0) {
|
||||
__assume(_Size_bits < 32);
|
||||
uint32_t _Val = 0;
|
||||
memcpy(&_Val, _Src, (_Size_bits + 7) / 8);
|
||||
uint32_t _Val;
|
||||
memcpy(&_Val, _Src, 4);
|
||||
const __m256i _Elems = _Bitset_to_string_1_step_avx(_Val, _Px0, _Px1);
|
||||
char _Tmp[32];
|
||||
_mm256_storeu_si256(reinterpret_cast<__m256i*>(_Tmp), _Elems);
|
||||
|
@ -3724,11 +3943,7 @@ __declspec(noalias) void __stdcall __std_bitset_to_string_1(
|
|||
if (_Size_bits > 0) {
|
||||
__assume(_Size_bits < 16);
|
||||
uint16_t _Val;
|
||||
if (_Size_bits > 8) {
|
||||
memcpy(&_Val, _Src, 2);
|
||||
} else {
|
||||
_Val = *reinterpret_cast<const uint8_t*>(_Src);
|
||||
}
|
||||
memcpy(&_Val, _Src, 2);
|
||||
const __m128i _Elems = _Bitset_to_string_1_step(_Val, _Px0, _Px1);
|
||||
char _Tmp[16];
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(_Tmp), _Elems);
|
||||
|
@ -3771,11 +3986,7 @@ __declspec(noalias) void __stdcall __std_bitset_to_string_2(
|
|||
if (_Size_bits > 0) {
|
||||
__assume(_Size_bits < 16);
|
||||
uint16_t _Val;
|
||||
if (_Size_bits > 8) {
|
||||
memcpy(&_Val, _Src, 2);
|
||||
} else {
|
||||
_Val = *reinterpret_cast<const uint8_t*>(_Src);
|
||||
}
|
||||
memcpy(&_Val, _Src, 2);
|
||||
const __m256i _Elems = _Bitset_to_string_2_step_avx(_Val, _Px0, _Px1);
|
||||
wchar_t _Tmp[16];
|
||||
_mm256_storeu_si256(reinterpret_cast<__m256i*>(_Tmp), _Elems);
|
||||
|
@ -3821,5 +4032,263 @@ __declspec(noalias) void __stdcall __std_bitset_to_string_2(
|
|||
}
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
namespace {
|
||||
|
||||
namespace __std_bitset_from_string {
|
||||
|
||||
#ifdef _M_ARM64EC
|
||||
using _Traits_1_avx = void;
|
||||
using _Traits_1_sse = void;
|
||||
using _Traits_2_avx = void;
|
||||
using _Traits_2_sse = void;
|
||||
#else // ^^^ defined(_M_ARM64EC) / !defined(_M_ARM64EC) vvv
|
||||
struct _Traits_avx {
|
||||
using _Vec = __m256i;
|
||||
|
||||
static __m256i _Load(const void* _Src) noexcept {
|
||||
return _mm256_loadu_si256(reinterpret_cast<const __m256i*>(_Src));
|
||||
}
|
||||
|
||||
static void _Store(void* _Dest, const __m256i _Val) noexcept {
|
||||
_mm256_storeu_si256(reinterpret_cast<__m256i*>(_Dest), _Val);
|
||||
}
|
||||
|
||||
static bool _Check(const __m256i _Val, const __m256i _Ex1, const __m256i _Dx0) noexcept {
|
||||
return _mm256_testc_si256(_Ex1, _mm256_xor_si256(_Val, _Dx0));
|
||||
}
|
||||
};
|
||||
|
||||
struct _Traits_sse {
|
||||
using _Vec = __m128i;
|
||||
|
||||
static __m128i _Load(const void* _Src) noexcept {
|
||||
return _mm_loadu_si128(reinterpret_cast<const __m128i*>(_Src));
|
||||
}
|
||||
|
||||
static void _Store(void* _Dest, const __m128i _Val) noexcept {
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(_Dest), _Val);
|
||||
}
|
||||
|
||||
static bool _Check(const __m128i _Val, const __m128i _Ex1, const __m128i _Dx0) noexcept {
|
||||
return _mm_testc_si128(_Ex1, _mm_xor_si128(_Val, _Dx0));
|
||||
}
|
||||
};
|
||||
|
||||
struct _Traits_1_avx : _Traits_avx {
|
||||
using _Word = uint32_t;
|
||||
|
||||
static __m256i _Set(const char _Val) noexcept {
|
||||
return _mm256_set1_epi8(_Val);
|
||||
}
|
||||
|
||||
static uint32_t _To_bits(const __m256i _Ex1) noexcept {
|
||||
const __m256i _Shuf = _mm256_set_epi8( //
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, //
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
|
||||
const __m256i _Ex2 = _mm256_shuffle_epi8(_Ex1, _Shuf);
|
||||
return _rotl(static_cast<uint32_t>(_mm256_movemask_epi8(_Ex2)), 16);
|
||||
}
|
||||
|
||||
static __m256i _Cmp(const __m256i _Val, const __m256i _Dx1) noexcept {
|
||||
return _mm256_cmpeq_epi8(_Val, _Dx1);
|
||||
}
|
||||
};
|
||||
|
||||
struct _Traits_1_sse : _Traits_sse {
|
||||
using _Word = uint16_t;
|
||||
|
||||
static __m128i _Set(const char _Val) noexcept {
|
||||
return _mm_shuffle_epi8(_mm_cvtsi32_si128(_Val), _mm_setzero_si128());
|
||||
}
|
||||
|
||||
static uint16_t _To_bits(const __m128i _Ex1) noexcept {
|
||||
const __m128i _Shuf = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
const __m128i _Ex2 = _mm_shuffle_epi8(_Ex1, _Shuf);
|
||||
return static_cast<uint16_t>(_mm_movemask_epi8(_Ex2));
|
||||
}
|
||||
|
||||
static __m128i _Cmp(const __m128i _Val, const __m128i _Dx1) noexcept {
|
||||
return _mm_cmpeq_epi8(_Val, _Dx1);
|
||||
}
|
||||
};
|
||||
|
||||
struct _Traits_2_avx : _Traits_avx {
|
||||
using _Word = uint16_t;
|
||||
|
||||
static __m256i _Set(const wchar_t _Val) noexcept {
|
||||
return _mm256_set1_epi16(_Val);
|
||||
}
|
||||
|
||||
static uint16_t _To_bits(const __m256i _Ex1) noexcept {
|
||||
const __m256i _Shuf = _mm256_set_epi8( //
|
||||
+0, +2, +4, +6, +8, 10, 12, 14, -1, -1, -1, -1, -1, -1, -1, -1, //
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, +0, +2, +4, +6, +8, 10, 12, 14);
|
||||
|
||||
const __m256i _Ex2 = _mm256_shuffle_epi8(_Ex1, _Shuf);
|
||||
return static_cast<uint16_t>(_rotl(static_cast<uint32_t>(_mm256_movemask_epi8(_Ex2)), 8));
|
||||
}
|
||||
|
||||
static __m256i _Cmp(const __m256i _Val, const __m256i _Dx1) noexcept {
|
||||
return _mm256_cmpeq_epi16(_Val, _Dx1);
|
||||
}
|
||||
};
|
||||
|
||||
struct _Traits_2_sse : _Traits_sse {
|
||||
using _Word = uint8_t;
|
||||
|
||||
static __m128i _Set(const wchar_t _Val) noexcept {
|
||||
return _mm_set1_epi16(_Val);
|
||||
}
|
||||
|
||||
static uint8_t _To_bits(const __m128i _Ex1) noexcept {
|
||||
const __m128i _Shuf = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 0, 2, 4, 6, 8, 10, 12, 14);
|
||||
const __m128i _Ex2 = _mm_shuffle_epi8(_Ex1, _Shuf);
|
||||
return static_cast<uint8_t>(_mm_movemask_epi8(_Ex2));
|
||||
}
|
||||
|
||||
static __m128i _Cmp(const __m128i _Val, const __m128i _Dx1) noexcept {
|
||||
return _mm_cmpeq_epi16(_Val, _Dx1);
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Traits, class _Elem, class _OutFn>
|
||||
bool _Loop(const _Elem* const _Src, const _Elem* _Src_end, const typename _Traits::_Vec _Dx0,
|
||||
const typename _Traits::_Vec _Dx1, _OutFn _Out) noexcept {
|
||||
for (;;) {
|
||||
typename _Traits::_Vec _Val;
|
||||
constexpr size_t _Per_vec = sizeof(_Val) / sizeof(_Elem);
|
||||
|
||||
if (const size_t _Left = _Src_end - _Src; _Left >= _Per_vec) {
|
||||
_Src_end -= _Per_vec;
|
||||
_Val = _Traits::_Load(_Src_end);
|
||||
} else if (_Left == 0) {
|
||||
return true;
|
||||
} else {
|
||||
_Src_end = _Src;
|
||||
_Elem _Tmp[_Per_vec];
|
||||
_Traits::_Store(_Tmp, _Dx0);
|
||||
_Elem* const _Tmpd = _Tmp + (_Per_vec - _Left);
|
||||
_CSTD memcpy(_Tmpd, _Src_end, _Left * sizeof(_Elem));
|
||||
_Val = _Traits::_Load(_Tmp);
|
||||
}
|
||||
|
||||
const auto _Ex1 = _Traits::_Cmp(_Val, _Dx1);
|
||||
|
||||
if (!_Traits::_Check(_Val, _Ex1, _Dx0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_Out(_Ex1);
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Traits, class _Elem>
|
||||
bool _Impl(void* const _Dest, const _Elem* const _Src, const size_t _Size_bytes, const size_t _Size_bits,
|
||||
const size_t _Size_chars, const _Elem _Elem0, const _Elem _Elem1) noexcept {
|
||||
const auto _Dx0 = _Traits::_Set(_Elem0);
|
||||
const auto _Dx1 = _Traits::_Set(_Elem1);
|
||||
|
||||
auto _Dst_words = reinterpret_cast<_Traits::_Word*>(_Dest);
|
||||
void* _Dst_words_end = _Dst_words;
|
||||
_Advance_bytes(_Dst_words_end, _Size_bytes);
|
||||
|
||||
auto _Out = [&_Dst_words](const _Traits::_Vec _Ex1) {
|
||||
*_Dst_words = _Traits::_To_bits(_Ex1);
|
||||
++_Dst_words;
|
||||
};
|
||||
|
||||
const size_t _Size_convert = (_Size_chars <= _Size_bits) ? _Size_chars : _Size_bits;
|
||||
|
||||
// Convert characters to bits
|
||||
if (!_Loop<_Traits>(_Src, _Src + _Size_convert, _Dx0, _Dx1, _Out)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify remaining characters, if any
|
||||
if (_Size_convert != _Size_chars
|
||||
&& !_Loop<_Traits>(_Src + _Size_convert, _Src + _Size_chars, _Dx0, _Dx1, [](_Traits::_Vec) {})) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Trim tail (may be padding tail, or too short string, or both)
|
||||
if (_Dst_words != _Dst_words_end) {
|
||||
_CSTD memset(_Dst_words, 0, _Byte_length(_Dst_words, _Dst_words_end));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // !defined(_M_ARM64EC)
|
||||
|
||||
template <class _Elem>
|
||||
bool _Fallback(void* const _Dest, const _Elem* const _Src, const size_t _Size_bytes, const size_t _Size_bits,
|
||||
const size_t _Size_chars, const _Elem _Elem0, const _Elem _Elem1) noexcept {
|
||||
const auto _Dest_bytes = static_cast<uint8_t*>(_Dest);
|
||||
size_t _Size_convert = _Size_chars;
|
||||
|
||||
if (_Size_chars > _Size_bits) {
|
||||
_Size_convert = _Size_bits;
|
||||
|
||||
for (size_t _Ix = _Size_bits; _Ix < _Size_chars; ++_Ix) {
|
||||
if (const _Elem _Cur = _Src[_Ix]; _Cur != _Elem0 && _Cur != _Elem1) [[unlikely]] {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_CSTD memset(_Dest, 0, _Size_bytes);
|
||||
|
||||
for (size_t _Ix = 0; _Ix != _Size_convert; ++_Ix) {
|
||||
const _Elem _Cur = _Src[_Size_convert - _Ix - 1];
|
||||
|
||||
if (_Cur != _Elem0 && _Cur != _Elem1) [[unlikely]] {
|
||||
return false;
|
||||
}
|
||||
|
||||
_Dest_bytes[_Ix >> 3] |= static_cast<uint8_t>(_Cur == _Elem1) << (_Ix & 0x7);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class _Avx, class _Sse, class _Elem>
|
||||
bool _Dispatch(void* _Dest, const _Elem* _Src, size_t _Size_bytes, size_t _Size_bits, size_t _Size_chars,
|
||||
_Elem _Elem0, _Elem _Elem1) noexcept {
|
||||
#ifndef _M_ARM64EC
|
||||
if (_Use_avx2() && _Size_bits >= 256) {
|
||||
_Zeroupper_on_exit _Guard; // TRANSITION, DevCom-10331414
|
||||
|
||||
return _Impl<_Avx>(_Dest, _Src, _Size_bytes, _Size_bits, _Size_chars, _Elem0, _Elem1);
|
||||
} else if (_Use_sse42()) {
|
||||
return _Impl<_Sse>(_Dest, _Src, _Size_bytes, _Size_bits, _Size_chars, _Elem0, _Elem1);
|
||||
} else
|
||||
#endif // !defined(_M_ARM64EC)
|
||||
{
|
||||
return _Fallback(_Dest, _Src, _Size_bytes, _Size_bits, _Size_chars, _Elem0, _Elem1);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace __std_bitset_from_string
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
__declspec(noalias) bool __stdcall __std_bitset_from_string_1(void* _Dest, const char* _Src, size_t _Size_bytes,
|
||||
size_t _Size_bits, size_t _Size_chars, char _Elem0, char _Elem1) noexcept {
|
||||
using namespace __std_bitset_from_string;
|
||||
|
||||
return _Dispatch<_Traits_1_avx, _Traits_1_sse>(_Dest, _Src, _Size_bytes, _Size_bits, _Size_chars, _Elem0, _Elem1);
|
||||
}
|
||||
|
||||
__declspec(noalias) bool __stdcall __std_bitset_from_string_2(void* _Dest, const wchar_t* _Src, size_t _Size_bytes,
|
||||
size_t _Size_bits, size_t _Size_chars, wchar_t _Elem0, wchar_t _Elem1) noexcept {
|
||||
using namespace __std_bitset_from_string;
|
||||
|
||||
return _Dispatch<_Traits_2_avx, _Traits_2_sse>(_Dest, _Src, _Size_bytes, _Size_bits, _Size_chars, _Elem0, _Elem1);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
#endif // defined(_M_IX86) || defined(_M_X64)
|
||||
|
|
|
@ -23,7 +23,7 @@ add_subdirectory(tr1)
|
|||
# chance to add to the config map and test directory global properties.
|
||||
add_subdirectory(utils/stl-lit)
|
||||
|
||||
find_package(Python "3.12" REQUIRED COMPONENTS Interpreter)
|
||||
find_package(Python "3.13" REQUIRED COMPONENTS Interpreter)
|
||||
|
||||
if(NOT DEFINED LIT_FLAGS)
|
||||
list(APPEND LIT_FLAGS "-o" "${CMAKE_CURRENT_BINARY_DIR}/test_results.json")
|
||||
|
|
|
@ -24,10 +24,6 @@ std/time/time.syn/formatter.year_month_weekday.pass.cpp:1 FAIL
|
|||
std/time/time.syn/formatter.zoned_time.pass.cpp:0 FAIL
|
||||
std/time/time.syn/formatter.zoned_time.pass.cpp:1 FAIL
|
||||
|
||||
# LLVM-74756: [libc++][test] overload_compare_iterator doesn't support its claimed iterator_category
|
||||
std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp FAIL
|
||||
std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp FAIL
|
||||
|
||||
# LLVM-90196: [libc++][format] Formatting range with m range-type is incorrect
|
||||
std/utilities/format/format.range/format.range.formatter/format.functions.format.pass.cpp FAIL
|
||||
std/utilities/format/format.range/format.range.formatter/format.functions.vformat.pass.cpp FAIL
|
||||
|
@ -224,9 +220,6 @@ std/atomics/atomics.types.generic/atomics.types.float/compare_exchange_strong.pa
|
|||
std/atomics/atomics.types.generic/atomics.types.float/compare_exchange_weak.pass.cpp:1 SKIPPED
|
||||
std/input.output/syncstream/osyncstream/thread/several_threads.pass.cpp:1 SKIPPED
|
||||
|
||||
# VSO-2164191 "[ASan][STL] Interception breaks strtoll"
|
||||
std/strings/string.conversions/stoll.pass.cpp:1 FAIL
|
||||
|
||||
|
||||
# *** MISSING STL FEATURES ***
|
||||
# Missing mbrtoc8 and c8rtomb
|
||||
|
@ -864,12 +857,6 @@ std/ranges/range.adaptors/range.lazy.split/range.lazy.split.inner/iter_swap.pass
|
|||
# Not analyzed. Checking whether packaged_task is constructible from an allocator and a packaged_task of a different type.
|
||||
std/thread/futures/futures.task/futures.task.members/ctor2.compile.pass.cpp FAIL
|
||||
|
||||
# Not analyzed. Possible MSVC compiler bug, this is inspecting type trait behavior.
|
||||
std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_copy_assignable.pass.cpp:0 FAIL
|
||||
std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_copy_assignable.pass.cpp:1 FAIL
|
||||
std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_move_assignable.pass.cpp:0 FAIL
|
||||
std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_move_assignable.pass.cpp:1 FAIL
|
||||
|
||||
# Not analyzed.
|
||||
# MSVC error C2131: expression did not evaluate to a constant
|
||||
# MSVC note: failure was caused by a read of an uninitialized symbol
|
||||
|
|
|
@ -367,9 +367,8 @@ namespace test {
|
|||
|
||||
template <class T>
|
||||
struct init_list_not_constructible_iterator {
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = int;
|
||||
using value_type = T;
|
||||
using value_type = T;
|
||||
using difference_type = int;
|
||||
|
||||
init_list_not_constructible_iterator() = default;
|
||||
init_list_not_constructible_iterator(T*) {}
|
||||
|
|
|
@ -250,6 +250,7 @@ tests\GH_004618_mixed_operator_usage_keeps_statistical_properties
|
|||
tests\GH_004618_normal_distribution_avoids_resets
|
||||
tests\GH_004657_expected_constraints_permissive
|
||||
tests\GH_004845_logical_operator_traits_with_non_bool_constant
|
||||
tests\GH_004929_internal_tag_constructors
|
||||
tests\GH_004930_char_traits_user_specialization
|
||||
tests\LWG2381_num_get_floating_point
|
||||
tests\LWG2597_complex_branch_cut
|
||||
|
@ -628,6 +629,9 @@ tests\P2286R8_text_formatting_escaping
|
|||
tests\P2286R8_text_formatting_escaping_legacy_text_encoding
|
||||
tests\P2286R8_text_formatting_escaping_utf8
|
||||
tests\P2286R8_text_formatting_formattable
|
||||
tests\P2286R8_text_formatting_header_queue
|
||||
tests\P2286R8_text_formatting_header_stack
|
||||
tests\P2286R8_text_formatting_header_vector
|
||||
tests\P2286R8_text_formatting_range_formatter
|
||||
tests\P2286R8_text_formatting_range_map
|
||||
tests\P2286R8_text_formatting_range_sequence
|
||||
|
@ -683,6 +687,8 @@ tests\P2517R1_apply_conditional_noexcept
|
|||
tests\P2538R1_adl_proof_std_projected
|
||||
tests\P2609R3_relaxing_ranges_just_a_smidge
|
||||
tests\P2693R1_ostream_and_thread_id
|
||||
tests\P2693R1_text_formatting_header_stacktrace
|
||||
tests\P2693R1_text_formatting_header_thread
|
||||
tests\P2693R1_text_formatting_stacktrace
|
||||
tests\P2693R1_text_formatting_thread_id
|
||||
tests\P3107R5_enabled_specializations
|
||||
|
|
|
@ -164,6 +164,17 @@ int main() {
|
|||
assert(f.get() == 1234);
|
||||
}
|
||||
|
||||
// Also test GH-321: "<future>: packaged_task can't be constructed from a move-only lambda"
|
||||
{
|
||||
packaged_task<int()> pt(allocator_arg, Mallocator<int>(), [uptr = make_unique<int>(172)] { return *uptr; });
|
||||
|
||||
future<int> f = pt.get_future();
|
||||
|
||||
pt();
|
||||
|
||||
assert(f.get() == 172);
|
||||
}
|
||||
|
||||
{
|
||||
int n = 4096;
|
||||
|
||||
|
|
|
@ -78,6 +78,9 @@ void test_DevDiv_725337() {
|
|||
int i = 1729;
|
||||
auto ref_lambda = [&]() -> int& { return i; };
|
||||
|
||||
// GH-321: "<future>: packaged_task can't be constructed from a move-only lambda"
|
||||
auto move_only_lambda = [uptr = make_unique<int>(42)] { return *uptr; };
|
||||
|
||||
{
|
||||
packaged_task<int()> pt1([] { return 19937; });
|
||||
future<int> f = pt1.get_future();
|
||||
|
@ -90,6 +93,18 @@ void test_DevDiv_725337() {
|
|||
assert(f.get() == 19937);
|
||||
}
|
||||
|
||||
{
|
||||
packaged_task<int()> pt1(move(move_only_lambda));
|
||||
future<int> f = pt1.get_future();
|
||||
packaged_task<int()> pt2(move(pt1));
|
||||
packaged_task<int()> pt3;
|
||||
pt3 = move(pt2);
|
||||
assert(f.wait_for(0s) == future_status::timeout);
|
||||
pt3();
|
||||
assert(f.wait_for(0s) == future_status::ready);
|
||||
assert(f.get() == 42);
|
||||
}
|
||||
|
||||
{
|
||||
packaged_task<int&()> pt1(ref_lambda);
|
||||
future<int&> f = pt1.get_future();
|
||||
|
|
|
@ -122,7 +122,6 @@ void test_function() {
|
|||
|
||||
void test_packaged_task() {
|
||||
packaged_task<void(validator)>{};
|
||||
packaged_task<void(validator)>{nullptr};
|
||||
packaged_task<void(validator)>{simple_identity{}};
|
||||
packaged_task<void(validator)>{simple_large_identity{}};
|
||||
|
||||
|
|
|
@ -5,3 +5,7 @@ PM_COMPILER="nvcc" PM_CL="--x cu -Xcompiler -Od,-EHsc,-nologo,-W4,-WX,-openmp"
|
|||
RUNALL_CROSSLIST
|
||||
PM_CL="-Xcompiler -MT"
|
||||
PM_CL="--debug -Xcompiler -MTd"
|
||||
RUNALL_CROSSLIST
|
||||
PM_CL="-std=c++14"
|
||||
PM_CL="-std=c++17 -D_SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING"
|
||||
PM_CL="-std=c++20"
|
||||
|
|
|
@ -78,6 +78,17 @@ void assert_throws_future_error(F f, std::error_code expected_code) {
|
|||
assert(false);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct MoveOnlyFunctor {
|
||||
MoveOnlyFunctor() = default;
|
||||
MoveOnlyFunctor(MoveOnlyFunctor&&) = default;
|
||||
MoveOnlyFunctor& operator=(MoveOnlyFunctor&&) = default;
|
||||
|
||||
T operator()() const {
|
||||
return T{172};
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void run_tests() {
|
||||
using Promise = std::promise<T>;
|
||||
|
@ -176,6 +187,15 @@ void run_tests() {
|
|||
|
||||
assert(f.get().x == 7);
|
||||
}
|
||||
|
||||
// Also test GH-321: "<future>: packaged_task can't be constructed from a move-only lambda"
|
||||
{
|
||||
std::packaged_task<T()> pt(MoveOnlyFunctor<T>{});
|
||||
Future f = pt.get_future();
|
||||
pt();
|
||||
|
||||
assert(f.get().x == 172);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
|
|
@ -40,12 +40,12 @@ struct Val {
|
|||
|
||||
struct I {
|
||||
using iterator_category = random_access_iterator_tag;
|
||||
using pointer = Val*;
|
||||
using value_type = Val;
|
||||
using reference = Val&;
|
||||
using difference_type = int;
|
||||
Val& operator*() const;
|
||||
Val& operator[](int) const;
|
||||
using pointer = void;
|
||||
using reference = Val&;
|
||||
reference operator*() const;
|
||||
reference operator[](int) const;
|
||||
I& operator++();
|
||||
I operator++(int);
|
||||
I& operator--();
|
||||
|
@ -58,10 +58,10 @@ struct I {
|
|||
friend bool operator<=(const I&, const I&);
|
||||
friend bool operator>(const I&, const I&);
|
||||
friend bool operator>=(const I&, const I&);
|
||||
friend int operator-(I, I);
|
||||
friend I operator+(I, int);
|
||||
friend I operator-(I, int);
|
||||
friend I operator+(int, I);
|
||||
friend difference_type operator-(I, I);
|
||||
friend I operator+(I, difference_type);
|
||||
friend I operator-(I, difference_type);
|
||||
friend I operator+(difference_type, I);
|
||||
friend RRef iter_move(const I&);
|
||||
|
||||
#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-1941943
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
RUNALL_INCLUDE ..\impure_matrix.lst
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#include <cassert>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#if _HAS_CXX17
|
||||
#include <string_view>
|
||||
#endif // _HAS_CXX17
|
||||
|
||||
#if _HAS_CXX20
|
||||
#define CONSTEXPR20 constexpr
|
||||
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
|
||||
#define CONSTEXPR20 inline
|
||||
#endif // ^^^ !_HAS_CXX20 ^^^
|
||||
|
||||
using namespace std;
|
||||
|
||||
template <class>
|
||||
constexpr bool is_initializer_list = false;
|
||||
template <class T>
|
||||
constexpr bool is_initializer_list<initializer_list<T>> = true;
|
||||
|
||||
template <class T>
|
||||
constexpr initializer_list<T> ilist42 = {T{'4'}, T{'2'}};
|
||||
|
||||
template <class>
|
||||
constexpr bool is_basic_string_or_cstr_or_view = false;
|
||||
template <class C, class T, class A>
|
||||
constexpr bool is_basic_string_or_cstr_or_view<basic_string<C, T, A>> = true;
|
||||
template <class C>
|
||||
constexpr bool is_basic_string_or_cstr_or_view<const C*> = true;
|
||||
#if _HAS_CXX17
|
||||
template <class C, class T>
|
||||
constexpr bool is_basic_string_or_cstr_or_view<basic_string_view<C, T>> = true;
|
||||
#endif // _HAS_CXX17
|
||||
|
||||
struct nasty_string_source {
|
||||
template <class IList, enable_if_t<is_initializer_list<IList>, int> = 0>
|
||||
constexpr operator IList() const {
|
||||
return ilist42<typename IList::value_type>;
|
||||
}
|
||||
|
||||
template <class T, enable_if_t<!is_initializer_list<T> && !is_basic_string_or_cstr_or_view<T>, int> = 0>
|
||||
constexpr operator T() const {
|
||||
return T{};
|
||||
}
|
||||
};
|
||||
|
||||
CONSTEXPR20 bool test_nasty_conversion_to_basic_string() {
|
||||
assert(string(nasty_string_source{}, allocator<char>{}) == "42"s);
|
||||
#ifdef __cpp_char8_t
|
||||
assert(u8string(nasty_string_source{}, allocator<char8_t>{}) == u8"42"s);
|
||||
#endif // defined(__cpp_char8_t)
|
||||
assert(u16string(nasty_string_source{}, allocator<char16_t>{}) == u"42"s);
|
||||
assert(u32string(nasty_string_source{}, allocator<char32_t>{}) == U"42"s);
|
||||
assert(wstring(nasty_string_source{}, allocator<wchar_t>{}) == L"42"s);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class>
|
||||
constexpr bool is_list = false;
|
||||
template <class T, class A>
|
||||
constexpr bool is_list<list<T, A>> = true;
|
||||
|
||||
struct nasty_list_source {
|
||||
template <class IList, enable_if_t<is_initializer_list<IList>, int> = 0>
|
||||
constexpr operator IList() const {
|
||||
return ilist42<typename IList::value_type>;
|
||||
}
|
||||
|
||||
template <class T, enable_if_t<!is_initializer_list<T> && !is_list<T> && !is_integral_v<T>, int> = 0>
|
||||
constexpr operator T() const {
|
||||
return T{};
|
||||
}
|
||||
};
|
||||
|
||||
void test_nasty_conversion_to_list() {
|
||||
allocator<int> ator{};
|
||||
assert((list<int>{nasty_list_source{}, ator} == list<int>{int{'4'}, int{'2'}}));
|
||||
}
|
||||
|
||||
#if _HAS_CXX20
|
||||
static_assert(test_nasty_conversion_to_basic_string());
|
||||
#endif // _HAS_CXX20
|
||||
|
||||
int main() {
|
||||
test_nasty_conversion_to_basic_string();
|
||||
test_nasty_conversion_to_list();
|
||||
}
|
|
@ -1,12 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#include <bitset>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <cwchar>
|
||||
#include <ios>
|
||||
#include <iosfwd>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
|
@ -22,15 +24,13 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
enum odd_char : unsigned char {};
|
||||
|
||||
template <>
|
||||
class std::char_traits<odd_char> {
|
||||
template <class T>
|
||||
class odd_char_traits {
|
||||
private:
|
||||
static constexpr unsigned char odd_mask = 0xF;
|
||||
|
||||
public:
|
||||
using char_type = odd_char;
|
||||
using char_type = T;
|
||||
using int_type = int;
|
||||
using off_type = streamoff;
|
||||
using pos_type = streampos;
|
||||
|
@ -161,6 +161,13 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
enum odd_char : unsigned char {};
|
||||
|
||||
template <>
|
||||
class char_traits<odd_char> : public odd_char_traits<odd_char> {};
|
||||
|
||||
// GH-4930 "<string>: basic_string<unicorn>::find_meow_of family
|
||||
// with std::char_traits<unicorn> specialization are not supported"
|
||||
CONSTEXPR20 bool test_gh_4930() {
|
||||
constexpr odd_char s_init[]{static_cast<odd_char>(0x55), static_cast<odd_char>(0x44), static_cast<odd_char>(0x33),
|
||||
static_cast<odd_char>(0x22), static_cast<odd_char>(0x11), static_cast<odd_char>(0)};
|
||||
|
@ -280,6 +287,19 @@ CONSTEXPR20 bool test_gh_4930() {
|
|||
static_assert(test_gh_4930());
|
||||
#endif // _HAS_CXX20
|
||||
|
||||
// GH-4956 "<bitset>: streaming operator >> does not use character traits"
|
||||
void test_gh_4956() {
|
||||
// bitset's stream extraction operator was using `!=` to compare characters instead of `traits::eq`
|
||||
basic_string<char, odd_char_traits<char>> s("QQPPQ", 5);
|
||||
basic_istringstream<char, odd_char_traits<char>> iss(s);
|
||||
|
||||
bitset<7> bs;
|
||||
iss >> bs;
|
||||
|
||||
assert(bs.to_ulong() == 0b11001);
|
||||
}
|
||||
|
||||
int main() {
|
||||
assert(test_gh_4930());
|
||||
test_gh_4956();
|
||||
}
|
||||
|
|
|
@ -285,9 +285,7 @@ void test_const_lvalue_get() {
|
|||
{
|
||||
using V = std::variant<int, const long>;
|
||||
constexpr V v(42);
|
||||
#if defined(_MSVC_INTERNAL_TESTING) || defined(__clang__) || defined(__EDG__) // TRANSITION, vs17.12p3
|
||||
ASSERT_NOT_NOEXCEPT(std::get<0>(v));
|
||||
#endif // ^^^ no workaround ^^^
|
||||
ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
|
||||
static_assert(std::get<0>(v) == 42, "");
|
||||
}
|
||||
|
@ -301,9 +299,7 @@ void test_const_lvalue_get() {
|
|||
{
|
||||
using V = std::variant<int, const long>;
|
||||
constexpr V v(42l);
|
||||
#if defined(_MSVC_INTERNAL_TESTING) || defined(__clang__) || defined(__EDG__) // TRANSITION, vs17.12p3
|
||||
ASSERT_NOT_NOEXCEPT(std::get<1>(v));
|
||||
#endif // ^^^ no workaround ^^^
|
||||
ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &);
|
||||
static_assert(std::get<1>(v) == 42, "");
|
||||
}
|
||||
|
@ -451,9 +447,7 @@ void test_const_lvalue_get() {
|
|||
{
|
||||
using V = std::variant<int, const long>;
|
||||
constexpr V v(42);
|
||||
#if defined(_MSVC_INTERNAL_TESTING) || defined(__clang__) || defined(__EDG__) // TRANSITION, vs17.12p3
|
||||
ASSERT_NOT_NOEXCEPT(std::get<int>(v));
|
||||
#endif // ^^^ no workaround ^^^
|
||||
ASSERT_SAME_TYPE(decltype(std::get<int>(v)), const int &);
|
||||
static_assert(std::get<int>(v) == 42, "");
|
||||
}
|
||||
|
@ -467,9 +461,7 @@ void test_const_lvalue_get() {
|
|||
{
|
||||
using V = std::variant<int, const long>;
|
||||
constexpr V v(42l);
|
||||
#if defined(_MSVC_INTERNAL_TESTING) || defined(__clang__) || defined(__EDG__) // TRANSITION, vs17.12p3
|
||||
ASSERT_NOT_NOEXCEPT(std::get<const long>(v));
|
||||
#endif // ^^^ no workaround ^^^
|
||||
ASSERT_SAME_TYPE(decltype(std::get<const long>(v)), const long &);
|
||||
static_assert(std::get<const long>(v) == 42, "");
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <functional>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
@ -909,6 +910,33 @@ namespace msvc {
|
|||
}
|
||||
}
|
||||
} // namespace assign_cv
|
||||
|
||||
namespace gh4959 {
|
||||
// Test GH-4959 "P0608R3 breaks flang build with Clang"
|
||||
// Constraints on variant's converting constructor and assignment operator templates reject arguments of the
|
||||
// variant's type, but did not short-circuit to avoid evaluating the constructibility constraint. For this
|
||||
// program, the constructibility constraint is ill-formed outside the immediate context when determining if
|
||||
// variant<optional<GenericSpec>> can be initialized from an rvalue of the same type.
|
||||
|
||||
template <typename... RvRef>
|
||||
using NoLvalue = std::enable_if_t<(... && !std::is_lvalue_reference_v<RvRef>)>;
|
||||
|
||||
struct Name {};
|
||||
|
||||
struct GenericSpec {
|
||||
template <typename A, typename = NoLvalue<A>>
|
||||
GenericSpec(A&& x) : u(std::move(x)) {}
|
||||
GenericSpec(GenericSpec&&) = default;
|
||||
std::variant<Name> u;
|
||||
};
|
||||
|
||||
struct InterfaceStmt {
|
||||
template <typename A, typename = NoLvalue<A>>
|
||||
InterfaceStmt(A&& x) : u(std::move(x)) {}
|
||||
InterfaceStmt(InterfaceStmt&&) = default;
|
||||
std::variant<std::optional<GenericSpec>> u;
|
||||
};
|
||||
} // namespace gh4959
|
||||
} // namespace msvc
|
||||
|
||||
int main() {
|
||||
|
|
|
@ -156,13 +156,11 @@ struct mappish_instantiator {
|
|||
assert(c5.get_allocator().state == 13);
|
||||
assert(ranges::is_permutation(c5, expected, any_pair_eq));
|
||||
}
|
||||
#if defined(_MSVC_INTERNAL_TESTING) || !defined(__EDG__) // TRANSITION, VS 17.12p3
|
||||
{
|
||||
std::same_as<T> auto c6 = R{some_pairs} | ranges::to<T>(Alloc{13});
|
||||
assert(c6.get_allocator().state == 13);
|
||||
assert(ranges::is_permutation(c6, expected, any_pair_eq));
|
||||
}
|
||||
#endif // ^^^ no workaround ^^^
|
||||
{
|
||||
std::same_as<T> auto c7 = R{some_pairs} | ranges::to<C>(Alloc{13});
|
||||
assert(c7.get_allocator().state == 13);
|
||||
|
|
|
@ -54,7 +54,6 @@ struct reservable {
|
|||
};
|
||||
|
||||
constexpr bool test_reservable() {
|
||||
#if defined(_MSVC_INTERNAL_TESTING) || !defined(__EDG__) // TRANSITION, VS 17.12p3
|
||||
int some_ints[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
{
|
||||
std::same_as<reservable> auto r = some_ints | ranges::to<reservable>(secret_key);
|
||||
|
@ -62,7 +61,6 @@ constexpr bool test_reservable() {
|
|||
assert(r.cap_ == ranges::size(some_ints));
|
||||
assert(r.reserved_ == ranges::size(some_ints));
|
||||
}
|
||||
#endif // ^^^ no workaround ^^^
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -93,14 +91,12 @@ constexpr bool test_common_constructible() {
|
|||
assert(c0.last_ == ranges::end(some_ints));
|
||||
assert(c0.args_ == 3);
|
||||
}
|
||||
#if defined(_MSVC_INTERNAL_TESTING) || !defined(__EDG__) // TRANSITION, VS 17.12p3
|
||||
{
|
||||
std::same_as<common_constructible> auto c1 = some_ints | ranges::to<common_constructible>(secret_key);
|
||||
assert(c1.first_ == ranges::begin(some_ints));
|
||||
assert(c1.last_ == ranges::end(some_ints));
|
||||
assert(c1.args_ == 3);
|
||||
}
|
||||
#endif // ^^^ no workaround ^^^
|
||||
|
||||
// Verify that more than one argument can be passed after the range:
|
||||
{
|
||||
|
@ -109,14 +105,12 @@ constexpr bool test_common_constructible() {
|
|||
assert(c2.last_ == ranges::end(some_ints));
|
||||
assert(c2.args_ == 4);
|
||||
}
|
||||
#if defined(_MSVC_INTERNAL_TESTING) || !defined(__EDG__) // TRANSITION, VS 17.12p3
|
||||
{
|
||||
std::same_as<common_constructible> auto c3 = some_ints | ranges::to<common_constructible>(secret_key, 3.14);
|
||||
assert(c3.first_ == ranges::begin(some_ints));
|
||||
assert(c3.last_ == ranges::end(some_ints));
|
||||
assert(c3.args_ == 4);
|
||||
}
|
||||
#endif // ^^^ no workaround ^^^
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -302,7 +296,6 @@ constexpr void test_lwg4016_per_kind() {
|
|||
std::same_as<V> auto vec = std::views::iota(0, 42) | ranges::to<V>();
|
||||
assert(ranges::equal(vec, std::views::iota(0, 42)));
|
||||
}
|
||||
#if defined(_MSVC_INTERNAL_TESTING) || !defined(__EDG__) // TRANSITION, VS 17.12p3
|
||||
{
|
||||
std::same_as<V> auto vec = std::views::iota(0, 42) | ranges::to<V>(std::allocator<int>{});
|
||||
assert(ranges::equal(vec, std::views::iota(0, 42)));
|
||||
|
@ -315,7 +308,6 @@ constexpr void test_lwg4016_per_kind() {
|
|||
std::same_as<V> auto vec = std::views::empty<int> | ranges::to<V>(std::size_t{42}, std::allocator<int>{});
|
||||
assert(ranges::equal(vec, std::views::repeat(0, 42)));
|
||||
}
|
||||
#endif // ^^^ no workaround ^^^
|
||||
{
|
||||
std::same_as<V> auto vec = ranges::to<V>(std::views::iota(0, 42), std::initializer_list<int>{-3, -2, -1});
|
||||
assert(ranges::equal(vec, std::views::iota(-3, 42)));
|
||||
|
|
|
@ -145,13 +145,11 @@ struct sequence_instantiator {
|
|||
assert(c5.get_allocator().state == 13);
|
||||
assert(ranges::equal(c5, meow));
|
||||
}
|
||||
#if defined(_MSVC_INTERNAL_TESTING) || !defined(__EDG__) // TRANSITION, VS 17.12p3
|
||||
{
|
||||
std::same_as<T> auto c6 = R{meow} | ranges::to<T>(Alloc{13});
|
||||
assert(c6.get_allocator().state == 13);
|
||||
assert(ranges::equal(c6, meow));
|
||||
}
|
||||
#endif // ^^^ no workaround ^^^
|
||||
{
|
||||
std::same_as<T> auto c7 = R{meow} | ranges::to<C>(Alloc{13});
|
||||
assert(c7.get_allocator().state == 13);
|
||||
|
|
|
@ -150,13 +150,11 @@ struct settish_instantiator {
|
|||
assert(c5.get_allocator().state == 13);
|
||||
assert(ranges::is_permutation(c5, expected));
|
||||
}
|
||||
#if defined(_MSVC_INTERNAL_TESTING) || !defined(__EDG__) // TRANSITION, VS 17.12p3
|
||||
{
|
||||
std::same_as<T> auto c6 = R{some_ints} | ranges::to<T>(Alloc{13});
|
||||
assert(c6.get_allocator().state == 13);
|
||||
assert(ranges::is_permutation(c6, expected));
|
||||
}
|
||||
#endif // ^^^ no workaround ^^^
|
||||
{
|
||||
std::same_as<T> auto c7 = R{some_ints} | ranges::to<C>(Alloc{13});
|
||||
assert(c7.get_allocator().state == 13);
|
||||
|
|
|
@ -19,4 +19,4 @@ RUNALL_CROSSLIST
|
|||
PM_CL=""
|
||||
ASAN PM_CL="-fsanitize=address /Zi" PM_LINK="/debug"
|
||||
# PM_CL="/analyze:only /analyze:autolog-" # TRANSITION, works correctly but slowly
|
||||
# PM_CL="/BE" # TRANSITION, VSO-1232145 "EDG ICEs when consuming Standard Library Header Units"
|
||||
# PM_CL="/BE" # TRANSITION, GH-1621 (See Modules (Including Header Units))
|
||||
|
|
|
@ -48,10 +48,8 @@ constexpr bool test_invoke_r() {
|
|||
static_assert(is_same_v<decltype(v2), double>);
|
||||
static_assert(is_void_v<decltype(invoke_r<void>(square, 1))>);
|
||||
|
||||
#if defined(_MSVC_INTERNAL_TESTING) || defined(__clang__) || defined(__EDG__) // TRANSITION, vs17.12p3
|
||||
static_assert(!noexcept(invoke_r<int>(square, 3)));
|
||||
static_assert(!noexcept(invoke(square, 3)));
|
||||
#endif // ^^^ no workaround ^^^
|
||||
|
||||
constexpr bool has_noexcept_in_type =
|
||||
#ifdef __cpp_noexcept_function_type
|
||||
|
|
|
@ -127,7 +127,7 @@ namespace test_make_from_tuple {
|
|||
assert(make_from_tuple<S>(tuple{&a, &b}) == expected_val);
|
||||
assert(make_from_tuple<S>(pair{&a, &b}) == expected_val);
|
||||
assert(make_from_tuple<S>(array{&a, &b}) == expected_val);
|
||||
assert(make_from_tuple<S>(subrange{&a, &b}) == expected_val);
|
||||
assert(make_from_tuple<S>(subrange{&a, &a + 1}) == (S{&a, &a + 1}));
|
||||
}
|
||||
|
||||
{ // Test make_from_tuple with big tuple-like types
|
||||
|
@ -180,9 +180,8 @@ namespace test_tuple_cat {
|
|||
|
||||
{ // Test tuple_cat with pair-like types
|
||||
int a = 0;
|
||||
int b = 1;
|
||||
assert(
|
||||
(tuple_cat(tuple{1, 2}, array{3, 4}, pair{5, 6}, subrange{&a, &b}) == tuple{1, 2, 3, 4, 5, 6, &a, &b}));
|
||||
assert((tuple_cat(tuple{1, 2}, array{3, 4}, pair{5, 6}, subrange{&a, &a + 1})
|
||||
== tuple{1, 2, 3, 4, 5, 6, &a, &a + 1}));
|
||||
}
|
||||
|
||||
// Test tuple_cat with big tuple-like types
|
||||
|
|
|
@ -76,8 +76,13 @@ constexpr bool test() {
|
|||
int a = 0;
|
||||
int b = 1;
|
||||
int c[2] = {2, 3};
|
||||
static_assert(tuple{&a, &b} == subrange{&a, &b});
|
||||
static_assert(tuple{&b, &a} != subrange{&a, &b});
|
||||
#ifdef __EDG__ // TRANSITION, VSO-2283373
|
||||
assert((tuple{&c[0], &c[1]} == subrange{&c[0], &c[1]}));
|
||||
assert((tuple{&c[1], &c[0]} != subrange{&c[0], &c[1]}));
|
||||
#else // ^^^ workaround / no workaround vvv
|
||||
static_assert(tuple{&c[0], &c[1]} == subrange{&c[0], &c[1]});
|
||||
static_assert(tuple{&c[1], &c[0]} != subrange{&c[0], &c[1]});
|
||||
#endif // ^^^ no workaround ^^^
|
||||
static_assert(is_eq(tuple{&a, &b} <=> pair{&a, &b}));
|
||||
static_assert(is_lt(tuple{&c[0], &c[0]} <=> pair{&c[0], &c[1]}));
|
||||
static_assert(is_gt(tuple{&c[1], &c[0]} <=> pair{&c[0], &c[1]}));
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
RUNALL_INCLUDE ..\usual_latest_matrix.lst
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// intentionally avoid including <format> to verify that the formatter specializations are defined in <queue>
|
||||
|
||||
#include <concepts>
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct cannot_format {
|
||||
friend auto operator<=>(cannot_format, cannot_format) = default;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void verify_semiregularity_for() {
|
||||
static_assert(semiregular<T>);
|
||||
|
||||
T x;
|
||||
T y = x;
|
||||
T z = move(x);
|
||||
x = y;
|
||||
x = move(z);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void verify_disabled_for() {
|
||||
static_assert(!is_default_constructible_v<T>);
|
||||
static_assert(!is_copy_constructible_v<T>);
|
||||
static_assert(!is_move_constructible_v<T>);
|
||||
static_assert(!is_copy_assignable_v<T>);
|
||||
static_assert(!is_move_assignable_v<T>);
|
||||
}
|
||||
|
||||
void verify_formatters() {
|
||||
verify_semiregularity_for<formatter<queue<int>, char>>();
|
||||
verify_semiregularity_for<formatter<queue<int>, wchar_t>>();
|
||||
verify_semiregularity_for<formatter<queue<int, pmr::deque<int>>, char>>();
|
||||
verify_semiregularity_for<formatter<queue<int, pmr::deque<int>>, wchar_t>>();
|
||||
|
||||
verify_semiregularity_for<formatter<priority_queue<int>, char>>();
|
||||
verify_semiregularity_for<formatter<priority_queue<int>, wchar_t>>();
|
||||
verify_semiregularity_for<formatter<priority_queue<int, vector<int>, greater<>>, char>>();
|
||||
verify_semiregularity_for<formatter<priority_queue<int, vector<int>, greater<>>, wchar_t>>();
|
||||
verify_semiregularity_for<formatter<priority_queue<int, pmr::vector<int>>, char>>();
|
||||
verify_semiregularity_for<formatter<priority_queue<int, pmr::vector<int>>, wchar_t>>();
|
||||
|
||||
verify_disabled_for<formatter<queue<cannot_format>, char>>();
|
||||
verify_disabled_for<formatter<queue<cannot_format>, wchar_t>>();
|
||||
verify_disabled_for<formatter<queue<cannot_format, pmr::deque<cannot_format>>, char>>();
|
||||
verify_disabled_for<formatter<queue<cannot_format, pmr::deque<cannot_format>>, wchar_t>>();
|
||||
|
||||
verify_disabled_for<formatter<priority_queue<cannot_format>, char>>();
|
||||
verify_disabled_for<formatter<priority_queue<cannot_format>, wchar_t>>();
|
||||
verify_disabled_for<formatter<priority_queue<cannot_format, vector<cannot_format>, greater<>>, char>>();
|
||||
verify_disabled_for<formatter<priority_queue<cannot_format, vector<cannot_format>, greater<>>, wchar_t>>();
|
||||
verify_disabled_for<formatter<priority_queue<cannot_format, pmr::vector<cannot_format>>, char>>();
|
||||
verify_disabled_for<formatter<priority_queue<cannot_format, pmr::vector<cannot_format>>, wchar_t>>();
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
RUNALL_INCLUDE ..\usual_latest_matrix.lst
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// intentionally avoid including <format> to verify that the formatter specialization is defined in <stack>
|
||||
|
||||
#include <concepts>
|
||||
#include <deque>
|
||||
#include <stack>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct cannot_format {};
|
||||
|
||||
template <class T>
|
||||
void verify_semiregularity_for() {
|
||||
static_assert(semiregular<T>);
|
||||
|
||||
T x;
|
||||
T y = x;
|
||||
T z = move(x);
|
||||
x = y;
|
||||
x = move(z);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void verify_disabled_for() {
|
||||
static_assert(!is_default_constructible_v<T>);
|
||||
static_assert(!is_copy_constructible_v<T>);
|
||||
static_assert(!is_move_constructible_v<T>);
|
||||
static_assert(!is_copy_assignable_v<T>);
|
||||
static_assert(!is_move_assignable_v<T>);
|
||||
}
|
||||
|
||||
void verify_formatters() {
|
||||
verify_semiregularity_for<formatter<stack<int>, char>>();
|
||||
verify_semiregularity_for<formatter<stack<int>, wchar_t>>();
|
||||
verify_semiregularity_for<formatter<stack<int, pmr::deque<int>>, char>>();
|
||||
verify_semiregularity_for<formatter<stack<int, pmr::deque<int>>, wchar_t>>();
|
||||
|
||||
verify_disabled_for<formatter<stack<cannot_format>, char>>();
|
||||
verify_disabled_for<formatter<stack<cannot_format>, wchar_t>>();
|
||||
verify_disabled_for<formatter<stack<cannot_format, pmr::deque<cannot_format>>, char>>();
|
||||
verify_disabled_for<formatter<stack<cannot_format, pmr::deque<cannot_format>>, wchar_t>>();
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
RUNALL_INCLUDE ..\usual_latest_matrix.lst
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// intentionally avoid including <format> to verify that the formatter specialization is defined in <vector>
|
||||
|
||||
#include <concepts>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
template <class T>
|
||||
void verify_semiregularity_for() {
|
||||
static_assert(semiregular<T>);
|
||||
|
||||
T x;
|
||||
T y = x;
|
||||
T z = move(x);
|
||||
x = y;
|
||||
x = move(z);
|
||||
}
|
||||
|
||||
void verify_formatters() {
|
||||
verify_semiregularity_for<formatter<vector<bool>::reference, char>>();
|
||||
verify_semiregularity_for<formatter<vector<bool>::reference, wchar_t>>();
|
||||
verify_semiregularity_for<formatter<pmr::vector<bool>::reference, char>>();
|
||||
verify_semiregularity_for<formatter<pmr::vector<bool>::reference, wchar_t>>();
|
||||
}
|
|
@ -183,12 +183,12 @@ generator<int> iota_repeater(const int hi, const int depth) {
|
|||
}
|
||||
|
||||
void recursive_test() {
|
||||
constexpr auto might_throw = []() -> generator<int> {
|
||||
auto might_throw = []() -> generator<int> {
|
||||
co_yield 0;
|
||||
throw runtime_error{"error"};
|
||||
};
|
||||
|
||||
constexpr auto nested_ints = [=]() -> generator<int> {
|
||||
auto nested_ints = [=]() -> generator<int> {
|
||||
try {
|
||||
co_yield ranges::elements_of(might_throw());
|
||||
} catch (const runtime_error& e) {
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
RUNALL_INCLUDE ..\usual_latest_matrix.lst
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// intentionally avoid including <format> to verify that the formatter specializations are defined in <stacktrace>
|
||||
|
||||
#include <concepts>
|
||||
#include <stacktrace>
|
||||
#include <utility>
|
||||
|
||||
using namespace std;
|
||||
|
||||
template <class T>
|
||||
void verify_semiregularity_for() {
|
||||
static_assert(semiregular<T>);
|
||||
|
||||
T x;
|
||||
T y = x;
|
||||
T z = move(x);
|
||||
x = y;
|
||||
x = move(z);
|
||||
}
|
||||
|
||||
void verify_formatters() {
|
||||
verify_semiregularity_for<formatter<stacktrace_entry, char>>();
|
||||
verify_semiregularity_for<formatter<stacktrace, char>>();
|
||||
verify_semiregularity_for<formatter<pmr::stacktrace, char>>();
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
RUNALL_INCLUDE ..\usual_latest_matrix.lst
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// intentionally avoid including <format> to verify that the formatter specialization is defined in <thread>
|
||||
|
||||
#include <concepts>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
using namespace std;
|
||||
|
||||
template <class T>
|
||||
void verify_semiregularity_for() {
|
||||
static_assert(semiregular<T>);
|
||||
|
||||
T x;
|
||||
T y = x;
|
||||
T z = move(x);
|
||||
x = y;
|
||||
x = move(z);
|
||||
}
|
||||
|
||||
void verify_formatters() {
|
||||
verify_semiregularity_for<formatter<thread::id, char>>();
|
||||
verify_semiregularity_for<formatter<thread::id, wchar_t>>();
|
||||
}
|
|
@ -554,9 +554,13 @@ void future_test() {
|
|||
swap_test(pv);
|
||||
|
||||
packaged_task<void()> pt([]() {});
|
||||
// GH-321: "<future>: packaged_task can't be constructed from a move-only lambda"
|
||||
packaged_task<void()> pt2([uptr = unique_ptr<int>{}]() { (void) uptr; });
|
||||
|
||||
#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
|
||||
packaged_task<void()> pta(allocator_arg, allocator<double>{}, []() {});
|
||||
// GH-321: "<future>: packaged_task can't be constructed from a move-only lambda"
|
||||
packaged_task<void()> pta2(allocator_arg, allocator<double>{}, [uptr = unique_ptr<int>{}]() { (void) uptr; });
|
||||
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
|
||||
|
||||
swap_test(pt);
|
||||
|
|
|
@ -558,6 +558,13 @@ STATIC_ASSERT(!is_constructible_v<tuple<A>, allocator_arg_t, allocator<int>, pai
|
|||
STATIC_ASSERT(is_constructible_v<tuple<A, A>, allocator_arg_t, allocator<int>, pair<Ex, Ex>>);
|
||||
STATIC_ASSERT(!is_constructible_v<tuple<A, A, A>, allocator_arg_t, allocator<int>, pair<Ex, Ex>>);
|
||||
|
||||
// Also test that the internal constructor used for the piecewise_construct_t constructor of pair is not public.
|
||||
STATIC_ASSERT(!is_constructible_v<pair<int, int>, tuple<>&, tuple<>&, make_index_sequence<0>, make_index_sequence<0>>);
|
||||
STATIC_ASSERT(
|
||||
!is_constructible_v<pair<int, int>, tuple<int>&, tuple<>&, make_index_sequence<1>, make_index_sequence<0>>);
|
||||
STATIC_ASSERT(
|
||||
!is_constructible_v<pair<int, int>, tuple<int>&, tuple<int>&, make_index_sequence<1>, make_index_sequence<1>>);
|
||||
|
||||
|
||||
pair<int, int> func1() {
|
||||
const int x = 17;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <limits>
|
||||
#include <list>
|
||||
#include <random>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
@ -997,6 +998,15 @@ void test_randomized_bitset_base_count(mt19937_64& gen) {
|
|||
test_randomized_bitset_base<Base>(make_index_sequence<Count>{}, gen);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
void assert_throws_inv(F f) {
|
||||
try {
|
||||
f();
|
||||
assert(false);
|
||||
} catch (const invalid_argument&) {
|
||||
}
|
||||
}
|
||||
|
||||
void test_bitset(mt19937_64& gen) {
|
||||
assert(bitset<0>(0x0ULL).to_string() == "");
|
||||
assert(bitset<0>(0xFEDCBA9876543210ULL).to_string() == "");
|
||||
|
@ -1038,6 +1048,33 @@ void test_bitset(mt19937_64& gen) {
|
|||
assert(bitset<75>(0xFEDCBA9876543210ULL).to_string<char32_t>()
|
||||
== U"000000000001111111011011100101110101001100001110110010101000011001000010000"); // not vectorized
|
||||
|
||||
assert(bitset<0>("").to_ullong() == 0);
|
||||
assert(bitset<0>("1").to_ullong() == 0);
|
||||
assert_throws_inv([] { (void) bitset<0>("x"); });
|
||||
|
||||
assert(bitset<45>("101110000000111010001011100101001111111111111").to_ullong() == 0x1701D1729FFFULL);
|
||||
assert(bitset<45>("110101001100001110110010101000011001000010000").to_ullong() == 0x1A9876543210ULL);
|
||||
assert(bitset<45>("111").to_ullong() == 0x7);
|
||||
assert_throws_inv([] { (void) bitset<45>("11x11"); });
|
||||
assert_throws_inv([] { (void) bitset<45>("111111111111111111111111111111111111111111111x"); });
|
||||
assert_throws_inv([] { (void) bitset<45>("x111111111111111111111111111111111111111111111"); });
|
||||
|
||||
assert(bitset<64>("xxxxxxxoxxoxxxooxoxxxoxoxooxxooooxxxoxxooxoxoxooooxxooxooooxoooo", string::npos, 'o', 'x')
|
||||
.to_ullong()
|
||||
== 0xFEDCBA9876543210ULL);
|
||||
assert(bitset<64>(L"xxxxxxxoxxoxxxooxoxxxoxoxooxxooooxxxoxxooxoxoxooooxxooxooooxoooo", wstring::npos, L'o', L'x')
|
||||
.to_ullong()
|
||||
== 0xFEDCBA9876543210ULL);
|
||||
|
||||
#ifdef __cpp_lib_char8_t
|
||||
assert(bitset<75>(u8"000000000001111111011011100101110101001100001110110010101000011001000010000").to_ullong()
|
||||
== 0xFEDCBA9876543210ULL);
|
||||
#endif // __cpp_lib_char8_t
|
||||
assert(bitset<75>(u"000000000001111111011011100101110101001100001110110010101000011001000010000").to_ullong()
|
||||
== 0xFEDCBA9876543210ULL);
|
||||
assert(bitset<75>(U"000000000001111111011011100101110101001100001110110010101000011001000010000").to_ullong()
|
||||
== 0xFEDCBA9876543210ULL); // not vectorized
|
||||
|
||||
test_randomized_bitset_base_count<512 - 5, 32 + 10>(gen);
|
||||
}
|
||||
|
||||
|
@ -1046,7 +1083,27 @@ void test_case_string_find_first_of(const basic_string<T>& input_haystack, const
|
|||
auto expected_iter = last_known_good_find_first_of(
|
||||
input_haystack.begin(), input_haystack.end(), input_needle.begin(), input_needle.end());
|
||||
auto expected = (expected_iter != input_haystack.end()) ? expected_iter - input_haystack.begin() : ptrdiff_t{-1};
|
||||
auto actual = static_cast<ptrdiff_t>(input_haystack.find_first_of(input_needle.data(), 0, input_needle.size()));
|
||||
auto actual = static_cast<ptrdiff_t>(input_haystack.find_first_of(input_needle));
|
||||
assert(expected == actual);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
size_t last_known_good_find_last_of(const basic_string<T>& h, const basic_string<T>& n) {
|
||||
size_t pos = h.size();
|
||||
while (pos != 0) {
|
||||
--pos;
|
||||
if (n.find(h[pos]) != basic_string<T>::npos) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
return basic_string<T>::npos;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void test_case_string_find_last_of(const basic_string<T>& input_haystack, const basic_string<T>& input_needle) {
|
||||
size_t expected = last_known_good_find_last_of(input_haystack, input_needle);
|
||||
size_t actual = input_haystack.find_last_of(input_needle);
|
||||
assert(expected == actual);
|
||||
}
|
||||
|
||||
|
@ -1061,9 +1118,11 @@ void test_basic_string_dis(mt19937_64& gen, D& dis) {
|
|||
input_needle.clear();
|
||||
|
||||
test_case_string_find_first_of(input_haystack, input_needle);
|
||||
test_case_string_find_last_of(input_haystack, input_needle);
|
||||
for (size_t attempts = 0; attempts < needleDataCount; ++attempts) {
|
||||
input_needle.push_back(static_cast<T>(dis(gen)));
|
||||
test_case_string_find_first_of(input_haystack, input_needle);
|
||||
test_case_string_find_last_of(input_haystack, input_needle);
|
||||
}
|
||||
|
||||
if (input_haystack.size() == haystackDataCount) {
|
||||
|
@ -1094,6 +1153,7 @@ void test_string(mt19937_64& gen) {
|
|||
#endif // __cpp_lib_char8_t
|
||||
test_basic_string<char16_t>(gen);
|
||||
test_basic_string<char32_t>(gen);
|
||||
test_basic_string<unsigned long long>(gen);
|
||||
}
|
||||
|
||||
void test_various_containers() {
|
||||
|
|
|
@ -42,12 +42,12 @@ PM_CL="/BE /c /EHsc /MD /std:c++14 /w14640 /Zc:threadSafeInit-"
|
|||
PM_CL="/BE /c /EHsc /MDd /std:c++17 /permissive- /w14640 /Zc:threadSafeInit-"
|
||||
PM_CL="/BE /c /EHsc /MT /std:c++20 /permissive- /w14640 /Zc:threadSafeInit-"
|
||||
PM_CL="/BE /c /EHsc /MTd /std:c++latest /permissive- /w14640 /Zc:threadSafeInit-"
|
||||
PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call -Wno-nan-infinity-disabled /EHsc /MD /std:c++14 /w14640 /Zc:threadSafeInit- --start-no-unused-arguments"
|
||||
PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call -Wno-nan-infinity-disabled /EHsc /MDd /std:c++17 /w14640 /Zc:threadSafeInit- --start-no-unused-arguments"
|
||||
PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call -Wno-nan-infinity-disabled /EHsc /MT /std:c++20 /permissive- /w14640 /Zc:threadSafeInit- --start-no-unused-arguments"
|
||||
PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call -Wno-nan-infinity-disabled /EHsc /MTd /std:c++latest /permissive- /w14640 /Zc:threadSafeInit- --start-no-unused-arguments"
|
||||
PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /EHsc /MD /std:c++14 /w14640 /Zc:threadSafeInit- --start-no-unused-arguments"
|
||||
PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /EHsc /MDd /std:c++17 /w14640 /Zc:threadSafeInit- --start-no-unused-arguments"
|
||||
PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /EHsc /MT /std:c++20 /permissive- /w14640 /Zc:threadSafeInit- --start-no-unused-arguments"
|
||||
PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /EHsc /MTd /std:c++latest /permissive- /w14640 /Zc:threadSafeInit- --start-no-unused-arguments"
|
||||
# TRANSITION, GH-3568
|
||||
# PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call -Wno-nan-infinity-disabled /EHsc /MT /std:c++latest /permissive- /w14640 /Zc:threadSafeInit- -fsanitize=undefined -fno-sanitize-recover=undefined --start-no-unused-arguments"
|
||||
# PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /EHsc /MT /std:c++latest /permissive- /w14640 /Zc:threadSafeInit- -fsanitize=undefined -fno-sanitize-recover=undefined --start-no-unused-arguments"
|
||||
RUNALL_CROSSLIST
|
||||
* PM_CL="/fp:strict"
|
||||
* PM_CL="/fp:precise"
|
||||
|
|
|
@ -148,12 +148,9 @@ public:
|
|||
|
||||
template <typename Func>
|
||||
nanoseconds time_execution(Func&& f) {
|
||||
// system_clock currently powers mutex waits, so we're using system_clock
|
||||
// rather than high_resolution_clock here for consistency. This should be
|
||||
// fixed with VSO-133414, VSO-166543, VSO-189735.
|
||||
const auto startTime = system_clock::now();
|
||||
const auto startTime = steady_clock::now();
|
||||
forward<Func>(f)();
|
||||
return duration_cast<nanoseconds>(system_clock::now() - startTime);
|
||||
return duration_cast<nanoseconds>(steady_clock::now() - startTime);
|
||||
}
|
||||
|
||||
template <typename Mutex>
|
||||
|
@ -298,7 +295,7 @@ struct mutex_test_fixture {
|
|||
// Test acquiring locks successfully
|
||||
assert(time_execution([this] { assert(mtx.try_lock_for(24h)); }) < 1h);
|
||||
mtx.unlock();
|
||||
assert(time_execution([this] { assert(mtx.try_lock_until(system_clock::now() + 24h)); }) < 1h);
|
||||
assert(time_execution([this] { assert(mtx.try_lock_until(steady_clock::now() + 24h)); }) < 1h);
|
||||
mtx.unlock();
|
||||
assert(time_execution([this] {
|
||||
unique_lock<Mutex> ul(mtx, defer_lock);
|
||||
|
@ -310,18 +307,17 @@ struct mutex_test_fixture {
|
|||
}) < 1h);
|
||||
assert(time_execution([this] {
|
||||
unique_lock<Mutex> ul(mtx, defer_lock);
|
||||
assert(ul.try_lock_until(system_clock::now() + 24h));
|
||||
assert(ul.try_lock_until(steady_clock::now() + 24h));
|
||||
}) < 1h);
|
||||
assert(time_execution([this] {
|
||||
unique_lock<Mutex> ul(mtx, system_clock::now() + 24h);
|
||||
unique_lock<Mutex> ul(mtx, steady_clock::now() + 24h);
|
||||
assert(ul.owns_lock());
|
||||
}) < 1h);
|
||||
|
||||
#if 0 // TRANSITION, GH-1472
|
||||
// Test failing to acquire locks on timeout
|
||||
// Test failing to acquire locks on timeout
|
||||
ot.lock();
|
||||
assert(time_execution([this] { assert(!mtx.try_lock_for(50ms)); }) >= 50ms);
|
||||
assert(time_execution([this] { assert(!mtx.try_lock_until(system_clock::now() + 50ms)); }) >= 50ms);
|
||||
assert(time_execution([this] { assert(!mtx.try_lock_until(steady_clock::now() + 50ms)); }) >= 50ms);
|
||||
assert(time_execution([this] {
|
||||
unique_lock<Mutex> ul(mtx, defer_lock);
|
||||
assert(!ul.try_lock_for(50ms));
|
||||
|
@ -332,14 +328,13 @@ struct mutex_test_fixture {
|
|||
}) >= 50ms);
|
||||
assert(time_execution([this] {
|
||||
unique_lock<Mutex> ul(mtx, defer_lock);
|
||||
assert(!ul.try_lock_until(system_clock::now() + 50ms));
|
||||
assert(!ul.try_lock_until(steady_clock::now() + 50ms));
|
||||
}) >= 50ms);
|
||||
assert(time_execution([this] {
|
||||
unique_lock<Mutex> ul(mtx, system_clock::now() + 50ms);
|
||||
unique_lock<Mutex> ul(mtx, steady_clock::now() + 50ms);
|
||||
assert(!ul.owns_lock());
|
||||
}) >= 50ms);
|
||||
ot.unlock();
|
||||
#endif // TRANSITION, GH-1472
|
||||
}
|
||||
|
||||
void test_recursive_lockable() {
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
#include <deque>
|
||||
#include <forward_list>
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <stack>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
@ -21,12 +19,6 @@ struct convertible_to_any {
|
|||
operator T() &&; // not defined, only used in unevaluated context
|
||||
};
|
||||
|
||||
template <class Cont, class = void>
|
||||
constexpr bool has_emplace = false;
|
||||
template <class Cont>
|
||||
constexpr bool has_emplace<Cont,
|
||||
void_t<decltype(declval<Cont&>().emplace(declval<convertible_to_any<typename Cont::value_type>>()))>> = true;
|
||||
|
||||
template <class Cont, class = void>
|
||||
constexpr bool has_emplace_back = false;
|
||||
template <class Cont>
|
||||
|
@ -51,6 +43,7 @@ STATIC_ASSERT(has_emplace_front<deque<S2>>);
|
|||
STATIC_ASSERT(has_emplace_front<forward_list<S2>>);
|
||||
STATIC_ASSERT(has_emplace_back<list<S2>>);
|
||||
STATIC_ASSERT(has_emplace_front<list<S2>>);
|
||||
STATIC_ASSERT(has_emplace<queue<S2>>);
|
||||
STATIC_ASSERT(has_emplace<stack<S2>>);
|
||||
STATIC_ASSERT(has_emplace_back<vector<bool>>); // Cannot trigger this bug, but for consistency
|
||||
|
||||
// N4988 [queue.defn] and [stack.defn] require the container adaptors to have `decltype(auto) emplace(Args&&... args)`,
|
||||
// allowing them to adapt both C++14-era and C++17-era containers.
|
||||
|
|
Загрузка…
Ссылка в новой задаче