| _build/ | _build/ | ||||
| __pycache__/ | __pycache__/ | ||||
| .peru/ | |||||
| .vscode/ | .vscode/ | ||||
| .mypy_cache/ | .mypy_cache/ | ||||
| *.dsd/ | |||||
| _prebuilt/ | _prebuilt/ | ||||
| .dds-repo-lock | |||||
| .pytest_cache |
| Type: Index | |||||
| Package: taywee-args; external/taywee-args.lmp | |||||
| Package: spdlog; external/spdlog.lmp | |||||
| Package: ms-third; external/ms-third.lmp | |||||
| Package: ranges-v3; external/ranges-v3.lmp | |||||
| Package: nlohmann-json; external/nlohmann-json.lmp |
| steps: | steps: | ||||
| - script: | | - script: | | ||||
| echo Loading VS environment | echo Loading VS environment | ||||
| call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\Common7\\Tools\\vsdevcmd" -arch=x64 || exit 1 | |||||
| call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\vsdevcmd" -arch=x64 || exit 1 | |||||
| echo Executing Build and Tests | echo Executing Build and Tests | ||||
| python -u tools/ci.py --cxx cl.exe -T tools\\msvc.dds || exit 1 | |||||
| reg add HKLM\SYSTEM\CurrentControlSet\Control\FileSystem /v LongPathsEnabled /t REG_DWORD /d 1 /f || exit 1 | |||||
| python -m pip install pytest pytest-xdist || exit 1 | |||||
| python -u tools/ci.py -B download -T tools\msvc.dds || exit 1 | |||||
| displayName: Full CI | displayName: Full CI | ||||
| - publish: _build/dds.exe | - publish: _build/dds.exe | ||||
| artifact: DDS Executable - Windows VS2019 | artifact: DDS Executable - Windows VS2019 | ||||
| pool: | pool: | ||||
| vmImage: ubuntu-18.04 | vmImage: ubuntu-18.04 | ||||
| steps: | steps: | ||||
| - script: sudo apt update -y && sudo apt install -y python3-minimal g++-8 | |||||
| - script: | | |||||
| set -eu | |||||
| sudo apt update -y | |||||
| sudo apt install -y python3-minimal g++-9 ccache | |||||
| python3 -m pip install pytest pytest-xdist | |||||
| displayName: Prepare System | displayName: Prepare System | ||||
| - script: python3 -u tools/ci.py --cxx g++-8 -T tools/gcc-8.dds | |||||
| - script: python3 -u tools/ci.py -B download -T tools/gcc-9.dds | |||||
| displayName: Full CI | displayName: Full CI | ||||
| - publish: _build/dds | - publish: _build/dds | ||||
| artifact: DDS Executable - Linux | artifact: DDS Executable - Linux | ||||
| pool: | pool: | ||||
| vmImage: macOS-10.14 | vmImage: macOS-10.14 | ||||
| steps: | steps: | ||||
| - script: brew install gcc@8 | |||||
| - script: brew install gcc@9 ccache | |||||
| displayName: Prepare System | displayName: Prepare System | ||||
| - script: python3 -u tools/ci.py --cxx g++-8 -T tools/gcc-8.dds | |||||
| - script: | | |||||
| set -eu | |||||
| python3 -m pip install pytest pytest-xdist | |||||
| python3 -u tools/ci.py -B download -T tools/gcc-9.dds | |||||
| displayName: Build and Run Unit Tests | displayName: Build and Run Unit Tests | ||||
| - publish: _build/dds | - publish: _build/dds | ||||
| artifact: DDS Executable - macOS | artifact: DDS Executable - macOS |
| { | |||||
| "version": 1, | |||||
| "packages": { | |||||
| "range-v3": { | |||||
| "0.10.0": { | |||||
| "git": { | |||||
| "url": "https://github.com/ericniebler/range-v3.git", | |||||
| "ref": "0.10.0", | |||||
| "auto-lib": "Niebler/range-v3" | |||||
| }, | |||||
| "depends": {} | |||||
| } | |||||
| }, | |||||
| "spdlog": { | |||||
| "1.4.2": { | |||||
| "git": { | |||||
| "url": "https://github.com/gabime/spdlog.git", | |||||
| "ref": "v1.4.2", | |||||
| "auto-lib": "spdlog/spdlog" | |||||
| }, | |||||
| "depends": {} | |||||
| } | |||||
| }, | |||||
| "nlohmann-json": { | |||||
| "3.7.1": { | |||||
| "git": { | |||||
| "url": "https://github.com/vector-of-bool/json.git", | |||||
| "ref": "dds/3.7.1" | |||||
| }, | |||||
| "depends": {} | |||||
| } | |||||
| }, | |||||
| "ms-wil": { | |||||
| "2019.11.10": { | |||||
| "git": { | |||||
| "url": "https://github.com/vector-of-bool/wil.git", | |||||
| "ref": "dds/2019.11.10" | |||||
| }, | |||||
| "depends": {} | |||||
| } | |||||
| }, | |||||
| "neo-sqlite3": { | |||||
| "0.2.2": { | |||||
| "git": { | |||||
| "url": "https://github.com/vector-of-bool/neo-sqlite3.git", | |||||
| "ref": "0.2.2" | |||||
| }, | |||||
| "depends": {} | |||||
| } | |||||
| }, | |||||
| "neo-fun": { | |||||
| "0.1.0": { | |||||
| "git": { | |||||
| "url": "https://github.com/vector-of-bool/neo-fun.git", | |||||
| "ref": "0.1.0" | |||||
| }, | |||||
| "depends": {} | |||||
| } | |||||
| }, | |||||
| "semver": { | |||||
| "0.2.1": { | |||||
| "git": { | |||||
| "url": "https://github.com/vector-of-bool/semver.git", | |||||
| "ref": "0.2.1" | |||||
| }, | |||||
| "depends": {} | |||||
| } | |||||
| }, | |||||
| "pubgrub": { | |||||
| "0.1.2": { | |||||
| "git": { | |||||
| "url": "https://github.com/vector-of-bool/pubgrub.git", | |||||
| "ref": "0.1.2" | |||||
| }, | |||||
| "depends": {} | |||||
| } | |||||
| } | |||||
| } | |||||
| } |
| Type: Library | |||||
| Name: args | |||||
| Include-Path: repo/taywee-args/include |
| Type: Package | |||||
| Name: ms-third | |||||
| Namespace: Microsoft | |||||
| Library: wil.lml |
| Type: Library | |||||
| Name: json | |||||
| Include-Path: repo/nlohmann-json/include |
| Type: Package | |||||
| Name: nlohmann-json | |||||
| Namespace: nlohmann | |||||
| Library: nlohmann-json.lml |
| Type: Library | |||||
| Name: range-v3 | |||||
| Include-Path: repo/range-v3/include |
| Type: Package | |||||
| Name: ranges-v3 | |||||
| Namespace: Niebler | |||||
| Library: ranges-v3.lml |
| _build/ | |||||
| .vscode/ |
| ; DO NOT EDIT (unless you know what you are doing) | |||||
| ; | |||||
| ; This subdirectory is a git "subrepo", and this file is maintained by the | |||||
| ; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme | |||||
| ; | |||||
| [subrepo] | |||||
| remote = git@github.com:vector-of-bool/neo-buffer.git | |||||
| branch = develop | |||||
| commit = 9461eded7f661b31bcdf4f8760ebe4ebc83e9630 | |||||
| parent = 4bc28954ef34869a5b5ad65094c6f56a23937f8b | |||||
| method = merge | |||||
| cmdver = 0.4.0 |
| Name: buffer |
| Name: neo-buffer | |||||
| Namespace: neo | |||||
| Version: 0.1.0 |
| #pragma once | |||||
| #include <cstddef> | |||||
| #include <iterator> | |||||
| namespace neo { | |||||
| namespace detail { | |||||
| class single_buffer_iter_sentinel {}; | |||||
| template <typename Buffer> | |||||
| class single_buffer_iter { | |||||
| Buffer _buf; | |||||
| bool _dead = false; | |||||
| public: | |||||
| using difference_type = std::ptrdiff_t; | |||||
| using value_type = Buffer; | |||||
| using pointer = const value_type*; | |||||
| using reference = const value_type&; | |||||
| using iterator_category = std::forward_iterator_tag; | |||||
| constexpr single_buffer_iter(Buffer b) noexcept | |||||
| : _buf(b) {} | |||||
| constexpr reference operator*() const noexcept { return _buf; } | |||||
| constexpr pointer operator->() const noexcept { return &_buf; } | |||||
| constexpr bool operator==(single_buffer_iter_sentinel) const noexcept { return _dead; } | |||||
| constexpr bool operator!=(single_buffer_iter_sentinel) const noexcept { return !_dead; } | |||||
| constexpr bool operator==(single_buffer_iter o) const noexcept { return _dead == o._dead; } | |||||
| constexpr bool operator!=(single_buffer_iter o) const noexcept { return !(*this == o); } | |||||
| constexpr single_buffer_iter operator++(int) noexcept { | |||||
| auto me = *this; | |||||
| _dead = true; | |||||
| return me; | |||||
| } | |||||
| constexpr single_buffer_iter& operator++() noexcept { | |||||
| _dead = true; | |||||
| return *this; | |||||
| } | |||||
| }; | |||||
| } // namespace detail | |||||
| template <typename T> | |||||
| constexpr std::byte* byte_pointer(T* ptr) noexcept requires std::is_trivial_v<T> { | |||||
| auto void_ = static_cast<void*>(ptr); | |||||
| return static_cast<std::byte*>(void_); | |||||
| } | |||||
| template <typename T> | |||||
| constexpr const std::byte* byte_pointer(const T* ptr) noexcept requires std::is_trivial_v<T> { | |||||
| auto void_ = static_cast<const void*>(ptr); | |||||
| return static_cast<const std::byte*>(void_); | |||||
| } | |||||
| } // namespace neo |
| #include "./buffer.hpp" |
| #pragma once | |||||
| #include <neo/const_buffer.hpp> | |||||
| #include <neo/mutable_buffer.hpp> | |||||
| #include <string> | |||||
| #include <string_view> | |||||
| #include <type_traits> | |||||
| namespace neo { | |||||
| constexpr mutable_buffer buffer(const mutable_buffer& b) noexcept { return b; } | |||||
| constexpr mutable_buffer buffer(const mutable_buffer& b, mutable_buffer::size_type s) noexcept { | |||||
| auto min_size = s > b.size() ? b.size() : s; | |||||
| return mutable_buffer(b.data(), min_size); | |||||
| } | |||||
| constexpr const_buffer buffer(const const_buffer& b) noexcept { return b; } | |||||
| constexpr const_buffer buffer(const const_buffer& b, const_buffer::size_type s) noexcept { | |||||
| auto min_size = s > b.size() ? b.size() : s; | |||||
| return const_buffer(b.data(), min_size); | |||||
| } | |||||
| // ############################################################################# | |||||
| /** | |||||
| * Create a mutable buffer from an opaque pointer to void | |||||
| */ | |||||
| constexpr mutable_buffer buffer(void* ptr, mutable_buffer::size_type s) noexcept { | |||||
| return mutable_buffer(static_cast<std::byte*>(ptr), s); | |||||
| } | |||||
| /** | |||||
| * Create an immutable buffer from an opaque pointer to void | |||||
| */ | |||||
| constexpr const_buffer buffer(const void* ptr, const_buffer::size_type s) noexcept { | |||||
| return const_buffer(static_cast<const std::byte*>(ptr), s); | |||||
| } | |||||
| // ############################################################################# | |||||
| /** | |||||
| * Create a mutable buffer that refers to the bytes of a trivial object. | |||||
| */ | |||||
| template <typename Trivial, | |||||
| typename | |||||
| = std::enable_if_t<!std::is_const_v<Trivial> && !std::is_same_v<Trivial, mutable_buffer>>> | |||||
| constexpr mutable_buffer buffer(Trivial& item, std::size_t max_size = sizeof(Trivial)) { | |||||
| auto min_size = max_size > sizeof(item) ? sizeof(item) : max_size; | |||||
| return mutable_buffer(byte_pointer(std::addressof(item)), min_size); | |||||
| } | |||||
| /** | |||||
| * Create an immutable buffer that refers to the bytes of a trivial object. | |||||
| */ | |||||
| template < | |||||
| typename Trivial, | |||||
| typename = std::enable_if_t< | |||||
| std::is_const_v< | |||||
| Trivial> && !std::is_same_v<Trivial, mutable_buffer> && !std::is_same_v<Trivial, const_buffer>>> | |||||
| constexpr const_buffer buffer(Trivial& item, std::size_t max_size = sizeof(Trivial)) { | |||||
| auto min_size = std::min(sizeof(item), max_size); | |||||
| return const_buffer(byte_pointer(std::addressof(item)), min_size); | |||||
| } | |||||
| // ############################################################################# | |||||
| /** | |||||
| * Create a mutable buffer referring to the characters of a basic_string object | |||||
| */ | |||||
| template <typename Char, typename Traits, typename Alloc> | |||||
| constexpr mutable_buffer buffer(std::basic_string<Char, Traits, Alloc>& str, std::size_t max_size) { | |||||
| auto use_size = max_size > str.size() ? str.size() : max_size; | |||||
| return buffer(str.data(), use_size); | |||||
| } | |||||
| template <typename Char, typename Traits, typename Alloc> | |||||
| constexpr mutable_buffer buffer(std::basic_string<Char, Traits, Alloc>& str) { | |||||
| return buffer(str, str.size()); | |||||
| } | |||||
| /** | |||||
| * Create an immutable buffer refering to the characters of a basic_string object | |||||
| */ | |||||
| template <typename Char, typename Traits, typename Alloc> | |||||
| constexpr const_buffer buffer(const std::basic_string<Char, Traits, Alloc>& str, | |||||
| std::size_t max_size) { | |||||
| auto use_size = max_size > str.size() ? str.size() : max_size; | |||||
| return buffer(str.data(), use_size); | |||||
| } | |||||
| template <typename Char, typename Traits, typename Alloc> | |||||
| constexpr const_buffer buffer(const std::basic_string<Char, Traits, Alloc>& str) { | |||||
| return buffer(str, str.size()); | |||||
| } | |||||
| // ############################################################################# | |||||
| /** | |||||
| * Create an immutable buffer referring to the characters of a basic_string_view | |||||
| */ | |||||
| template <typename Char, typename Traits> | |||||
| constexpr const_buffer buffer(std::basic_string_view<Char, Traits> sv, std::size_t max_size) { | |||||
| auto use_size = max_size > sv.size() ? sv.size() : max_size; | |||||
| return buffer(sv.data(), use_size); | |||||
| } | |||||
| template <typename Char, typename Traits> | |||||
| constexpr const_buffer buffer(std::basic_string_view<Char, Traits> sv) { | |||||
| return buffer(sv, sv.size()); | |||||
| } | |||||
| } // namespace neo |
| #include <neo/buffer.hpp> | |||||
| #include <neo/buffer.test.hpp> | |||||
| #include <neo/buffer_algorithm.hpp> | |||||
| #include <array> | |||||
| #include <string> | |||||
| struct my_simple_struct { | |||||
| int a; | |||||
| int b; | |||||
| }; | |||||
| int main() { | |||||
| // std::string s = "I am a string!"; | |||||
| // auto s_buf = neo::buffer(s); | |||||
| // CHECK(s_buf.data() == s.data()); | |||||
| my_simple_struct foo; | |||||
| foo.a = 12; | |||||
| foo.b = 3; | |||||
| neo::mutable_buffer pod_buf = neo::buffer(foo); | |||||
| CHECK(pod_buf.size() == sizeof(foo)); | |||||
| my_simple_struct bar; | |||||
| neo::buffer_copy(neo::buffer(bar), pod_buf); | |||||
| CHECK(bar.a == foo.a); | |||||
| CHECK(bar.b == foo.b); | |||||
| bar.b = 55; | |||||
| std::array<char, sizeof bar> buf; | |||||
| neo::buffer_copy(neo::buffer(buf), neo::buffer(bar)); | |||||
| neo::buffer_copy(neo::buffer(foo), neo::buffer(buf)); | |||||
| CHECK(foo.b == 55); | |||||
| } |
| #pragma once | |||||
| #include <iostream> | |||||
| #define CHECK(...) \ | |||||
| do { \ | |||||
| if (!(__VA_ARGS__)) { \ | |||||
| std::cerr << "Check failed: " << (#__VA_ARGS__) << '\n'; \ | |||||
| return 1; \ | |||||
| } \ | |||||
| } while (0) |
| #pragma once | |||||
| #include <neo/buffer_concepts.hpp> | |||||
| #include <neo/const_buffer.hpp> | |||||
| #include <neo/mutable_buffer.hpp> | |||||
| #include <algorithm> | |||||
| #include <cstddef> | |||||
| #include <cstring> | |||||
| namespace neo { | |||||
| template <typename Seq> | |||||
| constexpr std::size_t buffer_size(const Seq& seq) { | |||||
| auto iter = buffer_sequence_begin(seq); | |||||
| const auto stop = buffer_sequence_end(seq); | |||||
| std::size_t size = 0; | |||||
| while (iter != stop) { | |||||
| size += static_cast<std::size_t>(iter->size()); | |||||
| ++iter; | |||||
| } | |||||
| return size; | |||||
| } | |||||
| template <mutable_buffer_sequence MutableSeq, const_buffer_sequence ConstSeq> | |||||
| constexpr std::size_t | |||||
| buffer_copy(const MutableSeq& dest, const ConstSeq& src, std::size_t max_copy) { | |||||
| auto remaining_to_copy = max_copy; | |||||
| std::size_t n_copied = 0; | |||||
| auto dest_iter = buffer_sequence_begin(dest); | |||||
| const auto dest_stop = buffer_sequence_end(dest); | |||||
| auto src_iter = buffer_sequence_begin(src); | |||||
| const auto src_stop = buffer_sequence_end(dest); | |||||
| std::size_t src_offset = 0; | |||||
| std::size_t dest_offset = 0; | |||||
| while (dest_iter != dest_stop && src_iter != src_stop && remaining_to_copy) { | |||||
| const_buffer src_buf = *src_iter + src_offset; | |||||
| mutable_buffer dest_buf = *dest_iter + dest_offset; | |||||
| const auto copy_now | |||||
| = std::min(src_buf.size(), std::min(dest_buf.size(), remaining_to_copy)); | |||||
| std::memcpy(dest_buf.data(), src_buf.data(), copy_now); | |||||
| n_copied += copy_now; | |||||
| src_buf += n_copied; | |||||
| dest_buf += n_copied; | |||||
| src_offset += n_copied; | |||||
| dest_offset += n_copied; | |||||
| if (src_buf.size() == 0) { | |||||
| ++src_iter; | |||||
| src_offset = 0; | |||||
| } | |||||
| if (dest_buf.size() == 0) { | |||||
| ++dest_iter; | |||||
| dest_offset = 0; | |||||
| } | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| template <typename MutableSeq, typename ConstSeq> | |||||
| constexpr std::size_t buffer_copy(const MutableSeq& dest, const ConstSeq& src) { | |||||
| auto src_size = buffer_size(src); | |||||
| auto dest_size = buffer_size(dest); | |||||
| auto min_size = (src_size > dest_size) ? dest_size : src_size; | |||||
| return buffer_copy(dest, src, min_size); | |||||
| } | |||||
| } // namespace neo |
| #include <neo/buffer_algorithm.hpp> | |||||
| #include <neo/buffer.test.hpp> | |||||
| #include <neo/const_buffer.hpp> | |||||
| #include <string_view> | |||||
| int main() { | |||||
| auto buf = neo::const_buffer("A string"); | |||||
| auto buf_iter = neo::buffer_sequence_begin(buf); | |||||
| CHECK(buf_iter->data() == buf.data()); | |||||
| CHECK(buf_iter != neo::buffer_sequence_end(buf)); | |||||
| CHECK(neo::buffer_size(buf) == buf.size()); | |||||
| // neo::buffer_size(12); | |||||
| } |
| #pragma once | |||||
| #ifndef NEO_CONCEPT | |||||
| #if defined(__GNUC__) && __GNUC__ < 9 | |||||
| #define NEO_CONCEPT concept bool | |||||
| #else | |||||
| #define NEO_CONCEPT concept | |||||
| #endif | |||||
| #endif | |||||
| #include <neo/buffer_seq_iter.hpp> | |||||
| #include <neo/const_buffer.hpp> | |||||
| #include <neo/mutable_buffer.hpp> | |||||
| #include <iterator> | |||||
| namespace neo { | |||||
| template <typename T> | |||||
| NEO_CONCEPT const_buffer_sequence_iterator = requires(T iter) { | |||||
| typename std::iterator_traits<T>::value_type; | |||||
| std::is_convertible_v<typename std::iterator_traits<T>::value_type, const_buffer>; | |||||
| }; | |||||
| template <typename T> | |||||
| NEO_CONCEPT mutable_buffer_sequence_iterator | |||||
| = const_buffer_sequence_iterator<T>&& requires(T iter) { | |||||
| std::is_convertible_v<typename std::iterator_traits<T>::value_type, mutable_buffer>; | |||||
| }; | |||||
| template <typename T> | |||||
| NEO_CONCEPT const_buffer_sequence = requires(T seq) { | |||||
| { buffer_sequence_begin(seq) } | |||||
| ->const_buffer_sequence_iterator; | |||||
| buffer_sequence_end(seq); | |||||
| { buffer_sequence_begin(seq) != buffer_sequence_end(seq) } | |||||
| ->bool; | |||||
| }; | |||||
| template <typename T> | |||||
| NEO_CONCEPT mutable_buffer_sequence = const_buffer_sequence<T>&& requires(T seq) { | |||||
| { buffer_sequence_begin(seq) } | |||||
| ->mutable_buffer_sequence_iterator; | |||||
| }; | |||||
| } // namespace neo |
| #pragma once | |||||
| #include <utility> | |||||
| namespace neo { | |||||
| constexpr inline struct buffer_sequence_begin_fn { | |||||
| template <typename T> | |||||
| decltype(auto) operator()(T&& t) const requires requires { | |||||
| buffer_sequence_begin(t); | |||||
| } | |||||
| { return buffer_sequence_begin(t); } | |||||
| template <typename T> | |||||
| decltype(auto) operator()(T&& t) const requires requires { | |||||
| t.buffer_sequence_begin(); | |||||
| } | |||||
| { return t.buffer_sequence_begin(); } | |||||
| template <typename T> | |||||
| decltype(auto) operator()(T&& t) const requires requires { | |||||
| _impl_buffer_sequence_begin(t); | |||||
| } | |||||
| { return _impl_buffer_sequence_begin(t); } | |||||
| } buffer_sequence_begin; | |||||
| inline struct buffer_sequence_end_fn { | |||||
| template <typename T> | |||||
| decltype(auto) operator()(T&& t) const requires requires { | |||||
| buffer_sequence_end(t); | |||||
| } | |||||
| { return buffer_sequence_end(t); } | |||||
| template <typename T> | |||||
| decltype(auto) operator()(T&& t) const requires requires { | |||||
| t.buffer_sequence_end(); | |||||
| } | |||||
| { return t.buffer_sequence_end(); } | |||||
| template <typename T> | |||||
| decltype(auto) operator()(T&& t) const requires requires { | |||||
| _impl_buffer_sequence_end(t); | |||||
| } | |||||
| { return _impl_buffer_sequence_end(t); } | |||||
| } buffer_sequence_end; | |||||
| } // namespace neo |
| #pragma once | |||||
| #include <neo/base_buffer.hpp> | |||||
| #include <neo/mutable_buffer.hpp> | |||||
| #include <cassert> | |||||
| #include <cstddef> | |||||
| #include <string_view> | |||||
| namespace neo { | |||||
| /** | |||||
| * A type that represents a view to a readonly segment of contiguous memory. | |||||
| */ | |||||
| class const_buffer { | |||||
| public: | |||||
| using pointer = const std::byte*; | |||||
| using size_type = std::size_t; | |||||
| private: | |||||
| pointer _data = nullptr; | |||||
| size_type _size = 0; | |||||
| public: | |||||
| constexpr const_buffer() noexcept = default; | |||||
| constexpr const_buffer(pointer ptr, size_type size) noexcept | |||||
| : _data(ptr) | |||||
| , _size(size) {} | |||||
| constexpr const_buffer(mutable_buffer buf) | |||||
| : _data(buf.data()) | |||||
| , _size(buf.size()) {} | |||||
| explicit constexpr const_buffer(std::string_view sv) | |||||
| : _data(byte_pointer(sv.data())) | |||||
| , _size(sv.size()) {} | |||||
| constexpr pointer data() const noexcept { return _data; } | |||||
| constexpr pointer data_end() const noexcept { return _data + size(); } | |||||
| constexpr size_type size() const noexcept { return _size; } | |||||
| constexpr const_buffer& operator+=(size_type s) noexcept { | |||||
| assert(s <= size() && "Advanced neo::const_buffer past-the-end"); | |||||
| _data += s; | |||||
| _size -= s; | |||||
| return *this; | |||||
| } | |||||
| }; | |||||
| inline constexpr const_buffer operator+(const_buffer buf, const_buffer::size_type s) noexcept { | |||||
| auto copy = buf; | |||||
| copy += s; | |||||
| return copy; | |||||
| } | |||||
| inline constexpr auto _impl_buffer_sequence_begin(const_buffer buf) noexcept { | |||||
| return detail::single_buffer_iter(buf); | |||||
| } | |||||
| inline constexpr auto _impl_buffer_sequence_end(const_buffer) noexcept { | |||||
| return detail::single_buffer_iter_sentinel(); | |||||
| } | |||||
| } // namespace neo |
| #include <neo/buffer.test.hpp> | |||||
| #include <neo/const_buffer.hpp> | |||||
| #include <iostream> | |||||
| int main() { | |||||
| neo::const_buffer buf; | |||||
| CHECK(buf.size() == 0); | |||||
| buf = neo::const_buffer("meow"); | |||||
| CHECK(buf.size() == 4); | |||||
| auto buf2 = buf + 3; | |||||
| CHECK(buf2.size() == 1); | |||||
| CHECK(buf2.data()[0] == std::byte('w')); | |||||
| buf2 += 1; | |||||
| CHECK(buf2.size() == 0); | |||||
| } |
| #pragma once | |||||
| #include <neo/base_buffer.hpp> | |||||
| #include <cstddef> | |||||
| #include <iterator> | |||||
| #include <type_traits> | |||||
| namespace neo { | |||||
| class mutable_buffer { | |||||
| public: | |||||
| using pointer = std::byte*; | |||||
| using size_type = std::size_t; | |||||
| private: | |||||
| pointer _data = nullptr; | |||||
| size_type _size = 0; | |||||
| public: | |||||
| constexpr mutable_buffer() noexcept = default; | |||||
| constexpr mutable_buffer(pointer p, size_type size) noexcept | |||||
| : _data(p) | |||||
| , _size(size) {} | |||||
| constexpr mutable_buffer& operator+=(size_type s) noexcept { | |||||
| _data += s; | |||||
| _size -= s; | |||||
| return *this; | |||||
| } | |||||
| constexpr pointer data() const noexcept { return _data; } | |||||
| constexpr pointer data_end() const noexcept { return _data + size(); } | |||||
| constexpr size_type size() const noexcept { return _size; } | |||||
| }; | |||||
| inline constexpr mutable_buffer operator+(mutable_buffer buf, | |||||
| mutable_buffer::size_type s) noexcept { | |||||
| auto copy = buf; | |||||
| copy += s; | |||||
| return copy; | |||||
| } | |||||
| inline constexpr auto _impl_buffer_sequence_begin(mutable_buffer buf) noexcept { | |||||
| return detail::single_buffer_iter(buf); | |||||
| } | |||||
| inline constexpr auto _impl_buffer_sequence_end(mutable_buffer) noexcept { | |||||
| return detail::single_buffer_iter_sentinel(); | |||||
| } | |||||
| } // namespace neo |
| #include <neo/mutable_buffer.hpp> | |||||
| int main() {} |
| Compiler-ID: GNU | |||||
| C++-Compiler: g++-8 | |||||
| C++-Version: C++17 | |||||
| Flags: -fconcepts |
| Name: json |
| Name: nlohmann-json | |||||
| Namespace: nlohmann | |||||
| Version: 3.7.0 |
| /// \file | |||||
| // Concepts library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| #ifndef CPP_SWAP_HPP | |||||
| #define CPP_SWAP_HPP | |||||
| #include <tuple> | |||||
| #include <utility> | |||||
| #include <type_traits> | |||||
| #include <meta/meta.hpp> | |||||
| // Note: constexpr implies inline, to retain the same visibility | |||||
| // C++14 constexpr functions are inline in C++11 | |||||
| #if (defined(__cpp_constexpr) && __cpp_constexpr >= 201304L) ||\ | |||||
| (!defined(__cpp_constexpr) && __cplusplus >= 201402L) | |||||
| #define CPP_CXX14_CONSTEXPR constexpr | |||||
| #else | |||||
| #define CPP_CXX14_CONSTEXPR inline | |||||
| #endif | |||||
| #ifndef CPP_CXX_INLINE_VARIABLES | |||||
| #ifdef __cpp_inline_variables // TODO: fix this if SD-6 picks another name | |||||
| #define CPP_CXX_INLINE_VARIABLES __cpp_inline_variables | |||||
| // TODO: remove once clang defines __cpp_inline_variables (or equivalent) | |||||
| #elif defined(__clang__) && \ | |||||
| (__clang_major__ > 3 || __clang_major__ == 3 && __clang_minor__ == 9) && \ | |||||
| __cplusplus > 201402L | |||||
| #define CPP_CXX_INLINE_VARIABLES 201606L | |||||
| #else | |||||
| #define CPP_CXX_INLINE_VARIABLES __cplusplus | |||||
| #endif // __cpp_inline_variables | |||||
| #endif // CPP_CXX_INLINE_VARIABLES | |||||
| #if defined(_MSC_VER) && !defined(__clang__) | |||||
| #define CPP_WORKAROUND_MSVC_895622 // Error when phase 1 name binding finds only deleted function | |||||
| #endif | |||||
| #if CPP_CXX_INLINE_VARIABLES < 201606L | |||||
| #define CPP_INLINE_VAR | |||||
| #define CPP_INLINE_VARIABLE(type, name) \ | |||||
| inline namespace \ | |||||
| { \ | |||||
| constexpr auto &name = ::concepts::detail::static_const<type>::value; \ | |||||
| } \ | |||||
| /**/ | |||||
| #else // CPP_CXX_INLINE_VARIABLES >= 201606L | |||||
| #define CPP_INLINE_VAR inline | |||||
| #define CPP_INLINE_VARIABLE(type, name) \ | |||||
| inline constexpr type name{}; \ | |||||
| /**/ | |||||
| #endif // CPP_CXX_INLINE_VARIABLES | |||||
| #if CPP_CXX_INLINE_VARIABLES < 201606L | |||||
| #define CPP_DEFINE_CPO(type, name) \ | |||||
| inline namespace \ | |||||
| { \ | |||||
| constexpr auto &name = ::concepts::detail::static_const<type>::value; \ | |||||
| } \ | |||||
| /**/ | |||||
| #else // CPP_CXX_INLINE_VARIABLES >= 201606L | |||||
| #define CPP_DEFINE_CPO(type, name) \ | |||||
| inline namespace _ \ | |||||
| { \ | |||||
| inline constexpr type name{}; \ | |||||
| } \ | |||||
| /**/ | |||||
| #endif // CPP_CXX_INLINE_VARIABLES | |||||
| #if defined(_MSC_VER) && !defined(__clang__) | |||||
| #define CPP_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME | |||||
| #else // ^^^ defined(_MSC_VER) ^^^ / vvv !defined(_MSC_VER) vvv | |||||
| #if defined(__GNUC__) || defined(__clang__) | |||||
| #define CPP_PRAGMA(X) _Pragma(#X) | |||||
| #define CPP_DIAGNOSTIC_IGNORE_PRAGMAS \ | |||||
| CPP_PRAGMA(GCC diagnostic ignored "-Wpragmas") | |||||
| #define CPP_DIAGNOSTIC_IGNORE(X) \ | |||||
| CPP_DIAGNOSTIC_IGNORE_PRAGMAS \ | |||||
| CPP_PRAGMA(GCC diagnostic ignored "-Wunknown-pragmas") \ | |||||
| CPP_PRAGMA(GCC diagnostic ignored X) | |||||
| #define CPP_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME \ | |||||
| CPP_DIAGNOSTIC_IGNORE("-Wunknown-warning-option") \ | |||||
| CPP_DIAGNOSTIC_IGNORE("-Winit-list-lifetime") | |||||
| #else | |||||
| #define CPP_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME | |||||
| #endif | |||||
| #endif // MSVC/Generic configuration switch | |||||
| namespace concepts | |||||
| { | |||||
| /// \cond | |||||
| namespace detail | |||||
| { | |||||
| template<typename T> | |||||
| CPP_INLINE_VAR constexpr bool is_movable_v = | |||||
| std::is_object<T>::value && | |||||
| std::is_move_constructible<T>::value && | |||||
| std::is_move_assignable<T>::value; | |||||
| template<typename T> | |||||
| struct static_const | |||||
| { | |||||
| static constexpr T const value {}; | |||||
| }; | |||||
| template<typename T> | |||||
| constexpr T const static_const<T>::value; | |||||
| } | |||||
| /// \endcond | |||||
| template<typename T> | |||||
| struct is_swappable; | |||||
| template<typename T> | |||||
| struct is_nothrow_swappable; | |||||
| template<typename T, typename U> | |||||
| struct is_swappable_with; | |||||
| template<typename T, typename U> | |||||
| struct is_nothrow_swappable_with; | |||||
| template<typename T, typename U = T> | |||||
| CPP_CXX14_CONSTEXPR | |||||
| meta::if_c< | |||||
| std::is_move_constructible<T>::value && | |||||
| std::is_assignable<T &, U>::value, T> | |||||
| exchange(T &t, U &&u) | |||||
| noexcept( | |||||
| std::is_nothrow_move_constructible<T>::value && | |||||
| std::is_nothrow_assignable<T &, U>::value) | |||||
| { | |||||
| T tmp((T &&) t); | |||||
| t = (U &&) u; | |||||
| CPP_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME | |||||
| return tmp; | |||||
| } | |||||
| /// \cond | |||||
| namespace adl_swap_detail | |||||
| { | |||||
| struct nope | |||||
| {}; | |||||
| // Intentionally create an ambiguity with std::swap, which is | |||||
| // (possibly) unconstrained. | |||||
| template<typename T> | |||||
| nope swap(T &, T &) = delete; | |||||
| template<typename T, std::size_t N> | |||||
| nope swap(T (&)[N], T (&)[N]) = delete; | |||||
| #ifdef CPP_WORKAROUND_MSVC_895622 | |||||
| nope swap(); | |||||
| #endif | |||||
| template<typename T, typename U> | |||||
| decltype(swap(std::declval<T>(), std::declval<U>())) try_adl_swap_(int); | |||||
| template<typename T, typename U> | |||||
| nope try_adl_swap_(long); | |||||
| template<typename T, typename U = T> | |||||
| CPP_INLINE_VAR constexpr bool is_adl_swappable_v = | |||||
| !META_IS_SAME(decltype(adl_swap_detail::try_adl_swap_<T, U>(42)), nope); | |||||
| struct swap_fn | |||||
| { | |||||
| // Dispatch to user-defined swap found via ADL: | |||||
| template<typename T, typename U> | |||||
| CPP_CXX14_CONSTEXPR | |||||
| meta::if_c<is_adl_swappable_v<T, U>> | |||||
| operator()(T &&t, U &&u) const | |||||
| noexcept(noexcept(swap((T &&) t, (U &&) u))) | |||||
| { | |||||
| swap((T &&) t, (U &&) u); | |||||
| } | |||||
| // For intrinsically swappable (i.e., movable) types for which | |||||
| // a swap overload cannot be found via ADL, swap by moving. | |||||
| template<typename T> | |||||
| CPP_CXX14_CONSTEXPR | |||||
| meta::if_c< | |||||
| !is_adl_swappable_v<T &> && | |||||
| detail::is_movable_v<T>> | |||||
| operator()(T &a, T &b) const | |||||
| noexcept(noexcept(b = concepts::exchange(a, (T &&) b))) | |||||
| { | |||||
| b = concepts::exchange(a, (T &&) b); | |||||
| } | |||||
| // For arrays of intrinsically swappable (i.e., movable) types | |||||
| // for which a swap overload cannot be found via ADL, swap array | |||||
| // elements by moving. | |||||
| template<typename T, typename U, std::size_t N> | |||||
| CPP_CXX14_CONSTEXPR | |||||
| meta::if_c< | |||||
| !is_adl_swappable_v<T (&)[N], U (&)[N]> && | |||||
| is_swappable_with<T &, U &>::value> | |||||
| operator()(T (&t)[N], U (&u)[N]) const | |||||
| noexcept(is_nothrow_swappable_with<T &, U &>::value) | |||||
| { | |||||
| for(std::size_t i = 0; i < N; ++i) | |||||
| (*this)(t[i], u[i]); | |||||
| } | |||||
| // For rvalue pairs and tuples of swappable types, swap the | |||||
| // members. This permits code like: | |||||
| // ranges::swap(std::tie(a,b,c), std::tie(d,e,f)); | |||||
| template<typename F0, typename S0, typename F1, typename S1> | |||||
| CPP_CXX14_CONSTEXPR | |||||
| meta::if_c<is_swappable_with<F0, F1>::value && is_swappable_with<S0, S1>::value> | |||||
| operator()(std::pair<F0, S0> &&left, std::pair<F1, S1> &&right) const | |||||
| noexcept( | |||||
| is_nothrow_swappable_with<F0, F1>::value && | |||||
| is_nothrow_swappable_with<S0, S1>::value) | |||||
| { | |||||
| swap_fn()(static_cast<std::pair<F0, S0> &&>(left).first, | |||||
| static_cast<std::pair<F1, S1> &&>(right).first); | |||||
| swap_fn()(static_cast<std::pair<F0, S0> &&>(left).second, | |||||
| static_cast<std::pair<F1, S1> &&>(right).second); | |||||
| } | |||||
| template<typename ...Ts, typename ...Us> | |||||
| CPP_CXX14_CONSTEXPR | |||||
| meta::if_c<meta::and_c<is_swappable_with<Ts, Us>::value...>::value> | |||||
| operator()(std::tuple<Ts...> &&left, std::tuple<Us...> &&right) const | |||||
| noexcept(meta::and_c<is_nothrow_swappable_with<Ts, Us>::value...>::value) | |||||
| { | |||||
| swap_fn::impl( | |||||
| static_cast<std::tuple<Ts...> &&>(left), | |||||
| static_cast<std::tuple<Us...> &&>(right), | |||||
| meta::make_index_sequence<sizeof...(Ts)>{}); | |||||
| } | |||||
| private: | |||||
| template<typename... Ts> | |||||
| static constexpr int ignore_unused(Ts &&...) | |||||
| { | |||||
| return 0; | |||||
| } | |||||
| template<typename T, typename U, std::size_t ...Is> | |||||
| CPP_CXX14_CONSTEXPR | |||||
| static void impl(T &&left, U &&right, meta::index_sequence<Is...>) | |||||
| { | |||||
| (void) swap_fn::ignore_unused( | |||||
| (swap_fn()(std::get<Is>(static_cast<T &&>(left)), | |||||
| std::get<Is>(static_cast<U &&>(right))), 42)...); | |||||
| } | |||||
| }; | |||||
| template<typename T, typename U, typename = void> | |||||
| struct is_swappable_with_ | |||||
| : std::false_type | |||||
| {}; | |||||
| template<typename T, typename U> | |||||
| struct is_swappable_with_<T, U, meta::void_< | |||||
| decltype(swap_fn()(std::declval<T>(), std::declval<U>())), | |||||
| decltype(swap_fn()(std::declval<U>(), std::declval<T>()))>> | |||||
| : std::true_type | |||||
| {}; | |||||
| template<typename T, typename U> | |||||
| struct is_nothrow_swappable_with_ | |||||
| : meta::bool_<noexcept(swap_fn()(std::declval<T>(), std::declval<U>())) && | |||||
| noexcept(swap_fn()(std::declval<U>(), std::declval<T>()))> | |||||
| {}; | |||||
| // Q: Should std::reference_wrapper be considered a proxy wrt swapping rvalues? | |||||
| // A: No. Its operator= is currently defined to reseat the references, so | |||||
| // std::swap(ra, rb) already means something when ra and rb are (lvalue) | |||||
| // reference_wrappers. That reseats the reference wrappers but leaves the | |||||
| // referents unmodified. Treating rvalue reference_wrappers differently would | |||||
| // be confusing. | |||||
| // Q: Then why is it OK to "re"-define swap for pairs and tuples of references? | |||||
| // A: Because as defined above, swapping an rvalue tuple of references has the same | |||||
| // semantics as swapping an lvalue tuple of references. Rather than reseat the | |||||
| // references, assignment happens *through* the references. | |||||
| // Q: But I have an iterator whose operator* returns an rvalue | |||||
| // std::reference_wrapper<T>. How do I make it model indirectly_swappable? | |||||
| // A: With an overload of iter_swap. | |||||
| } | |||||
| /// \endcond | |||||
| /// \ingroup group-utility | |||||
| template<typename T, typename U> | |||||
| struct is_swappable_with | |||||
| : adl_swap_detail::is_swappable_with_<T, U> | |||||
| {}; | |||||
| /// \ingroup group-utility | |||||
| template<typename T, typename U> | |||||
| struct is_nothrow_swappable_with | |||||
| : meta::and_< | |||||
| is_swappable_with<T, U>, | |||||
| adl_swap_detail::is_nothrow_swappable_with_<T, U>> | |||||
| {}; | |||||
| /// \ingroup group-utility | |||||
| template<typename T> | |||||
| struct is_swappable | |||||
| : is_swappable_with<T &, T &> | |||||
| {}; | |||||
| /// \ingroup group-utility | |||||
| template<typename T> | |||||
| struct is_nothrow_swappable | |||||
| : is_nothrow_swappable_with<T &, T &> | |||||
| {}; | |||||
| /// \ingroup group-utility | |||||
| /// \relates adl_swap_detail::swap_fn | |||||
| CPP_DEFINE_CPO(adl_swap_detail::swap_fn, swap) | |||||
| } | |||||
| #endif |
| /// \file | |||||
| // Concepts library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| #ifndef CPP_TYPE_TRAITS_HPP | |||||
| #define CPP_TYPE_TRAITS_HPP | |||||
| #include <tuple> | |||||
| #include <utility> | |||||
| #include <type_traits> | |||||
| #include <meta/meta.hpp> | |||||
| namespace concepts | |||||
| { | |||||
| template<typename T> | |||||
| using remove_cvref_t = | |||||
| typename std::remove_cv< | |||||
| typename std::remove_reference<T>::type>::type; | |||||
| /// \cond | |||||
| namespace detail | |||||
| { | |||||
| template<typename From, typename To> | |||||
| using is_convertible = std::is_convertible<meta::_t<std::add_rvalue_reference<From>>, To>; | |||||
| template<bool> | |||||
| struct if_else_ | |||||
| { | |||||
| template<typename, typename U> | |||||
| using invoke = U; | |||||
| }; | |||||
| template<> | |||||
| struct if_else_<true> | |||||
| { | |||||
| template<typename T, typename> | |||||
| using invoke = T; | |||||
| }; | |||||
| template<bool B, typename T, typename U> | |||||
| using if_else_t = meta::invoke<if_else_<B>, T, U>; | |||||
| template<bool> | |||||
| struct if_ | |||||
| {}; | |||||
| template<> | |||||
| struct if_<true> | |||||
| { | |||||
| template<typename T> | |||||
| using invoke = T; | |||||
| }; | |||||
| template<bool B, typename T = void> | |||||
| using if_t = meta::invoke<if_<B>, T>; | |||||
| template<typename From, typename To> | |||||
| struct _copy_cv_ | |||||
| { | |||||
| using type = To; | |||||
| }; | |||||
| template<typename From, typename To> | |||||
| struct _copy_cv_<From const, To> | |||||
| { | |||||
| using type = To const; | |||||
| }; | |||||
| template<typename From, typename To> | |||||
| struct _copy_cv_<From volatile, To> | |||||
| { | |||||
| using type = To volatile; | |||||
| }; | |||||
| template<typename From, typename To> | |||||
| struct _copy_cv_<From const volatile, To> | |||||
| { | |||||
| using type = To const volatile; | |||||
| }; | |||||
| template<typename From, typename To> | |||||
| using _copy_cv = meta::_t<_copy_cv_<From, To>>; | |||||
| //////////////////////////////////////////////////////////////////////////////////////// | |||||
| template<typename T, typename U, typename = void> | |||||
| struct _builtin_common; | |||||
| template<typename T, typename U> | |||||
| using _builtin_common_t = meta::_t<_builtin_common<T, U>>; | |||||
| template<typename T, typename U> | |||||
| using _cond_res = decltype(true ? std::declval<T>() : std::declval<U>()); | |||||
| template<typename T, typename U, typename R = _builtin_common_t<T &, U &>> | |||||
| using _rref_res = | |||||
| if_else_t<std::is_reference<R>::value, meta::_t<std::remove_reference<R>> &&, R>; | |||||
| template<typename T, typename U> | |||||
| using _lref_res = _cond_res<_copy_cv<T, U> &, _copy_cv<U, T> &>; | |||||
| template<typename T> | |||||
| struct as_cref_ | |||||
| { | |||||
| using type = T const &; | |||||
| }; | |||||
| template<typename T> | |||||
| struct as_cref_<T &> | |||||
| { | |||||
| using type = T const &; | |||||
| }; | |||||
| template<typename T> | |||||
| struct as_cref_<T &&> | |||||
| { | |||||
| using type = T const &; | |||||
| }; | |||||
| template<> | |||||
| struct as_cref_<void> | |||||
| { | |||||
| using type = void; | |||||
| }; | |||||
| template<> | |||||
| struct as_cref_<void const> | |||||
| { | |||||
| using type = void const; | |||||
| }; | |||||
| template<typename T> | |||||
| using as_cref_t = typename as_cref_<T>::type; | |||||
| template<typename T> | |||||
| using decay_t = typename std::decay<T>::type; | |||||
| #if !defined(__GNUC__) || defined(__clang__) | |||||
| template<typename T, typename U, typename = void> | |||||
| struct _builtin_common_2 | |||||
| {}; | |||||
| template<typename T, typename U> | |||||
| struct _builtin_common_2<T, U, meta::void_<_cond_res<as_cref_t<T>, as_cref_t<U>>>> | |||||
| : std::decay<_cond_res<as_cref_t<T>, as_cref_t<U>>> | |||||
| {}; | |||||
| template<typename T, typename U, typename /* = void */> | |||||
| struct _builtin_common | |||||
| : _builtin_common_2<T, U> | |||||
| {}; | |||||
| template<typename T, typename U> | |||||
| struct _builtin_common<T &&, U &&, if_t< | |||||
| is_convertible<T &&, _rref_res<T, U>>::value && | |||||
| is_convertible<U &&, _rref_res<T, U>>::value>> | |||||
| { | |||||
| using type = _rref_res<T, U>; | |||||
| }; | |||||
| template<typename T, typename U> | |||||
| struct _builtin_common<T &, U &> | |||||
| : meta::defer<_lref_res, T, U> | |||||
| {}; | |||||
| template<typename T, typename U> | |||||
| struct _builtin_common<T &, U &&, if_t< | |||||
| is_convertible<U &&, _builtin_common_t<T &, U const &>>::value>> | |||||
| : _builtin_common<T &, U const &> | |||||
| {}; | |||||
| template<typename T, typename U> | |||||
| struct _builtin_common<T &&, U &> | |||||
| : _builtin_common<U &, T &&> | |||||
| {}; | |||||
| #else | |||||
| template<typename T, typename U, typename = void> | |||||
| struct _builtin_common_ | |||||
| {}; | |||||
| template<typename T, typename U> | |||||
| struct _builtin_common_<T, U, meta::void_<_cond_res<as_cref_t<T>, as_cref_t<U>>>> | |||||
| : std::decay<_cond_res<as_cref_t<T>, as_cref_t<U>>> | |||||
| {}; | |||||
| template<typename T, typename U, typename /* = void */> | |||||
| struct _builtin_common | |||||
| : _builtin_common_<T, U> | |||||
| {}; | |||||
| template<typename T, typename U, typename = void> | |||||
| struct _builtin_common_rr | |||||
| : _builtin_common_<T &&, U &&> | |||||
| {}; | |||||
| template<typename T, typename U> | |||||
| struct _builtin_common_rr<T, U, if_t< | |||||
| is_convertible<T &&, _rref_res<T, U>>::value && | |||||
| is_convertible<U &&, _rref_res<T, U>>::value>> | |||||
| { | |||||
| using type = _rref_res<T, U>; | |||||
| }; | |||||
| template<typename T, typename U> | |||||
| struct _builtin_common<T &&, U &&> | |||||
| : _builtin_common_rr<T, U> | |||||
| {}; | |||||
| template<typename T, typename U> | |||||
| struct _builtin_common<T &, U &> | |||||
| : meta::defer<_lref_res, T, U> | |||||
| {}; | |||||
| template<typename T, typename U, typename = void> | |||||
| struct _builtin_common_lr | |||||
| : _builtin_common_<T &, T &&> | |||||
| {}; | |||||
| template<typename T, typename U> | |||||
| struct _builtin_common_lr<T, U, if_t< | |||||
| is_convertible<U &&, _builtin_common_t<T &, U const &>>::value>> | |||||
| : _builtin_common<T &, U const &> | |||||
| {}; | |||||
| template<typename T, typename U> | |||||
| struct _builtin_common<T &, U &&> | |||||
| : _builtin_common_lr<T, U> | |||||
| {}; | |||||
| template<typename T, typename U> | |||||
| struct _builtin_common<T &&, U &> | |||||
| : _builtin_common<U &, T &&> | |||||
| {}; | |||||
| #endif | |||||
| } | |||||
| /// \endcond | |||||
| /// \addtogroup group-utility Utility | |||||
| /// @{ | |||||
| /// | |||||
| /// Users should specialize this to hook the \c common_with concept | |||||
| /// until \c std gets a SFINAE-friendly \c std::common_type and there's | |||||
| /// some sane way to deal with cv and ref qualifiers. | |||||
| template<typename ...Ts> | |||||
| struct common_type | |||||
| {}; | |||||
| template<typename T> | |||||
| struct common_type<T> | |||||
| : std::decay<T> | |||||
| {}; | |||||
| template<typename T, typename U> | |||||
| struct common_type<T, U> | |||||
| : detail::if_else_t< | |||||
| (META_IS_SAME(detail::decay_t<T>, T) && | |||||
| META_IS_SAME(detail::decay_t<U>, U) ), | |||||
| meta::defer<detail::_builtin_common_t, T, U>, | |||||
| common_type<detail::decay_t<T>, detail::decay_t<U>>> | |||||
| {}; | |||||
| template<typename... Ts> | |||||
| using common_type_t = typename common_type<Ts...>::type; | |||||
| template<typename T, typename U, typename... Vs> | |||||
| struct common_type<T, U, Vs...> | |||||
| : meta::lazy::fold<meta::list<U, Vs...>, T, meta::quote<common_type_t>> | |||||
| {}; | |||||
| /// @} | |||||
| /// \addtogroup group-utility Utility | |||||
| /// @{ | |||||
| /// | |||||
| /// Users can specialize this to hook the \c common_reference_with concept. | |||||
| /// \sa `common_reference` | |||||
| template< | |||||
| typename T, | |||||
| typename U, | |||||
| template<typename> class TQual, | |||||
| template<typename> class UQual> | |||||
| struct basic_common_reference | |||||
| {}; | |||||
| /// \cond | |||||
| namespace detail | |||||
| { | |||||
| using _rref = | |||||
| meta::quote_trait<std::add_rvalue_reference>; | |||||
| using _lref = | |||||
| meta::quote_trait<std::add_lvalue_reference>; | |||||
| template<typename> | |||||
| struct _xref | |||||
| { | |||||
| template<typename T> | |||||
| using invoke = T; | |||||
| }; | |||||
| template<typename T> | |||||
| struct _xref<T &&> | |||||
| { | |||||
| template<typename U> | |||||
| using invoke = | |||||
| meta::_t<std::add_rvalue_reference<meta::invoke<_xref<T>, U>>>; | |||||
| }; | |||||
| template<typename T> | |||||
| struct _xref<T &> | |||||
| { | |||||
| template<typename U> | |||||
| using invoke = | |||||
| meta::_t<std::add_lvalue_reference<meta::invoke<_xref<T>, U>>>; | |||||
| }; | |||||
| template<typename T> | |||||
| struct _xref<T const> | |||||
| { | |||||
| template<typename U> | |||||
| using invoke = U const; | |||||
| }; | |||||
| template<typename T> | |||||
| struct _xref<T volatile> | |||||
| { | |||||
| template<typename U> | |||||
| using invoke = U volatile; | |||||
| }; | |||||
| template<typename T> | |||||
| struct _xref<T const volatile> | |||||
| { | |||||
| template<typename U> | |||||
| using invoke = U const volatile; | |||||
| }; | |||||
| template<typename T, typename U> | |||||
| using _basic_common_reference = | |||||
| basic_common_reference< | |||||
| remove_cvref_t<T>, | |||||
| remove_cvref_t<U>, | |||||
| _xref<T>::template invoke, | |||||
| _xref<U>::template invoke>; | |||||
| template<typename T, typename U, typename = void> | |||||
| struct _common_reference2 | |||||
| : if_else_t< | |||||
| meta::is_trait<_basic_common_reference<T, U>>::value, | |||||
| _basic_common_reference<T, U>, | |||||
| common_type<T, U>> | |||||
| {}; | |||||
| template<typename T, typename U> | |||||
| struct _common_reference2<T, U, if_t<std::is_reference<_builtin_common_t<T, U>>::value>> | |||||
| : _builtin_common<T, U> | |||||
| {}; | |||||
| } | |||||
| /// \endcond | |||||
| /// Users can specialize this to hook the \c common_reference_with concept. | |||||
| /// \sa `basic_common_reference` | |||||
| template<typename ...Ts> | |||||
| struct common_reference | |||||
| {}; | |||||
| template<typename T> | |||||
| struct common_reference<T> | |||||
| { | |||||
| using type = T; | |||||
| }; | |||||
| template<typename T, typename U> | |||||
| struct common_reference<T, U> | |||||
| : detail::_common_reference2<T, U> | |||||
| {}; | |||||
| template<typename... Ts> | |||||
| using common_reference_t = typename common_reference<Ts...>::type; | |||||
| template<typename T, typename U, typename... Vs> | |||||
| struct common_reference<T, U, Vs...> | |||||
| : meta::lazy::fold<meta::list<U, Vs...>, T, meta::quote<common_reference_t>> | |||||
| {}; | |||||
| /// @} | |||||
| } // namespace concepts | |||||
| #endif |
| /// \file meta_fwd.hpp Forward declarations | |||||
| // | |||||
| // Meta library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/meta | |||||
| // | |||||
| #ifndef META_FWD_HPP | |||||
| #define META_FWD_HPP | |||||
| #include <type_traits> | |||||
| #include <utility> | |||||
| #ifdef __clang__ | |||||
| #pragma GCC diagnostic push | |||||
| #pragma GCC diagnostic ignored "-Wmissing-variable-declarations" | |||||
| #endif | |||||
| #define META_CXX_STD_14 201402L | |||||
| #define META_CXX_STD_17 201703L | |||||
| #if defined(_MSVC_LANG) && _MSVC_LANG > __cplusplus // Older clangs define _MSVC_LANG < __cplusplus | |||||
| #define META_CXX_VER _MSVC_LANG | |||||
| #else | |||||
| #define META_CXX_VER __cplusplus | |||||
| #endif | |||||
| #if defined(__apple_build_version__) || defined(__clang__) | |||||
| #if defined(__apple_build_version__) || (defined(__clang__) && __clang_major__ < 6) | |||||
| #define META_WORKAROUND_LLVM_28385 // https://llvm.org/bugs/show_bug.cgi?id=28385 | |||||
| #endif | |||||
| #elif defined(_MSC_VER) | |||||
| #define META_HAS_MAKE_INTEGER_SEQ 1 | |||||
| #if _MSC_VER < 1920 | |||||
| #define META_WORKAROUND_MSVC_702792 // Bogus C4018 comparing constant expressions with dependent type | |||||
| #define META_WORKAROUND_MSVC_703656 // ICE with pack expansion inside decltype in alias template | |||||
| #endif | |||||
| #if _MSC_VER < 1921 | |||||
| #define META_WORKAROUND_MSVC_756112 // fold expression + alias templates in template argument | |||||
| #endif | |||||
| #elif defined(__GNUC__) | |||||
| #define META_WORKAROUND_GCC_86356 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86356 | |||||
| #if __GNUC__ < 8 | |||||
| #define META_WORKAROUND_GCC_UNKNOWN1 // Older GCCs don't like fold + debug + -march=native | |||||
| #endif | |||||
| #if __GNUC__ == 5 && __GNUC_MINOR__ == 1 | |||||
| #define META_WORKAROUND_GCC_66405 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66405 | |||||
| #endif | |||||
| #if __GNUC__ < 5 | |||||
| #define META_WORKAROUND_CWG_1558 // https://wg21.link/cwg1558 | |||||
| #endif | |||||
| #endif | |||||
| #ifndef META_CXX_VARIABLE_TEMPLATES | |||||
| #ifdef __cpp_variable_templates | |||||
| #define META_CXX_VARIABLE_TEMPLATES __cpp_variable_templates | |||||
| #else | |||||
| #define META_CXX_VARIABLE_TEMPLATES (META_CXX_VER >= META_CXX_STD_14) | |||||
| #endif | |||||
| #endif | |||||
| #ifndef META_CXX_INLINE_VARIABLES | |||||
| #ifdef __cpp_inline_variables | |||||
| #define META_CXX_INLINE_VARIABLES __cpp_inline_variables | |||||
| #else | |||||
| #define META_CXX_INLINE_VARIABLES (META_CXX_VER >= META_CXX_STD_17) | |||||
| #endif | |||||
| #endif | |||||
| #ifndef META_INLINE_VAR | |||||
| #if META_CXX_INLINE_VARIABLES | |||||
| #define META_INLINE_VAR inline | |||||
| #else | |||||
| #define META_INLINE_VAR | |||||
| #endif | |||||
| #endif | |||||
| #ifndef META_CXX_INTEGER_SEQUENCE | |||||
| #ifdef __cpp_lib_integer_sequence | |||||
| #define META_CXX_INTEGER_SEQUENCE __cpp_lib_integer_sequence | |||||
| #else | |||||
| #define META_CXX_INTEGER_SEQUENCE (META_CXX_VER >= META_CXX_STD_14) | |||||
| #endif | |||||
| #endif | |||||
| #ifndef META_HAS_MAKE_INTEGER_SEQ | |||||
| #ifdef __has_builtin | |||||
| #if __has_builtin(__make_integer_seq) | |||||
| #define META_HAS_MAKE_INTEGER_SEQ 1 | |||||
| #endif | |||||
| #endif | |||||
| #endif | |||||
| #ifndef META_HAS_MAKE_INTEGER_SEQ | |||||
| #define META_HAS_MAKE_INTEGER_SEQ 0 | |||||
| #endif | |||||
| #ifndef META_HAS_TYPE_PACK_ELEMENT | |||||
| #ifdef __has_builtin | |||||
| #if __has_builtin(__type_pack_element) | |||||
| #define META_HAS_TYPE_PACK_ELEMENT 1 | |||||
| #endif | |||||
| #endif | |||||
| #endif | |||||
| #ifndef META_HAS_TYPE_PACK_ELEMENT | |||||
| #define META_HAS_TYPE_PACK_ELEMENT 0 | |||||
| #endif | |||||
| #if !defined(META_DEPRECATED) && !defined(META_DISABLE_DEPRECATED_WARNINGS) | |||||
| #if defined(__cpp_attribute_deprecated) || META_CXX_VER >= META_CXX_STD_14 | |||||
| #define META_DEPRECATED(...) [[deprecated(__VA_ARGS__)]] | |||||
| #elif defined(__clang__) || defined(__GNUC__) | |||||
| #define META_DEPRECATED(...) __attribute__((deprecated(__VA_ARGS__))) | |||||
| #endif | |||||
| #endif | |||||
| #ifndef META_DEPRECATED | |||||
| #define META_DEPRECATED(...) | |||||
| #endif | |||||
| #ifndef META_CXX_FOLD_EXPRESSIONS | |||||
| #ifdef __cpp_fold_expressions | |||||
| #define META_CXX_FOLD_EXPRESSIONS __cpp_fold_expressions | |||||
| #else | |||||
| #define META_CXX_FOLD_EXPRESSIONS (META_CXX_VER >= META_CXX_STD_17) | |||||
| #endif | |||||
| #endif | |||||
| #if META_CXX_FOLD_EXPRESSIONS | |||||
| #if !META_CXX_VARIABLE_TEMPLATES | |||||
| #error Fold expressions, but no variable templates? | |||||
| #endif | |||||
| #endif | |||||
| #if defined(__cpp_concepts) && __cpp_concepts > 0 | |||||
| #if !META_CXX_VARIABLE_TEMPLATES | |||||
| #error Concepts, but no variable templates? | |||||
| #endif | |||||
| #if __cpp_concepts <= 201507L | |||||
| #define META_CONCEPT concept bool | |||||
| // TS concepts subsumption barrier for atomic expressions | |||||
| #define META_CONCEPT_BARRIER(...) ::meta::detail::barrier<__VA_ARGS__> | |||||
| #else | |||||
| #define META_CONCEPT concept | |||||
| #define META_CONCEPT_BARRIER(...) __VA_ARGS__ | |||||
| #endif | |||||
| #define META_TYPE_CONSTRAINT(...) __VA_ARGS__ | |||||
| #else | |||||
| #define META_TYPE_CONSTRAINT(...) typename | |||||
| #endif | |||||
| #if (defined(__cpp_lib_type_trait_variable_templates) && \ | |||||
| __cpp_lib_type_trait_variable_templates > 0) | |||||
| #define META_CXX_TRAIT_VARIABLE_TEMPLATES 1 | |||||
| #else | |||||
| #define META_CXX_TRAIT_VARIABLE_TEMPLATES 0 | |||||
| #endif | |||||
| #if defined(__clang__) | |||||
| #define META_IS_SAME(...) __is_same(__VA_ARGS__) | |||||
| #elif defined(__GNUC__) && __GNUC__ >= 6 | |||||
| #define META_IS_SAME(...) __is_same_as(__VA_ARGS__) | |||||
| #elif META_CXX_TRAIT_VARIABLE_TEMPLATES | |||||
| #define META_IS_SAME(...) std::is_same_v<__VA_ARGS__> | |||||
| #else | |||||
| #define META_IS_SAME(...) std::is_same<__VA_ARGS__>::value | |||||
| #endif | |||||
| #if defined(__GNUC__) || defined(_MSC_VER) | |||||
| #define META_IS_BASE_OF(...) __is_base_of(__VA_ARGS__) | |||||
| #elif META_CXX_TRAIT_VARIABLE_TEMPLATES | |||||
| #define META_IS_BASE_OF(...) std::is_base_of_v<__VA_ARGS__> | |||||
| #else | |||||
| #define META_IS_BASE_OF(...) std::is_base_of<__VA_ARGS__>::value | |||||
| #endif | |||||
| #if defined(__clang__) || defined(_MSC_VER) || \ | |||||
| (defined(__GNUC__) && __GNUC__ >= 8) | |||||
| #define META_IS_CONSTRUCTIBLE(...) __is_constructible(__VA_ARGS__) | |||||
| #elif META_CXX_TRAIT_VARIABLE_TEMPLATES | |||||
| #define META_IS_CONSTRUCTIBLE(...) std::is_constructible_v<__VA_ARGS__> | |||||
| #else | |||||
| #define META_IS_CONSTRUCTIBLE(...) std::is_constructible<__VA_ARGS__>::value | |||||
| #endif | |||||
| /// \cond | |||||
| // Non-portable forward declarations of standard containers | |||||
| #ifdef _LIBCPP_VERSION | |||||
| #define META_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD | |||||
| #define META_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD | |||||
| #elif defined(_MSVC_STL_VERSION) | |||||
| #define META_BEGIN_NAMESPACE_STD _STD_BEGIN | |||||
| #define META_END_NAMESPACE_STD _STD_END | |||||
| #else | |||||
| #define META_BEGIN_NAMESPACE_STD namespace std { | |||||
| #define META_END_NAMESPACE_STD } | |||||
| #endif | |||||
| #if defined(__GLIBCXX__) | |||||
| #define META_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION | |||||
| #define META_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION | |||||
| #define META_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_BEGIN_NAMESPACE_CONTAINER | |||||
| #define META_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER | |||||
| #else | |||||
| #define META_BEGIN_NAMESPACE_VERSION | |||||
| #define META_END_NAMESPACE_VERSION | |||||
| #define META_BEGIN_NAMESPACE_CONTAINER | |||||
| #define META_END_NAMESPACE_CONTAINER | |||||
| #endif | |||||
| #if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 4000 | |||||
| #define META_TEMPLATE_VIS _LIBCPP_TEMPLATE_VIS | |||||
| #elif defined(_LIBCPP_VERSION) | |||||
| #define META_TEMPLATE_VIS _LIBCPP_TYPE_VIS_ONLY | |||||
| #else | |||||
| #define META_TEMPLATE_VIS | |||||
| #endif | |||||
| /// \endcond | |||||
| namespace meta | |||||
| { | |||||
| #if META_CXX_INTEGER_SEQUENCE | |||||
| using std::integer_sequence; | |||||
| #else | |||||
| template <typename T, T...> | |||||
| struct integer_sequence; | |||||
| #endif | |||||
| template <typename... Ts> | |||||
| struct list; | |||||
| template <typename T> | |||||
| struct id; | |||||
| template <template <typename...> class> | |||||
| struct quote; | |||||
| template <typename T, template <T...> class F> | |||||
| struct quote_i; | |||||
| template <template <typename...> class C, typename... Ts> | |||||
| struct defer; | |||||
| template <typename T, template <T...> class C, T... Is> | |||||
| struct defer_i; | |||||
| #if META_CXX_VARIABLE_TEMPLATES || defined(META_DOXYGEN_INVOKED) | |||||
| /// is_v | |||||
| /// Test whether a type \p T is an instantiation of class | |||||
| /// template \p C. | |||||
| /// \ingroup trait | |||||
| template <typename, template <typename...> class> | |||||
| META_INLINE_VAR constexpr bool is_v = false; | |||||
| template <typename... Ts, template <typename...> class C> | |||||
| META_INLINE_VAR constexpr bool is_v<C<Ts...>, C> = true; | |||||
| #endif | |||||
| #ifdef META_CONCEPT | |||||
| namespace detail | |||||
| { | |||||
| template <bool B> | |||||
| META_INLINE_VAR constexpr bool barrier = B; | |||||
| template <class T, T> struct require_constant; // not defined | |||||
| } | |||||
| template <typename...> | |||||
| META_CONCEPT is_true = META_CONCEPT_BARRIER(true); | |||||
| template <typename T, typename U> | |||||
| META_CONCEPT same_as = | |||||
| META_CONCEPT_BARRIER(META_IS_SAME(T, U)); | |||||
| template <template <typename...> class C, typename... Ts> | |||||
| META_CONCEPT valid = requires | |||||
| { | |||||
| typename C<Ts...>; | |||||
| }; | |||||
| template <typename T, template <T...> class C, T... Is> | |||||
| META_CONCEPT valid_i = requires | |||||
| { | |||||
| typename C<Is...>; | |||||
| }; | |||||
| template <typename T> | |||||
| META_CONCEPT trait = requires | |||||
| { | |||||
| typename T::type; | |||||
| }; | |||||
| template <typename T> | |||||
| META_CONCEPT invocable = requires | |||||
| { | |||||
| typename quote<T::template invoke>; | |||||
| }; | |||||
| template <typename T> | |||||
| META_CONCEPT list_like = is_v<T, list>; | |||||
| // clang-format off | |||||
| template <typename T> | |||||
| META_CONCEPT integral = requires | |||||
| { | |||||
| typename T::type; | |||||
| typename T::value_type; | |||||
| typename T::type::value_type; | |||||
| } | |||||
| && same_as<typename T::value_type, typename T::type::value_type> | |||||
| #if META_CXX_TRAIT_VARIABLE_TEMPLATES | |||||
| && std::is_integral_v<typename T::value_type> | |||||
| #else | |||||
| && std::is_integral<typename T::value_type>::value | |||||
| #endif | |||||
| && requires | |||||
| { | |||||
| // { T::value } -> same_as<const typename T::value_type&>; | |||||
| T::value; | |||||
| requires same_as<decltype(T::value), const typename T::value_type>; | |||||
| typename detail::require_constant<decltype(T::value), T::value>; | |||||
| // { T::type::value } -> same_as<const typename T::value_type&>; | |||||
| T::type::value; | |||||
| requires same_as<decltype(T::type::value), const typename T::value_type>; | |||||
| typename detail::require_constant<decltype(T::type::value), T::type::value>; | |||||
| requires T::value == T::type::value; | |||||
| // { T{}() } -> same_as<typename T::value_type>; | |||||
| T{}(); | |||||
| requires same_as<decltype(T{}()), typename T::value_type>; | |||||
| typename detail::require_constant<decltype(T{}()), T{}()>; | |||||
| requires T{}() == T::value; | |||||
| { T{} } -> typename T::value_type; | |||||
| }; | |||||
| // clang-format on | |||||
| #endif // META_CONCEPT | |||||
| namespace extension | |||||
| { | |||||
| template <META_TYPE_CONSTRAINT(invocable) F, typename L> | |||||
| struct apply; | |||||
| } | |||||
| } // namespace meta | |||||
| #ifdef __clang__ | |||||
| #pragma GCC diagnostic pop | |||||
| #endif | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Gonzalo Brito Gadeschi 2017. | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| module concepts { | |||||
| umbrella "concepts" | |||||
| export * | |||||
| } | |||||
| module meta { | |||||
| umbrella "meta" | |||||
| export * | |||||
| } | |||||
| module range_v3 { | |||||
| umbrella "range" | |||||
| export * | |||||
| exclude header "range/v3/algorithm/tagspec.hpp" | |||||
| exclude header "range/v3/at.hpp" | |||||
| exclude header "range/v3/back.hpp" | |||||
| exclude header "range/v3/begin_end.hpp" | |||||
| exclude header "range/v3/data.hpp" | |||||
| exclude header "range/v3/distance.hpp" | |||||
| exclude header "range/v3/empty.hpp" | |||||
| exclude header "range/v3/front.hpp" | |||||
| exclude header "range/v3/getlines.hpp" | |||||
| exclude header "range/v3/index.hpp" | |||||
| exclude header "range/v3/istream_range.hpp" | |||||
| exclude header "range/v3/iterator_range.hpp" | |||||
| exclude header "range/v3/range_access.hpp" | |||||
| exclude header "range/v3/range_concepts.hpp" | |||||
| exclude header "range/v3/range_traits.hpp" | |||||
| exclude header "range/v3/size.hpp" | |||||
| exclude header "range/v3/span.hpp" | |||||
| exclude header "range/v3/to_container.hpp" | |||||
| exclude header "range/v3/utility/associated_types.hpp" | |||||
| exclude header "range/v3/utility/basic_iterator.hpp" | |||||
| exclude header "range/v3/utility/common_iterator.hpp" | |||||
| exclude header "range/v3/utility/concepts.hpp" | |||||
| exclude header "range/v3/utility/counted_iterator.hpp" | |||||
| exclude header "range/v3/utility/dangling.hpp" | |||||
| exclude header "range/v3/utility/functional.hpp" | |||||
| exclude header "range/v3/utility/infinity.hpp" | |||||
| exclude header "range/v3/utility/invoke.hpp" | |||||
| exclude header "range/v3/utility/iterator_concepts.hpp" | |||||
| exclude header "range/v3/utility/iterator_traits.hpp" | |||||
| exclude header "range/v3/utility/iterator.hpp" | |||||
| exclude header "range/v3/utility/nullptr_v.hpp" | |||||
| exclude header "range/v3/utility/unreachable.hpp" | |||||
| exclude header "range/v3/view_adaptor.hpp" | |||||
| exclude header "range/v3/view_facade.hpp" | |||||
| exclude header "range/v3/view_interface.hpp" | |||||
| exclude header "range/v3/view/bounded.hpp" | |||||
| } |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_HPP | |||||
| #define RANGES_V3_ACTION_HPP | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/adjacent_remove_if.hpp> | |||||
| #include <range/v3/action/concepts.hpp> | |||||
| #include <range/v3/action/drop.hpp> | |||||
| #include <range/v3/action/drop_while.hpp> | |||||
| #include <range/v3/action/erase.hpp> | |||||
| #include <range/v3/action/insert.hpp> | |||||
| #include <range/v3/action/join.hpp> | |||||
| #include <range/v3/action/push_back.hpp> | |||||
| #include <range/v3/action/push_front.hpp> | |||||
| #include <range/v3/action/remove_if.hpp> | |||||
| #include <range/v3/action/reverse.hpp> | |||||
| #include <range/v3/action/shuffle.hpp> | |||||
| #include <range/v3/action/slice.hpp> | |||||
| #include <range/v3/action/sort.hpp> | |||||
| #include <range/v3/action/split.hpp> | |||||
| #include <range/v3/action/split_when.hpp> | |||||
| #include <range/v3/action/stable_sort.hpp> | |||||
| #include <range/v3/action/stride.hpp> | |||||
| #include <range/v3/action/take.hpp> | |||||
| #include <range/v3/action/take_while.hpp> | |||||
| #include <range/v3/action/transform.hpp> | |||||
| #include <range/v3/action/unique.hpp> | |||||
| #include <range/v3/action/unstable_remove_if.hpp> | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_CONTAINER_ACTION_HPP | |||||
| #define RANGES_V3_CONTAINER_ACTION_HPP | |||||
| #include <type_traits> | |||||
| #include <meta/meta.hpp> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/concepts.hpp> | |||||
| #include <range/v3/functional/arithmetic.hpp> | |||||
| #include <range/v3/functional/concepts.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| #include <range/v3/view/ref.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct action_access | |||||
| { | |||||
| template<typename Action> | |||||
| struct impl | |||||
| { | |||||
| // clang-format off | |||||
| template<typename... Ts, typename A = Action> | |||||
| static constexpr auto CPP_auto_fun(bind)(Ts &&... ts) | |||||
| ( | |||||
| return A::bind(static_cast<Ts &&>(ts)...) | |||||
| ) | |||||
| // clang-format on | |||||
| }; | |||||
| }; | |||||
| struct make_action_fn | |||||
| { | |||||
| template<typename Fun> | |||||
| constexpr action<Fun> operator()(Fun fun) const | |||||
| { | |||||
| return action<Fun>{detail::move(fun)}; | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates make_action_fn | |||||
| RANGES_INLINE_VARIABLE(make_action_fn, make_action) | |||||
| template<typename Action> | |||||
| struct action : pipeable_base | |||||
| { | |||||
| private: | |||||
| Action action_; | |||||
| friend pipeable_access; | |||||
| // Piping requires things are passed by value. | |||||
| template<typename Rng, typename Act> | |||||
| static auto pipe(Rng && rng, Act && act) | |||||
| -> CPP_ret(invoke_result_t<Action &, Rng>)( // | |||||
| requires range<Rng> && invocable<Action &, Rng> && | |||||
| (!std::is_reference<Rng>::value)) | |||||
| { | |||||
| return invoke(act.action_, detail::move(rng)); | |||||
| } | |||||
| public: | |||||
| action() = default; | |||||
| constexpr explicit action(Action a) noexcept( | |||||
| std::is_nothrow_move_constructible<Action>::value) | |||||
| : action_(detail::move(a)) | |||||
| {} | |||||
| // Calling directly requires things are passed by reference. | |||||
| template<typename Rng, typename... Rest> | |||||
| auto operator()(Rng & rng, Rest &&... rest) const | |||||
| -> CPP_ret(invoke_result_t<Action const &, Rng &, Rest...>)( // | |||||
| requires range<Rng> && invocable<Action const &, Rng &, Rest...>) | |||||
| { | |||||
| return invoke(action_, rng, static_cast<Rest &&>(rest)...); | |||||
| } | |||||
| // Currying overload. | |||||
| // clang-format off | |||||
| template<typename T, typename... Rest, typename A = Action> | |||||
| auto CPP_auto_fun(operator())(T &&t, Rest &&... rest)(const) | |||||
| ( | |||||
| return make_action( | |||||
| action_access::impl<A>::bind(action_, | |||||
| static_cast<T &&>(t), | |||||
| static_cast<Rest &&>(rest)...)) | |||||
| ) | |||||
| // clang-format on | |||||
| }; | |||||
| template<typename Rng, typename Action> | |||||
| auto operator|=(Rng & rng, Action && action) -> CPP_ret(Rng &)( // | |||||
| requires is_pipeable<Action>::value && range<Rng &> && | |||||
| invocable<bitwise_or, ref_view<Rng>, Action &> && same_as< | |||||
| ref_view<Rng>, invoke_result_t<bitwise_or, ref_view<Rng>, Action &>>) | |||||
| { | |||||
| views::ref(rng) | action; | |||||
| return rng; | |||||
| } | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler | |||||
| // Copyright Christopher Di Bella | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_ADJACENT_REMOVE_IF_HPP | |||||
| #define RANGES_V3_ACTION_ADJACENT_REMOVE_IF_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/erase.hpp> | |||||
| #include <range/v3/algorithm/adjacent_remove_if.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct adjacent_remove_if_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename Pred, typename Proj = identity> | |||||
| static auto CPP_fun(bind)(adjacent_remove_if_fn adjacent_remove_if, Pred pred, | |||||
| Proj proj = {})( // | |||||
| requires(!range<Pred>)) | |||||
| { | |||||
| return bind_back(adjacent_remove_if, std::move(pred), std::move(proj)); | |||||
| } | |||||
| public: | |||||
| template<typename Rng, typename Pred, typename Proj = identity> | |||||
| auto operator()(Rng && rng, Pred pred, Proj proj = {}) const | |||||
| -> CPP_ret(Rng)( // | |||||
| requires forward_range<Rng> && | |||||
| erasable_range<Rng, iterator_t<Rng>, sentinel_t<Rng>> && | |||||
| indirect_relation<Pred, projected<iterator_t<Rng>, Proj>> && | |||||
| permutable<iterator_t<Rng>>) | |||||
| { | |||||
| auto i = adjacent_remove_if(rng, std::move(pred), std::move(proj)); | |||||
| erase(rng, std::move(i), end(rng)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \sa action | |||||
| /// \sa with_braced_init_args | |||||
| RANGES_INLINE_VARIABLE(action<adjacent_remove_if_fn>, adjacent_remove_if) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // RANGES_V3_ACTION_ADJACENT_REMOVE_IF_HPP |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_CONCEPTS_HPP | |||||
| #define RANGES_V3_ACTION_CONCEPTS_HPP | |||||
| #include <utility> | |||||
| #include <meta/meta.hpp> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \cond | |||||
| namespace detail | |||||
| { | |||||
| template<typename T> | |||||
| struct movable_input_iterator | |||||
| { | |||||
| using iterator_category = std::input_iterator_tag; | |||||
| using value_type = T; | |||||
| using difference_type = std::ptrdiff_t; | |||||
| using pointer = T *; | |||||
| using reference = T &&; | |||||
| movable_input_iterator() = default; | |||||
| movable_input_iterator & operator++(); | |||||
| movable_input_iterator operator++(int); | |||||
| bool operator==(movable_input_iterator const &) const; | |||||
| bool operator!=(movable_input_iterator const &) const; | |||||
| T && operator*() const; | |||||
| }; | |||||
| } // namespace detail | |||||
| /// \endcond | |||||
| /// \addtogroup group-range | |||||
| /// @{ | |||||
| // std::array is a semi_container, native arrays are not. | |||||
| // clang-format off | |||||
| CPP_def | |||||
| ( | |||||
| template(typename T) | |||||
| concept semi_container, | |||||
| forward_range<T> && default_constructible<uncvref_t<T>> && | |||||
| movable<uncvref_t<T>> && | |||||
| !view_<T> | |||||
| ); | |||||
| // std::vector is a container, std::array is not | |||||
| CPP_def | |||||
| ( | |||||
| template(typename T) | |||||
| concept container, | |||||
| semi_container<T> && | |||||
| constructible_from< | |||||
| uncvref_t<T>, | |||||
| detail::movable_input_iterator<range_value_t<T>>, | |||||
| detail::movable_input_iterator<range_value_t<T>>> | |||||
| ); | |||||
| CPP_def | |||||
| ( | |||||
| template(typename C) | |||||
| concept reservable, | |||||
| requires (C &c, C const &cc, range_size_t<C> s) | |||||
| ( | |||||
| c.reserve(s), | |||||
| cc.capacity(), | |||||
| cc.max_size(), | |||||
| concepts::requires_<same_as<decltype(cc.capacity()), range_size_t<C>>>, | |||||
| concepts::requires_<same_as<decltype(cc.max_size()), range_size_t<C>>> | |||||
| ) && | |||||
| container<C> && sized_range<C> | |||||
| ); | |||||
| CPP_def | |||||
| ( | |||||
| template(typename C, typename I) | |||||
| concept reservable_with_assign, | |||||
| requires (C &c, I i) | |||||
| ( | |||||
| c.assign(i, i) | |||||
| ) && | |||||
| reservable<C> && input_iterator<I> | |||||
| ); | |||||
| CPP_def | |||||
| ( | |||||
| template(typename C) | |||||
| concept random_access_reservable, | |||||
| reservable<C> && random_access_range<C> | |||||
| ); | |||||
| // clang-format on | |||||
| /// \cond | |||||
| namespace detail | |||||
| { | |||||
| template<typename T> | |||||
| auto is_lvalue_container_like(T &) noexcept -> CPP_ret(std::true_type)( // | |||||
| requires container<T>) | |||||
| { | |||||
| return {}; | |||||
| } | |||||
| template<typename T> | |||||
| auto is_lvalue_container_like(reference_wrapper<T>) noexcept | |||||
| -> CPP_ret(meta::not_<std::is_rvalue_reference<T>>)( // | |||||
| requires container<T>) | |||||
| { | |||||
| return {}; | |||||
| } | |||||
| template<typename T> | |||||
| auto is_lvalue_container_like(std::reference_wrapper<T>) noexcept | |||||
| -> CPP_ret(std::true_type)( // | |||||
| requires container<T>) | |||||
| { | |||||
| return {}; | |||||
| } | |||||
| template<typename T> | |||||
| auto is_lvalue_container_like(ref_view<T>) noexcept -> CPP_ret(std::true_type)( // | |||||
| requires container<T>) | |||||
| { | |||||
| return {}; | |||||
| } | |||||
| template<typename T> | |||||
| using is_lvalue_container_like_t = | |||||
| decltype(detail::is_lvalue_container_like(std::declval<T>())); | |||||
| } // namespace detail | |||||
| /// \endcond | |||||
| // clang-format off | |||||
| CPP_def | |||||
| ( | |||||
| template(typename T) | |||||
| concept lvalue_container_like, | |||||
| implicitly_convertible_to<detail::is_lvalue_container_like_t<T>, | |||||
| std::true_type> && | |||||
| forward_range<T> | |||||
| ); | |||||
| // clang-format on | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_DROP_HPP | |||||
| #define RANGES_V3_ACTION_DROP_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/erase.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct drop_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename Int> | |||||
| static auto CPP_fun(bind)(drop_fn drop, Int n)( // | |||||
| requires integral<Int>) | |||||
| { | |||||
| return bind_back(drop, n); | |||||
| } | |||||
| public: | |||||
| template<typename Rng> | |||||
| auto operator()(Rng && rng, range_difference_t<Rng> n) const | |||||
| -> CPP_ret(Rng)( // | |||||
| requires forward_range<Rng> && | |||||
| erasable_range<Rng &, iterator_t<Rng>, iterator_t<Rng>>) | |||||
| { | |||||
| RANGES_EXPECT(n >= 0); | |||||
| ranges::actions::erase( | |||||
| rng, begin(rng), ranges::next(begin(rng), n, end(rng))); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates drop_fn | |||||
| /// \sa action | |||||
| RANGES_INLINE_VARIABLE(action<drop_fn>, drop) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_DROP_WHILE_HPP | |||||
| #define RANGES_V3_ACTION_DROP_WHILE_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/erase.hpp> | |||||
| #include <range/v3/algorithm/find_if_not.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct drop_while_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename Fun> | |||||
| static auto CPP_fun(bind)(drop_while_fn drop_while, Fun fun)( // | |||||
| requires(!range<Fun>)) | |||||
| { | |||||
| return bind_back(drop_while, std::move(fun)); | |||||
| } | |||||
| public: | |||||
| template<typename Rng, typename Fun> | |||||
| auto operator()(Rng && rng, Fun fun) const -> CPP_ret(Rng)( // | |||||
| requires forward_range<Rng> && | |||||
| indirect_unary_predicate<Fun, iterator_t<Rng>> && | |||||
| erasable_range<Rng &, iterator_t<Rng>, iterator_t<Rng>>) | |||||
| { | |||||
| ranges::actions::erase( | |||||
| rng, begin(rng), find_if_not(begin(rng), end(rng), std::move(fun))); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates drop_while_fn | |||||
| /// \sa action | |||||
| RANGES_INLINE_VARIABLE(action<drop_while_fn>, drop_while) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_ERASE_HPP | |||||
| #define RANGES_V3_ACTION_ERASE_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/insert.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \cond | |||||
| namespace adl_erase_detail | |||||
| { | |||||
| template<typename Cont, typename I, typename S> | |||||
| auto erase(Cont && cont, I first, S last) // | |||||
| -> CPP_ret(decltype(unwrap_reference(cont).erase(first, last)))( // | |||||
| requires lvalue_container_like<Cont> && forward_iterator<I> && | |||||
| sentinel_for<S, I>) | |||||
| { | |||||
| return unwrap_reference(cont).erase(first, last); | |||||
| } | |||||
| struct erase_fn | |||||
| { | |||||
| template<typename Rng, typename I, typename S> | |||||
| auto operator()(Rng && rng, I first, S last) const | |||||
| -> CPP_ret(decltype(erase((Rng &&) rng, first, last)))( // | |||||
| requires range<Rng> && forward_iterator<I> && sentinel_for<S, I>) | |||||
| { | |||||
| return erase(static_cast<Rng &&>(rng), first, last); | |||||
| } | |||||
| }; | |||||
| } // namespace adl_erase_detail | |||||
| /// \endcond | |||||
| /// \ingroup group-actions | |||||
| RANGES_INLINE_VARIABLE(adl_erase_detail::erase_fn, erase) | |||||
| namespace actions | |||||
| { | |||||
| using ranges::erase; | |||||
| } | |||||
| /// \addtogroup group-range | |||||
| /// @{ | |||||
| // clang-format off | |||||
| CPP_def | |||||
| ( | |||||
| template(typename Rng, typename I, typename S) | |||||
| concept erasable_range, | |||||
| requires (Rng &&rng, I first, S last) | |||||
| ( | |||||
| ranges::erase(static_cast<Rng &&>(rng), first, last) | |||||
| ) && | |||||
| range<Rng> | |||||
| ); | |||||
| // clang-format on | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_INSERT_HPP | |||||
| #define RANGES_V3_ACTION_INSERT_HPP | |||||
| #include <initializer_list> | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/concepts.hpp> | |||||
| #include <range/v3/algorithm/max.hpp> | |||||
| #include <range/v3/iterator/common_iterator.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \cond | |||||
| namespace adl_insert_detail | |||||
| { | |||||
| template<typename Cont, typename... Args> | |||||
| using insert_result_t = decltype( | |||||
| unwrap_reference(std::declval<Cont>()).insert(std::declval<Args>()...)); | |||||
| template<typename Cont, typename T> | |||||
| auto insert(Cont && cont, T && t) -> CPP_ret(insert_result_t<Cont &, T>)( // | |||||
| requires lvalue_container_like<Cont> && | |||||
| (!range<T> && constructible_from<range_value_t<Cont>, T>)) | |||||
| { | |||||
| return unwrap_reference(cont).insert(static_cast<T &&>(t)); | |||||
| } | |||||
| template<typename Cont, typename I, typename S> | |||||
| auto insert(Cont && cont, I i, S j) | |||||
| -> CPP_ret(insert_result_t<Cont &, detail::cpp17_iterator_t<I, S>, | |||||
| detail::cpp17_iterator_t<I, S>>)( // | |||||
| requires lvalue_container_like<Cont> && sentinel_for<S, I> && (!range<S>)) | |||||
| { | |||||
| return unwrap_reference(cont).insert(detail::cpp17_iterator_t<I, S>{i}, | |||||
| detail::cpp17_iterator_t<I, S>{j}); | |||||
| } | |||||
| template<typename Cont, typename Rng> | |||||
| auto insert(Cont && cont, Rng && rng) | |||||
| -> CPP_ret(insert_result_t<Cont &, detail::range_cpp17_iterator_t<Rng>, | |||||
| detail::range_cpp17_iterator_t<Rng>>)( // | |||||
| requires lvalue_container_like<Cont> && range<Rng>) | |||||
| { | |||||
| return unwrap_reference(cont).insert( | |||||
| detail::range_cpp17_iterator_t<Rng>{ranges::begin(rng)}, | |||||
| detail::range_cpp17_iterator_t<Rng>{ranges::end(rng)}); | |||||
| } | |||||
| template<typename Cont, typename I, typename T> | |||||
| auto insert(Cont && cont, I p, T && t) | |||||
| -> CPP_ret(insert_result_t<Cont &, I, T>)( // | |||||
| requires lvalue_container_like<Cont> && input_iterator<I> && | |||||
| (!range<T> && constructible_from<range_value_t<Cont>, T>)) | |||||
| { | |||||
| return unwrap_reference(cont).insert(p, static_cast<T &&>(t)); | |||||
| } | |||||
| template<typename Cont, typename I, typename N, typename T> | |||||
| auto insert(Cont && cont, I p, N n, T && t) | |||||
| -> CPP_ret(insert_result_t<Cont &, I, N, T>)( // | |||||
| requires lvalue_container_like<Cont> && input_iterator<I> && | |||||
| integral<N> && constructible_from<range_value_t<Cont>, T>) | |||||
| { | |||||
| return unwrap_reference(cont).insert(p, n, static_cast<T &&>(t)); | |||||
| } | |||||
| /// \cond | |||||
| namespace detail | |||||
| { | |||||
| using ranges::detail::cpp17_iterator_t; | |||||
| using ranges::detail::range_cpp17_iterator_t; | |||||
| template<typename Cont, typename P> | |||||
| auto insert_reserve_helper(Cont & cont, P const p, | |||||
| range_size_t<Cont> const delta) | |||||
| -> CPP_ret(iterator_t<Cont>)( // | |||||
| requires container<Cont> && input_iterator<P> && | |||||
| random_access_reservable<Cont>) | |||||
| { | |||||
| auto const old_size = ranges::size(cont); | |||||
| auto const max_size = cont.max_size(); | |||||
| RANGES_EXPECT(delta <= max_size - old_size); | |||||
| auto const new_size = old_size + delta; | |||||
| auto const old_capacity = cont.capacity(); | |||||
| auto const index = p - ranges::begin(cont); | |||||
| if(old_capacity < new_size) | |||||
| { | |||||
| auto const new_capacity = | |||||
| (old_capacity <= max_size / 3 * 2) | |||||
| ? ranges::max(old_capacity + old_capacity / 2, new_size) | |||||
| : max_size; | |||||
| cont.reserve(new_capacity); | |||||
| } | |||||
| return ranges::begin(cont) + index; | |||||
| } | |||||
| template<typename Cont, typename P, typename I, typename S> | |||||
| auto insert_impl(Cont && cont, P p, I i, S j, std::false_type) | |||||
| -> CPP_ret(decltype(unwrap_reference(cont).insert( | |||||
| p, cpp17_iterator_t<I, S>{i}, cpp17_iterator_t<I, S>{j})))( // | |||||
| requires sentinel_for<S, I> && (!range<S>)) | |||||
| { | |||||
| using C = cpp17_iterator_t<I, S>; | |||||
| return unwrap_reference(cont).insert(p, C{i}, C{j}); | |||||
| } | |||||
| template<typename Cont, typename P, typename I, typename S> | |||||
| auto insert_impl(Cont && cont_, P p, I i, S j, std::true_type) | |||||
| -> CPP_ret(decltype(unwrap_reference(cont_).insert( | |||||
| ranges::begin(unwrap_reference(cont_)), cpp17_iterator_t<I, S>{i}, | |||||
| cpp17_iterator_t<I, S>{j})))( // | |||||
| requires sized_sentinel_for<S, I> && random_access_reservable<Cont> && | |||||
| (!range<S>)) | |||||
| { | |||||
| using C = cpp17_iterator_t<I, S>; | |||||
| auto && cont = unwrap_reference(cont_); | |||||
| auto const delta = static_cast<range_size_t<Cont>>(j - i); | |||||
| auto pos = insert_reserve_helper(cont, std::move(p), delta); | |||||
| return cont.insert(pos, C{std::move(i)}, C{std::move(j)}); | |||||
| } | |||||
| template<typename Cont, typename I, typename Rng> | |||||
| auto insert_impl(Cont && cont, I p, Rng && rng, std::false_type) | |||||
| -> CPP_ret(decltype(unwrap_reference(cont).insert( | |||||
| p, range_cpp17_iterator_t<Rng>{ranges::begin(rng)}, | |||||
| range_cpp17_iterator_t<Rng>{ranges::end(rng)})))( // | |||||
| requires range<Rng>) | |||||
| { | |||||
| using C = range_cpp17_iterator_t<Rng>; | |||||
| return unwrap_reference(cont).insert( | |||||
| p, C{ranges::begin(rng)}, C{ranges::end(rng)}); | |||||
| } | |||||
| template<typename Cont, typename I, typename Rng> | |||||
| auto insert_impl(Cont && cont_, I p, Rng && rng, std::true_type) | |||||
| -> CPP_ret(decltype(unwrap_reference(cont_).insert( | |||||
| begin(unwrap_reference(cont_)), | |||||
| range_cpp17_iterator_t<Rng>{ranges::begin(rng)}, | |||||
| range_cpp17_iterator_t<Rng>{ranges::end(rng)})))( // | |||||
| requires random_access_reservable<Cont> && sized_range<Rng>) | |||||
| { | |||||
| using C = range_cpp17_iterator_t<Rng>; | |||||
| auto && cont = unwrap_reference(cont_); | |||||
| auto const delta = static_cast<range_size_t<Cont>>(ranges::size(rng)); | |||||
| auto pos = insert_reserve_helper(cont, std::move(p), delta); | |||||
| return cont.insert(pos, C{ranges::begin(rng)}, C{ranges::end(rng)}); | |||||
| } | |||||
| } // namespace detail | |||||
| /// \endcond | |||||
| template<typename Cont, typename P, typename I, typename S> | |||||
| auto insert(Cont && cont, P p, I i, S j) -> CPP_ret(decltype(detail::insert_impl( | |||||
| static_cast<Cont &&>(cont), std::move(p), std::move(i), std::move(j), | |||||
| meta::bool_<random_access_reservable<Cont> && | |||||
| sized_sentinel_for<S, I>>{})))( // | |||||
| requires lvalue_container_like<Cont> && input_iterator<P> && | |||||
| sentinel_for<S, I> && | |||||
| (!range<S>)) | |||||
| { | |||||
| return detail::insert_impl(static_cast<Cont &&>(cont), | |||||
| std::move(p), | |||||
| std::move(i), | |||||
| std::move(j), | |||||
| meta::bool_ < random_access_reservable<Cont> && | |||||
| sized_sentinel_for<S, I>> {}); | |||||
| } | |||||
| template<typename Cont, typename I, typename Rng> | |||||
| auto insert(Cont && cont, I p, Rng && rng) | |||||
| -> CPP_ret(decltype(detail::insert_impl( | |||||
| static_cast<Cont &&>(cont), std::move(p), static_cast<Rng &&>(rng), | |||||
| meta::bool_<random_access_reservable<Cont> && sized_range<Rng>>{})))( // | |||||
| requires lvalue_container_like<Cont> && input_iterator<I> && range<Rng>) | |||||
| { | |||||
| return detail::insert_impl(static_cast<Cont &&>(cont), | |||||
| std::move(p), | |||||
| static_cast<Rng &&>(rng), | |||||
| meta::bool_ < random_access_reservable<Cont> && | |||||
| sized_range<Rng>> {}); | |||||
| } | |||||
| struct insert_fn | |||||
| { | |||||
| template<typename Rng, typename... Args> | |||||
| using insert_result_t = | |||||
| decltype(insert(std::declval<Rng>(), std::declval<Args>()...)); | |||||
| template<typename Rng, typename T> | |||||
| auto operator()(Rng && rng, T && t) const | |||||
| -> CPP_ret(insert_result_t<Rng, T>)( // | |||||
| requires range<Rng> && | |||||
| (!range<T>)&&constructible_from<range_value_t<Rng>, T>) | |||||
| { | |||||
| return insert(static_cast<Rng &&>(rng), static_cast<T &&>(t)); | |||||
| } | |||||
| template<typename Rng, typename Rng2> | |||||
| auto operator()(Rng && rng, Rng2 && rng2) const | |||||
| -> CPP_ret(insert_result_t<Rng, Rng2>)( // | |||||
| requires range<Rng> && range<Rng2>) | |||||
| { | |||||
| static_assert(!is_infinite<Rng>::value, | |||||
| "Attempting to insert an infinite range into a container"); | |||||
| return insert(static_cast<Rng &&>(rng), static_cast<Rng2 &&>(rng2)); | |||||
| } | |||||
| template<typename Rng, typename T> | |||||
| auto operator()(Rng && rng, std::initializer_list<T> rng2) const | |||||
| -> CPP_ret(insert_result_t<Rng, std::initializer_list<T> &>)( // | |||||
| requires range<Rng>) | |||||
| { | |||||
| return insert(static_cast<Rng &&>(rng), rng2); | |||||
| } | |||||
| template<typename Rng, typename I, typename S> | |||||
| auto operator()(Rng && rng, I i, S j) const | |||||
| -> CPP_ret(insert_result_t<Rng, I, S>)( // | |||||
| requires range<Rng> && sentinel_for<S, I> && (!range<S>)) | |||||
| { | |||||
| return insert(static_cast<Rng &&>(rng), std::move(i), std::move(j)); | |||||
| } | |||||
| template<typename Rng, typename I, typename T> | |||||
| auto operator()(Rng && rng, I p, T && t) const | |||||
| -> CPP_ret(insert_result_t<Rng, I, T>)( // | |||||
| requires range<Rng> && input_iterator<I> && | |||||
| (!range<T>)&&constructible_from<range_value_t<Rng>, T>) | |||||
| { | |||||
| return insert( | |||||
| static_cast<Rng &&>(rng), std::move(p), static_cast<T &&>(t)); | |||||
| } | |||||
| template<typename Rng, typename I, typename Rng2> | |||||
| auto operator()(Rng && rng, I p, Rng2 && rng2) const | |||||
| -> CPP_ret(insert_result_t<Rng, I, Rng2>)( // | |||||
| requires range<Rng> && input_iterator<I> && range<Rng2>) | |||||
| { | |||||
| static_assert(!is_infinite<Rng>::value, | |||||
| "Attempting to insert an infinite range into a container"); | |||||
| return insert( | |||||
| static_cast<Rng &&>(rng), std::move(p), static_cast<Rng2 &&>(rng2)); | |||||
| } | |||||
| template<typename Rng, typename I, typename T> | |||||
| auto operator()(Rng && rng, I p, std::initializer_list<T> rng2) const | |||||
| -> CPP_ret(insert_result_t<Rng, I, std::initializer_list<T> &>)( // | |||||
| requires range<Rng> && input_iterator<I>) | |||||
| { | |||||
| return insert(static_cast<Rng &&>(rng), std::move(p), rng2); | |||||
| } | |||||
| template<typename Rng, typename I, typename N, typename T> | |||||
| auto operator()(Rng && rng, I p, N n, T && t) const | |||||
| -> CPP_ret(insert_result_t<Rng, I, N, T>)( // | |||||
| requires range<Rng> && input_iterator<I> && integral<N> && | |||||
| (!range<T>)&&constructible_from<range_value_t<Rng>, T>) | |||||
| { | |||||
| return insert( | |||||
| static_cast<Rng &&>(rng), std::move(p), n, static_cast<T &&>(t)); | |||||
| } | |||||
| template<typename Rng, typename P, typename I, typename S> | |||||
| auto operator()(Rng && rng, P p, I i, S j) const | |||||
| -> CPP_ret(insert_result_t<Rng, P, I, S>)( // | |||||
| requires range<Rng> && input_iterator<P> && sentinel_for<S, I> && | |||||
| (!range<S>)) | |||||
| { | |||||
| return insert( | |||||
| static_cast<Rng &&>(rng), std::move(p), std::move(i), std::move(j)); | |||||
| } | |||||
| }; | |||||
| } // namespace adl_insert_detail | |||||
| /// \endcond | |||||
| /// \ingroup group-actions | |||||
| RANGES_INLINE_VARIABLE(adl_insert_detail::insert_fn, insert) | |||||
| namespace actions | |||||
| { | |||||
| using ranges::insert; | |||||
| } | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_JOIN_HPP | |||||
| #define RANGES_V3_ACTION_JOIN_HPP | |||||
| #include <vector> | |||||
| #include <meta/meta.hpp> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/concepts.hpp> | |||||
| #include <range/v3/action/push_back.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| template<typename Rng> | |||||
| using join_action_value_t_ = | |||||
| meta::if_c<(bool)ranges::container<range_value_t<Rng>>, range_value_t<Rng>, | |||||
| std::vector<range_value_t<range_value_t<Rng>>>>; | |||||
| struct join_fn | |||||
| { | |||||
| public: | |||||
| template<typename Rng> | |||||
| auto operator()(Rng && rng) const -> CPP_ret(join_action_value_t_<Rng>)( // | |||||
| requires input_range<Rng> && input_range<range_value_t<Rng>> && | |||||
| semiregular<join_action_value_t_<Rng>>) | |||||
| { | |||||
| join_action_value_t_<Rng> ret; | |||||
| auto last = ranges::end(rng); | |||||
| for(auto it = begin(rng); it != last; ++it) | |||||
| push_back(ret, *it); | |||||
| return ret; | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates join_fn | |||||
| /// \sa action | |||||
| RANGES_INLINE_VARIABLE(action<join_fn>, join) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_PUSH_BACK_HPP | |||||
| #define RANGES_V3_ACTION_PUSH_BACK_HPP | |||||
| #include <utility> | |||||
| #include <meta/meta.hpp> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/insert.hpp> | |||||
| #include <range/v3/detail/with_braced_init_args.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \cond | |||||
| namespace adl_push_back_detail | |||||
| { | |||||
| template<typename Cont, typename T> | |||||
| using push_back_t = decltype(static_cast<void>( | |||||
| unwrap_reference(std::declval<Cont &>()).push_back(std::declval<T>()))); | |||||
| template<typename Cont, typename Rng> | |||||
| using insert_t = decltype(static_cast<void>( | |||||
| ranges::insert(std::declval<Cont &>(), std::declval<sentinel_t<Cont>>(), | |||||
| std::declval<Rng>()))); | |||||
| template<typename Cont, typename T> | |||||
| auto push_back(Cont && cont, T && t) -> CPP_ret(push_back_t<Cont, T>)( // | |||||
| requires lvalue_container_like<Cont> && | |||||
| (!range<T>)&&constructible_from<range_value_t<Cont>, T>) | |||||
| { | |||||
| unwrap_reference(cont).push_back(static_cast<T &&>(t)); | |||||
| } | |||||
| template<typename Cont, typename Rng> | |||||
| auto push_back(Cont && cont, Rng && rng) -> CPP_ret(insert_t<Cont, Rng>)( // | |||||
| requires lvalue_container_like<Cont> && range<Rng>) | |||||
| { | |||||
| ranges::insert(cont, end(cont), static_cast<Rng &&>(rng)); | |||||
| } | |||||
| /// \cond | |||||
| // clang-format off | |||||
| CPP_def | |||||
| ( | |||||
| template(typename Rng, typename T) | |||||
| concept can_push_back_, | |||||
| requires (Rng &&rng, T &&t) | |||||
| ( | |||||
| push_back(rng, (T &&) t) | |||||
| ) | |||||
| ); | |||||
| // clang-format on | |||||
| /// \endcond | |||||
| struct push_back_fn | |||||
| { | |||||
| private: | |||||
| friend actions::action_access; | |||||
| template<typename T> | |||||
| static auto bind(push_back_fn push_back, T && val) | |||||
| { | |||||
| return bind_back(push_back, static_cast<T &&>(val)); | |||||
| } | |||||
| #ifdef RANGES_WORKAROUND_MSVC_OLD_LAMBDA | |||||
| template<typename T, std::size_t N> | |||||
| struct lamduh | |||||
| { | |||||
| T (&val_)[N]; | |||||
| template<typename Rng> | |||||
| auto operator()(Rng && rng) const | |||||
| -> invoke_result_t<push_back_fn, Rng, T (&)[N]> | |||||
| { | |||||
| return push_back_fn{}(static_cast<Rng &&>(rng), val_); | |||||
| } | |||||
| }; | |||||
| template<typename T, std::size_t N> | |||||
| static lamduh<T, N> bind(push_back_fn, T (&val)[N]) | |||||
| { | |||||
| return {val}; | |||||
| } | |||||
| #else // ^^^ workaround / no workaround vvv | |||||
| template<typename T, std::size_t N> | |||||
| static auto bind(push_back_fn, T (&val)[N]) | |||||
| { | |||||
| return [&val](auto && rng) | |||||
| -> invoke_result_t<push_back_fn, decltype(rng), T(&)[N]> | |||||
| { | |||||
| return push_back_fn{}(static_cast<decltype(rng)>(rng), val); | |||||
| }; | |||||
| } | |||||
| #endif // RANGES_WORKAROUND_MSVC_OLD_LAMBDA | |||||
| public: | |||||
| template<typename Rng, typename T> | |||||
| auto operator()(Rng && rng, T && t) const -> CPP_ret(Rng)( // | |||||
| requires input_range<Rng> && can_push_back_<Rng, T> && | |||||
| (range<T> || constructible_from<range_value_t<Rng>, T>)) | |||||
| { | |||||
| push_back(rng, static_cast<T &&>(t)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| } // namespace adl_push_back_detail | |||||
| /// \endcond | |||||
| namespace actions | |||||
| { | |||||
| /// \ingroup group-actions | |||||
| RANGES_INLINE_VARIABLE( | |||||
| detail::with_braced_init_args<action<adl_push_back_detail::push_back_fn>>, | |||||
| push_back) | |||||
| } // namespace actions | |||||
| using actions::push_back; | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_PUSH_FRONT_HPP | |||||
| #define RANGES_V3_ACTION_PUSH_FRONT_HPP | |||||
| #include <utility> | |||||
| #include <meta/meta.hpp> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/insert.hpp> | |||||
| #include <range/v3/detail/with_braced_init_args.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \cond | |||||
| namespace adl_push_front_detail | |||||
| { | |||||
| template<typename Cont, typename T> | |||||
| using push_front_t = decltype(static_cast<void>( | |||||
| unwrap_reference(std::declval<Cont &>()).push_front(std::declval<T>()))); | |||||
| template<typename Cont, typename Rng> | |||||
| using insert_t = decltype(static_cast<void>( | |||||
| ranges::insert(std::declval<Cont &>(), std::declval<iterator_t<Cont>>(), | |||||
| std::declval<Rng>()))); | |||||
| template<typename Cont, typename T> | |||||
| auto push_front(Cont && cont, T && t) -> CPP_ret(push_front_t<Cont, T>)( // | |||||
| requires lvalue_container_like<Cont> && | |||||
| (!range<T>)&&constructible_from<range_value_t<Cont>, T>) | |||||
| { | |||||
| unwrap_reference(cont).push_front(static_cast<T &&>(t)); | |||||
| } | |||||
| template<typename Cont, typename Rng> | |||||
| auto push_front(Cont && cont, Rng && rng) -> CPP_ret(insert_t<Cont, Rng>)( // | |||||
| requires lvalue_container_like<Cont> && range<Rng>) | |||||
| { | |||||
| ranges::insert(cont, begin(cont), static_cast<Rng &&>(rng)); | |||||
| } | |||||
| // clang-format off | |||||
| CPP_def | |||||
| ( | |||||
| template(typename Rng, typename T) | |||||
| concept can_push_front_, | |||||
| requires (Rng &&rng, T &&t) | |||||
| ( | |||||
| push_front(rng, (T &&) t) | |||||
| ) | |||||
| ); | |||||
| // clang-format on | |||||
| struct push_front_fn | |||||
| { | |||||
| private: | |||||
| friend actions::action_access; | |||||
| template<typename T> | |||||
| static auto bind(push_front_fn push_front, T && val) | |||||
| { | |||||
| return bind_back(push_front, static_cast<T &&>(val)); | |||||
| } | |||||
| #ifdef RANGES_WORKAROUND_MSVC_OLD_LAMBDA | |||||
| template<typename T, std::size_t N> | |||||
| struct lamduh | |||||
| { | |||||
| T (&val_)[N]; | |||||
| template<typename Rng> | |||||
| auto operator()(Rng && rng) const | |||||
| -> invoke_result_t<push_front_fn, Rng, T (&)[N]> | |||||
| { | |||||
| return push_front_fn{}(static_cast<Rng &&>(rng), val_); | |||||
| } | |||||
| }; | |||||
| template<typename T, std::size_t N> | |||||
| static lamduh<T, N> bind(push_front_fn, T (&val)[N]) | |||||
| { | |||||
| return {val}; | |||||
| } | |||||
| #else // ^^^ workaround / no workaround vvv | |||||
| template<typename T, std::size_t N> | |||||
| static auto bind(push_front_fn, T (&val)[N]) | |||||
| { | |||||
| return [&val](auto && rng) | |||||
| -> invoke_result_t<push_front_fn, decltype(rng), T(&)[N]> | |||||
| { | |||||
| return push_front_fn{}(static_cast<decltype(rng)>(rng), val); | |||||
| }; | |||||
| } | |||||
| #endif // RANGES_WORKAROUND_MSVC_OLD_LAMBDA | |||||
| public: | |||||
| template<typename Rng, typename T> | |||||
| auto operator()(Rng && rng, T && t) const -> CPP_ret(Rng)( // | |||||
| requires input_range<Rng> && can_push_front_<Rng, T> && | |||||
| (range<T> || constructible_from<range_value_t<Rng>, T>)) | |||||
| { | |||||
| push_front(rng, static_cast<T &&>(t)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| } // namespace adl_push_front_detail | |||||
| /// \endcond | |||||
| namespace actions | |||||
| { | |||||
| /// \ingroup group-actions | |||||
| RANGES_INLINE_VARIABLE( | |||||
| detail::with_braced_init_args<action<adl_push_front_detail::push_front_fn>>, | |||||
| push_front) | |||||
| } // namespace actions | |||||
| using actions::push_front; | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Andrey Diduh 2019 | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_REMOVE_HPP | |||||
| #define RANGES_V3_ACTION_REMOVE_HPP | |||||
| #include <meta/meta.hpp> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/erase.hpp> | |||||
| #include <range/v3/algorithm/remove.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct remove_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename V, typename P> | |||||
| static auto CPP_fun(bind)(remove_fn remove, V && value, P proj)( // | |||||
| requires(!range<V>)) | |||||
| { | |||||
| return bind_back(remove, static_cast<V &&>(value), std::move(proj)); | |||||
| } | |||||
| template<typename V> | |||||
| static auto bind(remove_fn remove, V && value) | |||||
| { | |||||
| return bind_back(remove, static_cast<V &&>(value), identity{}); | |||||
| } | |||||
| public: | |||||
| template<typename Rng, typename V, typename P = identity> | |||||
| auto operator()(Rng && rng, V const & value, P proj = {}) const | |||||
| -> CPP_ret(Rng)( // | |||||
| requires forward_range<Rng> && permutable<iterator_t<Rng>> && | |||||
| erasable_range<Rng, iterator_t<Rng>, sentinel_t<Rng>> && | |||||
| indirect_relation<equal_to, projected<iterator_t<Rng>, P>, | |||||
| V const *>) | |||||
| { | |||||
| auto it = ranges::remove(rng, value, std::move(proj)); | |||||
| ranges::erase(rng, it, ranges::end(rng)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \sa action | |||||
| /// \sa with_braced_init_args | |||||
| RANGES_INLINE_VARIABLE(action<remove_fn>, remove) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_REMOVE_IF_HPP | |||||
| #define RANGES_V3_ACTION_REMOVE_IF_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/erase.hpp> | |||||
| #include <range/v3/algorithm/remove_if.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| // TODO Look at all the special cases handled by erase_if in Library Fundamentals 2 | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct remove_if_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename C, typename P = identity> | |||||
| static auto CPP_fun(bind)(remove_if_fn remove_if, C pred, P proj = P{})( // | |||||
| requires(!range<C>)) | |||||
| { | |||||
| return bind_back(remove_if, std::move(pred), std::move(proj)); | |||||
| } | |||||
| public: | |||||
| template<typename Rng, typename C, typename P = identity> | |||||
| auto operator()(Rng && rng, C pred, P proj = P{}) const -> CPP_ret(Rng)( // | |||||
| requires forward_range<Rng> && | |||||
| erasable_range<Rng &, iterator_t<Rng>, iterator_t<Rng>> && | |||||
| permutable<iterator_t<Rng>> && | |||||
| indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>) | |||||
| { | |||||
| auto it = ranges::remove_if(rng, std::move(pred), std::move(proj)); | |||||
| ranges::erase(rng, it, ranges::end(rng)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \sa action | |||||
| RANGES_INLINE_VARIABLE(action<remove_if_fn>, remove_if) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // Copyright Gonzalo Brito Gadeschi 2017 | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_REVERSE_HPP | |||||
| #define RANGES_V3_ACTION_REVERSE_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/algorithm/reverse.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| /// Reversed the source range in-place. | |||||
| struct reverse_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| public: | |||||
| template<typename Rng> | |||||
| auto operator()(Rng && rng) const -> CPP_ret(Rng)( // | |||||
| requires bidirectional_range<Rng> && permutable<iterator_t<Rng>>) | |||||
| { | |||||
| ranges::reverse(rng); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates reverse_fn | |||||
| /// \sa action | |||||
| RANGES_INLINE_VARIABLE(action<reverse_fn>, reverse) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Filip Matzner 2015 | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_SHUFFLE_HPP | |||||
| #define RANGES_V3_ACTION_SHUFFLE_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/algorithm/shuffle.hpp> | |||||
| #include <range/v3/functional/bind.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct shuffle_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename Gen> | |||||
| static auto CPP_fun(bind)(shuffle_fn shuffle, Gen && gen)( // | |||||
| requires uniform_random_bit_generator<Gen>) | |||||
| { | |||||
| return bind_back(shuffle, static_cast<Gen &&>(gen)); | |||||
| } | |||||
| #ifdef RANGES_WORKAROUND_MSVC_OLD_LAMBDA | |||||
| template<typename Gen> | |||||
| struct lamduh | |||||
| { | |||||
| Gen & gen_; | |||||
| template<typename Rng> | |||||
| auto operator()(Rng && rng) const | |||||
| -> invoke_result_t<shuffle_fn, Rng, Gen &> | |||||
| { | |||||
| return shuffle_fn{}(static_cast<Rng &&>(rng), gen_); | |||||
| } | |||||
| }; | |||||
| template<typename Gen> | |||||
| static lamduh<Gen> CPP_fun(bind)(shuffle_fn, Gen & gen)( // | |||||
| requires uniform_random_bit_generator<Gen>) | |||||
| { | |||||
| return {gen}; | |||||
| } | |||||
| #else // ^^^ workaround / no workaround vvv | |||||
| template<typename Gen> | |||||
| static auto CPP_fun(bind)(shuffle_fn, Gen & gen)( // | |||||
| requires uniform_random_bit_generator<Gen>) | |||||
| { | |||||
| return [&gen](auto && rng) | |||||
| -> invoke_result_t<shuffle_fn, decltype(rng), Gen &> { | |||||
| return shuffle_fn{}(static_cast<decltype(rng)>(rng), gen); | |||||
| }; | |||||
| } | |||||
| #endif // RANGES_WORKAROUND_MSVC_OLD_LAMBDA | |||||
| public: | |||||
| template<typename Rng, typename Gen> | |||||
| auto operator()(Rng && rng, Gen && gen) const -> CPP_ret(Rng)( // | |||||
| requires random_access_range<Rng> && permutable<iterator_t<Rng>> && | |||||
| uniform_random_bit_generator<std::remove_reference_t<Gen>> && | |||||
| convertible_to<invoke_result_t<Gen &>, range_difference_t<Rng>>) | |||||
| { | |||||
| ranges::shuffle(rng, static_cast<Gen &&>(gen)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates shuffle_fn | |||||
| /// \sa `action` | |||||
| RANGES_INLINE_VARIABLE(action<shuffle_fn>, shuffle) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_SLICE_HPP | |||||
| #define RANGES_V3_ACTION_SLICE_HPP | |||||
| #include <meta/meta.hpp> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/erase.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| #include <range/v3/view/interface.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct slice_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename D> | |||||
| using diff_t = range_difference_t<D>; | |||||
| // Overloads for the pipe syntax: rng | actions::slice(from, to) | |||||
| template<typename D> | |||||
| static auto CPP_fun(bind)(slice_fn slice, D from, D to)( // | |||||
| requires integral<D>) | |||||
| { | |||||
| return bind_back(slice, from, to); | |||||
| } | |||||
| template<typename D> | |||||
| static auto CPP_fun(bind)(slice_fn slice, D from, detail::from_end_<D> to)( // | |||||
| requires integral<D>) | |||||
| { | |||||
| return bind_back(slice, from, to); | |||||
| } | |||||
| template<typename D> | |||||
| static auto CPP_fun(bind)(slice_fn slice, detail::from_end_<D> from, | |||||
| detail::from_end_<D> to)( // | |||||
| requires integral<D>) | |||||
| { | |||||
| return bind_back(slice, from, to); | |||||
| } | |||||
| template<typename D> | |||||
| static auto CPP_fun(bind)(slice_fn slice, D from, end_fn const & to)( // | |||||
| requires integral<D>) | |||||
| { | |||||
| return bind_back(slice, from, to); | |||||
| } | |||||
| template<typename D> | |||||
| static auto CPP_fun(bind)(slice_fn slice, detail::from_end_<D> from, | |||||
| end_fn const & to)( // | |||||
| requires integral<D>) | |||||
| { | |||||
| return bind_back(slice, from, to); | |||||
| } | |||||
| public: | |||||
| template<typename Rng, typename I = iterator_t<Rng>> | |||||
| auto operator()(Rng && rng, diff_t<Rng> from, diff_t<Rng> to) const | |||||
| -> CPP_ret(Rng)( // | |||||
| requires forward_range<Rng> && erasable_range<Rng &, I, I>) | |||||
| { | |||||
| RANGES_EXPECT(0 <= from && 0 <= to && from <= to); | |||||
| RANGES_EXPECT(!sized_range<Rng> || to <= distance(rng)); | |||||
| ranges::actions::erase(rng, begin(rng), next(begin(rng), from)); | |||||
| ranges::actions::erase(rng, next(begin(rng), to - from), end(rng)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| template<typename Rng, typename I = iterator_t<Rng>> | |||||
| auto operator()(Rng && rng, diff_t<Rng> from, | |||||
| detail::from_end_<diff_t<Rng>> to) const -> CPP_ret(Rng)( // | |||||
| requires bidirectional_range<Rng> && erasable_range<Rng &, I, I>) | |||||
| { | |||||
| RANGES_EXPECT(0 <= from && to.dist_ <= 0); | |||||
| RANGES_EXPECT(!sized_range<Rng> || from - to.dist_ <= distance(rng)); | |||||
| ranges::actions::erase(rng, begin(rng), next(begin(rng), from)); | |||||
| if(to.dist_ != 0) | |||||
| { | |||||
| auto const last = next(begin(rng), end(rng)); | |||||
| ranges::actions::erase(rng, prev(last, -to.dist_), last); | |||||
| } | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| template<typename Rng, typename I = iterator_t<Rng>> | |||||
| auto operator()(Rng && rng, detail::from_end_<diff_t<Rng>> from, | |||||
| detail::from_end_<diff_t<Rng>> to) const -> CPP_ret(Rng)( // | |||||
| requires bidirectional_range<Rng> && erasable_range<Rng &, I, I>) | |||||
| { | |||||
| RANGES_EXPECT(from.dist_ <= 0 && to.dist_ <= 0 && from.dist_ <= to.dist_); | |||||
| RANGES_EXPECT(!sized_range<Rng> || 0 <= distance(rng) + from.dist_); | |||||
| auto last = next(begin(rng), end(rng)); | |||||
| ranges::actions::erase(rng, prev(last, -to.dist_), last); | |||||
| last = next(begin(rng), end(rng)); | |||||
| ranges::actions::erase( | |||||
| rng, begin(rng), prev(last, to.dist_ - from.dist_)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| template<typename Rng, typename I = iterator_t<Rng>> | |||||
| auto operator()(Rng && rng, diff_t<Rng> from, end_fn const &) const | |||||
| -> CPP_ret(Rng)( // | |||||
| requires forward_range<Rng> && erasable_range<Rng &, I, I>) | |||||
| { | |||||
| RANGES_EXPECT(0 <= from); | |||||
| RANGES_EXPECT(!sized_range<Rng> || from <= distance(rng)); | |||||
| ranges::actions::erase(rng, begin(rng), next(begin(rng), from)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| template<typename Rng, typename I = iterator_t<Rng>> | |||||
| auto operator()(Rng && rng, detail::from_end_<diff_t<Rng>> from, | |||||
| end_fn const &) const -> CPP_ret(Rng)( // | |||||
| requires bidirectional_range<Rng> && erasable_range<Rng &, I, I>) | |||||
| { | |||||
| RANGES_EXPECT(from.dist_ <= 0); | |||||
| RANGES_EXPECT(!sized_range<Rng> || 0 <= distance(rng) + from.dist_); | |||||
| auto const last = next(begin(rng), end(rng)); | |||||
| ranges::actions::erase(rng, begin(rng), prev(last, -from.dist_)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates slice_fn | |||||
| /// \sa action | |||||
| RANGES_INLINE_VARIABLE(action<slice_fn>, slice) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_SORT_HPP | |||||
| #define RANGES_V3_ACTION_SORT_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/algorithm/sort.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct sort_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename C, typename P = identity> | |||||
| static auto CPP_fun(bind)(sort_fn sort, C pred, P proj = {})( // | |||||
| requires(!range<C>)) | |||||
| { | |||||
| return bind_back(sort, std::move(pred), std::move(proj)); | |||||
| } | |||||
| public: | |||||
| template<typename Rng, typename C = less, typename P = identity> | |||||
| auto operator()(Rng && rng, C pred = {}, P proj = {}) const | |||||
| -> CPP_ret(Rng)( // | |||||
| requires forward_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||||
| { | |||||
| ranges::sort(rng, std::move(pred), std::move(proj)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates sort_fn | |||||
| /// \sa `action` | |||||
| RANGES_INLINE_VARIABLE(action<sort_fn>, sort) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_SPLIT_HPP | |||||
| #define RANGES_V3_ACTION_SPLIT_HPP | |||||
| #include <vector> | |||||
| #include <meta/meta.hpp> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/concepts.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/conversion.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| #include <range/v3/view/split.hpp> | |||||
| #include <range/v3/view/transform.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct split_fn | |||||
| { | |||||
| private: | |||||
| template<typename Rng> | |||||
| using split_value_t = meta::if_c<(bool)ranges::container<Rng>, uncvref_t<Rng>, | |||||
| std::vector<range_value_t<Rng>>>; | |||||
| public: | |||||
| // BUGBUG something is not right with the actions. It should be possible | |||||
| // to move a container into a split and have elements moved into the result. | |||||
| template<typename Rng> | |||||
| auto operator()(Rng && rng, range_value_t<Rng> val) const | |||||
| -> CPP_ret(std::vector<split_value_t<Rng>>)( // | |||||
| requires input_range<Rng> && indirectly_comparable< | |||||
| iterator_t<Rng>, range_value_t<Rng> const *, ranges::equal_to>) | |||||
| { | |||||
| return views::split(rng, std::move(val)) | | |||||
| views::transform(to<split_value_t<Rng>>()) | to_vector; | |||||
| } | |||||
| template<typename Rng, typename Pattern> | |||||
| auto operator()(Rng && rng, Pattern && pattern) const | |||||
| -> CPP_ret(std::vector<split_value_t<Rng>>)( // | |||||
| requires input_range<Rng> && viewable_range<Pattern> && | |||||
| forward_range<Pattern> && indirectly_comparable< | |||||
| iterator_t<Rng>, iterator_t<Pattern>, ranges::equal_to> && | |||||
| (forward_range<Rng> || detail::tiny_range<Pattern>)) | |||||
| { | |||||
| return views::split(rng, static_cast<Pattern &&>(pattern)) | | |||||
| views::transform(to<split_value_t<Rng>>()) | to_vector; | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates split_fn | |||||
| /// \sa action | |||||
| RANGES_INLINE_VARIABLE(action<split_fn>, split) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_SPLIT_WHEN_HPP | |||||
| #define RANGES_V3_ACTION_SPLIT_WHEN_HPP | |||||
| #include <vector> | |||||
| #include <meta/meta.hpp> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/concepts.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/conversion.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| #include <range/v3/view/split_when.hpp> | |||||
| #include <range/v3/view/transform.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct split_when_fn | |||||
| { | |||||
| private: | |||||
| template<typename Rng> | |||||
| using split_value_t = meta::if_c<(bool)ranges::container<Rng>, uncvref_t<Rng>, | |||||
| std::vector<range_value_t<Rng>>>; | |||||
| public: | |||||
| // BUGBUG something is not right with the actions. It should be possible | |||||
| // to move a container into a split and have elements moved into the result. | |||||
| template<typename Rng, typename Fun> | |||||
| auto operator()(Rng && rng, Fun fun) const // | |||||
| -> CPP_ret(std::vector<split_value_t<Rng>>)( // | |||||
| requires forward_range<Rng> && // | |||||
| invocable<Fun &, iterator_t<Rng>, sentinel_t<Rng>> && invocable< | |||||
| Fun &, iterator_t<Rng>, iterator_t<Rng>> && | |||||
| copy_constructible<Fun> && convertible_to< | |||||
| invoke_result_t<Fun &, iterator_t<Rng>, sentinel_t<Rng>>, | |||||
| std::pair<bool, iterator_t<Rng>>>) | |||||
| { | |||||
| return views::split_when(rng, std::move(fun)) | | |||||
| views::transform(to<split_value_t<Rng>>()) | to_vector; | |||||
| } | |||||
| template<typename Rng, typename Fun> | |||||
| auto operator()(Rng && rng, Fun fun) const | |||||
| -> CPP_ret(std::vector<split_value_t<Rng>>)( // | |||||
| requires forward_range<Rng> && predicate< | |||||
| Fun const &, range_reference_t<Rng>> && copy_constructible<Fun>) | |||||
| { | |||||
| return views::split_when(rng, std::move(fun)) | | |||||
| views::transform(to<split_value_t<Rng>>()) | to_vector; | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates split_fn | |||||
| /// \sa action | |||||
| RANGES_INLINE_VARIABLE(action<split_when_fn>, split_when) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_STABLE_SORT_HPP | |||||
| #define RANGES_V3_ACTION_STABLE_SORT_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/algorithm/stable_sort.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct stable_sort_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename C, typename P = identity> | |||||
| static auto CPP_fun(bind)(stable_sort_fn stable_sort, C pred, | |||||
| P proj = P{})( // | |||||
| requires(!range<C>)) | |||||
| { | |||||
| return bind_back(stable_sort, std::move(pred), std::move(proj)); | |||||
| } | |||||
| public: | |||||
| template<typename Rng, typename C = less, typename P = identity> | |||||
| auto operator()(Rng && rng, C pred = C{}, P proj = P{}) const | |||||
| -> CPP_ret(Rng)( // | |||||
| requires forward_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||||
| { | |||||
| ranges::stable_sort(rng, std::move(pred), std::move(proj)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates stable_sort_fn | |||||
| /// \sa action | |||||
| RANGES_INLINE_VARIABLE(action<stable_sort_fn>, stable_sort) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_STRIDE_HPP | |||||
| #define RANGES_V3_ACTION_STRIDE_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/erase.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct stride_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename D> | |||||
| static auto CPP_fun(bind)(stride_fn stride, D step)( // | |||||
| requires integral<D>) | |||||
| { | |||||
| return bind_back(stride, step); | |||||
| } | |||||
| public: | |||||
| template<typename Rng, typename D = range_difference_t<Rng>> | |||||
| auto operator()(Rng && rng, range_difference_t<Rng> const step) const | |||||
| -> CPP_ret(Rng)( // | |||||
| requires forward_range<Rng> && | |||||
| erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>> && | |||||
| permutable<iterator_t<Rng>>) | |||||
| { | |||||
| using I = iterator_t<Rng>; | |||||
| using S = sentinel_t<Rng>; | |||||
| RANGES_EXPECT(0 < step); | |||||
| if(1 < step) | |||||
| { | |||||
| I first = ranges::begin(rng); | |||||
| S const last = ranges::end(rng); | |||||
| if(first != last) | |||||
| { | |||||
| for(I i = ranges::next(++first, step - 1, last); i != last; | |||||
| advance(i, step, last), ++first) | |||||
| { | |||||
| *first = iter_move(i); | |||||
| } | |||||
| } | |||||
| ranges::actions::erase(rng, first, last); | |||||
| } | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates stride_fn | |||||
| /// \sa action | |||||
| RANGES_INLINE_VARIABLE(action<stride_fn>, stride) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_TAKE_HPP | |||||
| #define RANGES_V3_ACTION_TAKE_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/erase.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct take_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename Int> | |||||
| static auto CPP_fun(bind)(take_fn take, Int n)( // | |||||
| requires integral<Int>) | |||||
| { | |||||
| return bind_back(take, n); | |||||
| } | |||||
| public: | |||||
| template<typename Rng> | |||||
| auto operator()(Rng && rng, range_difference_t<Rng> n) const | |||||
| -> CPP_ret(Rng)( // | |||||
| requires forward_range<Rng> && | |||||
| erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>>) | |||||
| { | |||||
| RANGES_EXPECT(n >= 0); | |||||
| ranges::actions::erase( | |||||
| rng, ranges::next(begin(rng), n, end(rng)), end(rng)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates take_fn | |||||
| /// \sa action | |||||
| RANGES_INLINE_VARIABLE(action<take_fn>, take) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_TAKE_WHILE_HPP | |||||
| #define RANGES_V3_ACTION_TAKE_WHILE_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/erase.hpp> | |||||
| #include <range/v3/algorithm/find_if_not.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct take_while_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename Fun> | |||||
| static auto CPP_fun(bind)(take_while_fn take_while, Fun fun)( // | |||||
| requires(!range<Fun>)) | |||||
| { | |||||
| return bind_back(take_while, std::move(fun)); | |||||
| } | |||||
| public: | |||||
| template<typename Rng, typename Fun> | |||||
| auto operator()(Rng && rng, Fun fun) const -> CPP_ret(Rng)( // | |||||
| requires forward_range<Rng> && | |||||
| erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>> && | |||||
| indirect_unary_predicate<Fun, iterator_t<Rng>>) | |||||
| { | |||||
| ranges::actions::erase( | |||||
| rng, find_if_not(begin(rng), end(rng), std::move(fun)), end(rng)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates take_while_fn | |||||
| /// \sa action | |||||
| RANGES_INLINE_VARIABLE(action<take_while_fn>, take_while) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_TRANSFORM_HPP | |||||
| #define RANGES_V3_ACTION_TRANSFORM_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/algorithm/transform.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct transform_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename F, typename P = identity> | |||||
| static auto CPP_fun(bind)(transform_fn transform, F fun, P proj = P{})( // | |||||
| requires(!range<F>)) | |||||
| { | |||||
| return bind_back(transform, std::move(fun), std::move(proj)); | |||||
| } | |||||
| public: | |||||
| template<typename Rng, typename F, typename P = identity> | |||||
| auto operator()(Rng && rng, F fun, P proj = P{}) const -> CPP_ret(Rng)( // | |||||
| requires input_range<Rng> && copy_constructible<F> && | |||||
| writable<iterator_t<Rng>, | |||||
| indirect_result_t<F &, projected<iterator_t<Rng>, P>>>) | |||||
| { | |||||
| ranges::transform(rng, begin(rng), std::move(fun), std::move(proj)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates transform_fn | |||||
| /// \sa action | |||||
| RANGES_INLINE_VARIABLE(action<transform_fn>, transform) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_UNIQUE_HPP | |||||
| #define RANGES_V3_ACTION_UNIQUE_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/erase.hpp> | |||||
| #include <range/v3/algorithm/unique.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct unique_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename C, typename P = identity> | |||||
| static auto CPP_fun(bind)(unique_fn unique, C pred, P proj = P{})( // | |||||
| requires(!range<C>)) | |||||
| { | |||||
| return bind_back(unique, std::move(pred), std::move(proj)); | |||||
| } | |||||
| public: | |||||
| template<typename Rng, typename C = equal_to, typename P = identity> | |||||
| auto operator()(Rng && rng, C pred = C{}, P proj = P{}) const | |||||
| -> CPP_ret(Rng)( // | |||||
| requires forward_range<Rng> && | |||||
| erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>> && | |||||
| sortable<iterator_t<Rng>, C, P>) | |||||
| { | |||||
| auto it = ranges::unique(rng, std::move(pred), std::move(proj)); | |||||
| ranges::erase(rng, it, end(rng)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \relates unique_fn | |||||
| /// \sa action | |||||
| RANGES_INLINE_VARIABLE(action<unique_fn>, unique) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Andrey Diduh 2019 | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ACTION_UNSTABLE_REMOVE_IF_HPP | |||||
| #define RANGES_V3_ACTION_UNSTABLE_REMOVE_IF_HPP | |||||
| #include <utility> | |||||
| #include <concepts/concepts.hpp> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/action/action.hpp> | |||||
| #include <range/v3/action/erase.hpp> | |||||
| #include <range/v3/algorithm/unstable_remove_if.hpp> | |||||
| #include <range/v3/functional/bind_back.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-actions | |||||
| /// @{ | |||||
| namespace actions | |||||
| { | |||||
| struct unstable_remove_if_fn | |||||
| { | |||||
| private: | |||||
| friend action_access; | |||||
| template<typename C, typename P = identity> | |||||
| static auto CPP_fun(bind)(unstable_remove_if_fn unstable_remove_if, C pred, | |||||
| P proj = P{})( // | |||||
| requires(!range<C>)) | |||||
| { | |||||
| return bind_back(unstable_remove_if, std::move(pred), std::move(proj)); | |||||
| } | |||||
| public: | |||||
| template<typename Rng, typename C, typename P = identity> | |||||
| auto operator()(Rng && rng, C pred, P proj = P{}) const -> CPP_ret(Rng)( // | |||||
| requires bidirectional_range<Rng> && common_range<Rng> && | |||||
| permutable<iterator_t<Rng>> && | |||||
| indirect_unary_predicate<C, projected<iterator_t<Rng>, P>> && | |||||
| erasable_range<Rng, iterator_t<Rng>, iterator_t<Rng>>) | |||||
| { | |||||
| auto it = ranges::unstable_remove_if(ranges::begin(rng), | |||||
| ranges::end(rng), | |||||
| std::move(pred), | |||||
| std::move(proj)); | |||||
| ranges::erase(rng, it, ranges::end(rng)); | |||||
| return static_cast<Rng &&>(rng); | |||||
| } | |||||
| }; | |||||
| /// \ingroup group-actions | |||||
| /// \sa `action` | |||||
| /// \sa `actions::unstable_remove_if_fn` | |||||
| RANGES_INLINE_VARIABLE(action<unstable_remove_if_fn>, unstable_remove_if) | |||||
| } // namespace actions | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // RANGES_V3_ACTION_UNSTABLE_REMOVE_IF_HPP |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_HPP | |||||
| #define RANGES_V3_ALGORITHM_HPP | |||||
| #include <range/v3/detail/config.hpp> | |||||
| RANGES_DISABLE_WARNINGS | |||||
| #include <range/v3/algorithm/adjacent_find.hpp> | |||||
| #include <range/v3/algorithm/adjacent_remove_if.hpp> | |||||
| #include <range/v3/algorithm/all_of.hpp> | |||||
| #include <range/v3/algorithm/any_of.hpp> | |||||
| #include <range/v3/algorithm/binary_search.hpp> | |||||
| #include <range/v3/algorithm/copy.hpp> | |||||
| #include <range/v3/algorithm/copy_backward.hpp> | |||||
| #include <range/v3/algorithm/copy_if.hpp> | |||||
| #include <range/v3/algorithm/copy_n.hpp> | |||||
| #include <range/v3/algorithm/count.hpp> | |||||
| #include <range/v3/algorithm/count_if.hpp> | |||||
| #include <range/v3/algorithm/ends_with.hpp> | |||||
| #include <range/v3/algorithm/equal.hpp> | |||||
| #include <range/v3/algorithm/equal_range.hpp> | |||||
| #include <range/v3/algorithm/fill.hpp> | |||||
| #include <range/v3/algorithm/fill_n.hpp> | |||||
| #include <range/v3/algorithm/find.hpp> | |||||
| #include <range/v3/algorithm/find_end.hpp> | |||||
| #include <range/v3/algorithm/find_first_of.hpp> | |||||
| #include <range/v3/algorithm/find_if.hpp> | |||||
| #include <range/v3/algorithm/find_if_not.hpp> | |||||
| #include <range/v3/algorithm/for_each.hpp> | |||||
| #include <range/v3/algorithm/for_each_n.hpp> | |||||
| #include <range/v3/algorithm/generate.hpp> | |||||
| #include <range/v3/algorithm/generate_n.hpp> | |||||
| #include <range/v3/algorithm/heap_algorithm.hpp> | |||||
| #include <range/v3/algorithm/inplace_merge.hpp> | |||||
| #include <range/v3/algorithm/is_partitioned.hpp> | |||||
| #include <range/v3/algorithm/is_sorted.hpp> | |||||
| #include <range/v3/algorithm/is_sorted_until.hpp> | |||||
| #include <range/v3/algorithm/lexicographical_compare.hpp> | |||||
| #include <range/v3/algorithm/lower_bound.hpp> | |||||
| #include <range/v3/algorithm/max.hpp> | |||||
| #include <range/v3/algorithm/max_element.hpp> | |||||
| #include <range/v3/algorithm/merge.hpp> | |||||
| #include <range/v3/algorithm/min.hpp> | |||||
| #include <range/v3/algorithm/min_element.hpp> | |||||
| #include <range/v3/algorithm/minmax.hpp> | |||||
| #include <range/v3/algorithm/minmax_element.hpp> | |||||
| #include <range/v3/algorithm/mismatch.hpp> | |||||
| #include <range/v3/algorithm/move.hpp> | |||||
| #include <range/v3/algorithm/move_backward.hpp> | |||||
| #include <range/v3/algorithm/none_of.hpp> | |||||
| #include <range/v3/algorithm/nth_element.hpp> | |||||
| #include <range/v3/algorithm/partial_sort.hpp> | |||||
| #include <range/v3/algorithm/partial_sort_copy.hpp> | |||||
| #include <range/v3/algorithm/partition.hpp> | |||||
| #include <range/v3/algorithm/partition_copy.hpp> | |||||
| #include <range/v3/algorithm/partition_point.hpp> | |||||
| #include <range/v3/algorithm/permutation.hpp> | |||||
| #include <range/v3/algorithm/remove.hpp> | |||||
| #include <range/v3/algorithm/remove_copy.hpp> | |||||
| #include <range/v3/algorithm/remove_copy_if.hpp> | |||||
| #include <range/v3/algorithm/remove_if.hpp> | |||||
| #include <range/v3/algorithm/replace.hpp> | |||||
| #include <range/v3/algorithm/replace_copy.hpp> | |||||
| #include <range/v3/algorithm/replace_copy_if.hpp> | |||||
| #include <range/v3/algorithm/replace_if.hpp> | |||||
| #include <range/v3/algorithm/reverse.hpp> | |||||
| #include <range/v3/algorithm/reverse_copy.hpp> | |||||
| #include <range/v3/algorithm/rotate.hpp> | |||||
| #include <range/v3/algorithm/rotate_copy.hpp> | |||||
| #include <range/v3/algorithm/sample.hpp> | |||||
| #include <range/v3/algorithm/search.hpp> | |||||
| #include <range/v3/algorithm/search_n.hpp> | |||||
| #include <range/v3/algorithm/set_algorithm.hpp> | |||||
| #include <range/v3/algorithm/shuffle.hpp> | |||||
| #include <range/v3/algorithm/sort.hpp> | |||||
| #include <range/v3/algorithm/stable_partition.hpp> | |||||
| #include <range/v3/algorithm/stable_sort.hpp> | |||||
| #include <range/v3/algorithm/starts_with.hpp> | |||||
| #include <range/v3/algorithm/swap_ranges.hpp> | |||||
| #include <range/v3/algorithm/transform.hpp> | |||||
| #include <range/v3/algorithm/unique.hpp> | |||||
| #include <range/v3/algorithm/unique_copy.hpp> | |||||
| #include <range/v3/algorithm/unstable_remove_if.hpp> | |||||
| #include <range/v3/algorithm/upper_bound.hpp> | |||||
| // BUGBUG | |||||
| #include <range/v3/algorithm/aux_/equal_range_n.hpp> | |||||
| #include <range/v3/algorithm/aux_/lower_bound_n.hpp> | |||||
| #include <range/v3/algorithm/aux_/merge_n.hpp> | |||||
| #include <range/v3/algorithm/aux_/merge_n_with_buffer.hpp> | |||||
| #include <range/v3/algorithm/aux_/sort_n_with_buffer.hpp> | |||||
| #include <range/v3/algorithm/aux_/upper_bound_n.hpp> | |||||
| RANGES_RE_ENABLE_WARNINGS | |||||
| #endif |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_ADJACENT_FIND_HPP | |||||
| #define RANGES_V3_ALGORITHM_ADJACENT_FIND_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/dangling.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(adjacent_find) | |||||
| /// \brief function template \c adjacent_find | |||||
| /// | |||||
| /// range-based version of the \c adjacent_find std algorithm | |||||
| /// | |||||
| /// \pre `Rng` is a model of the `Range` concept | |||||
| /// \pre `C` is a model of the `BinaryPredicate` concept | |||||
| template<typename I, typename S, typename C = equal_to, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(adjacent_find)( | |||||
| I first, S last, C pred = C{}, P proj = P{}) // | |||||
| ->CPP_ret(I)( // | |||||
| requires forward_iterator<I> && sentinel_for<S, I> && | |||||
| indirect_relation<C, projected<I, P>>) | |||||
| { | |||||
| if(first == last) | |||||
| return first; | |||||
| auto inext = first; | |||||
| for(; ++inext != last; first = inext) | |||||
| if(invoke(pred, invoke(proj, *first), invoke(proj, *inext))) | |||||
| return first; | |||||
| return inext; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename C = equal_to, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(adjacent_find)(Rng && rng, C pred = C{}, P proj = P{}) // | |||||
| ->CPP_ret(safe_iterator_t<Rng>)( // | |||||
| requires forward_range<Rng> && | |||||
| indirect_relation<C, projected<iterator_t<Rng>, P>>) | |||||
| { | |||||
| return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(adjacent_find) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::adjacent_find; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // RANGE_ALGORITHM_ADJACENT_FIND_HPP |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler | |||||
| // Copyright Christopher Di Bella | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_ADJACENT_REMOVE_IF_HPP | |||||
| #define RANGES_V3_ALGORITHM_ADJACENT_REMOVE_IF_HPP | |||||
| #include <functional> | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/adjacent_find.hpp> | |||||
| #include <range/v3/algorithm/move.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/move.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(adjacent_remove_if) | |||||
| /// \brief function \c adjacent_remove_if | |||||
| /// | |||||
| /// range-based version of the \c adjacent_remove_if algorithm | |||||
| /// | |||||
| /// \pre `Rng` is a model of the `forward_range` concept. | |||||
| /// \pre `Pred` is a model of the `BinaryPredicate` concept. | |||||
| template<typename I, typename S, typename Pred, typename Proj = identity> | |||||
| auto RANGES_FUN_NIEBLOID(adjacent_remove_if)( | |||||
| I first, S last, Pred pred = {}, Proj proj = {}) | |||||
| ->CPP_ret(I)( // | |||||
| requires permutable<I> && sentinel_for<S, I> && | |||||
| indirect_relation<Pred, projected<I, Proj>>) | |||||
| { | |||||
| first = adjacent_find(std::move(first), last, std::ref(pred), std::ref(proj)); | |||||
| if(first == last) | |||||
| return first; | |||||
| auto i = first; | |||||
| for(auto j = ++i; ++j != last; ++i) | |||||
| { | |||||
| if(!invoke(pred, invoke(proj, *i), invoke(proj, *j))) | |||||
| { | |||||
| *first = iter_move(i); | |||||
| ++first; | |||||
| } | |||||
| } | |||||
| *first = iter_move(i); | |||||
| ++first; | |||||
| return first; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename Pred, typename Proj = identity> | |||||
| auto RANGES_FUN_NIEBLOID(adjacent_remove_if)( | |||||
| Rng && rng, Pred pred, Proj proj = {}) // | |||||
| ->CPP_ret(safe_iterator_t<Rng>)( // | |||||
| requires forward_range<Rng> && | |||||
| indirect_relation<Pred, projected<iterator_t<Rng>, Proj>> && | |||||
| permutable<iterator_t<Rng>>) | |||||
| { | |||||
| return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(adjacent_remove_if) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::adjacent_remove_if; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // RANGES_V3_ALGORITHM_ADJACENT_REMOVE_IF_HPP |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Andrew Sutton 2014 | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_ALL_OF_HPP | |||||
| #define RANGES_V3_ALGORITHM_ALL_OF_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(all_of) | |||||
| /// \brief function template \c all_of | |||||
| template<typename I, typename S, typename F, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(all_of)(I first, S last, F pred, P proj = P{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires input_iterator<I> && sentinel_for<S, I> && | |||||
| indirect_unary_predicate<F, projected<I, P>>) | |||||
| { | |||||
| for(; first != last; ++first) | |||||
| if(!invoke(pred, invoke(proj, *first))) | |||||
| break; | |||||
| return first == last; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename F, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(all_of)(Rng && rng, F pred, P proj = P{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires input_range<Rng> && | |||||
| indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>) | |||||
| { | |||||
| return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(all_of) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::all_of; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Andrew Sutton 2014 | |||||
| // Copyright Gonzalo Brito Gadeschi 2014 | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_ANY_OF_HPP | |||||
| #define RANGES_V3_ALGORITHM_ANY_OF_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(any_of) | |||||
| /// \brief function template \c any_of | |||||
| template<typename I, typename S, typename F, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(any_of)(I first, S last, F pred, P proj = P{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires input_iterator<I> && sentinel_for<S, I> && | |||||
| indirect_unary_predicate<F, projected<I, P>>) | |||||
| { | |||||
| for(; first != last; ++first) | |||||
| if(invoke(pred, invoke(proj, *first))) | |||||
| return true; | |||||
| return false; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename F, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(any_of)(Rng && rng, F pred, P proj = P{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires input_range<Rng> && | |||||
| indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>) | |||||
| { | |||||
| return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(any_of) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::any_of; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_AUX_EQUAL_RANGE_N_HPP | |||||
| #define RANGES_V3_ALGORITHM_AUX_EQUAL_RANGE_N_HPP | |||||
| #include <functional> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/aux_/lower_bound_n.hpp> | |||||
| #include <range/v3/algorithm/aux_/upper_bound_n.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| #include <range/v3/view/subrange.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| namespace aux | |||||
| { | |||||
| struct equal_range_n_fn | |||||
| { | |||||
| template<typename I, typename V, typename R = less, typename P = identity> | |||||
| auto operator()(I first, iter_difference_t<I> dist, V const & val, | |||||
| R pred = R{}, P proj = P{}) const -> CPP_ret(subrange<I>)( // | |||||
| requires forward_iterator<I> && | |||||
| indirect_strict_weak_order<R, V const *, projected<I, P>>) | |||||
| { | |||||
| if(0 < dist) | |||||
| { | |||||
| do | |||||
| { | |||||
| auto half = dist / 2; | |||||
| auto middle = ranges::next(first, half); | |||||
| auto && v = *middle; | |||||
| auto && pv = invoke(proj, (decltype(v) &&)v); | |||||
| if(invoke(pred, pv, val)) | |||||
| { | |||||
| first = std::move(++middle); | |||||
| dist -= half + 1; | |||||
| } | |||||
| else if(invoke(pred, val, pv)) | |||||
| { | |||||
| dist = half; | |||||
| } | |||||
| else | |||||
| { | |||||
| return {lower_bound_n(std::move(first), | |||||
| half, | |||||
| val, | |||||
| std::ref(pred), | |||||
| std::ref(proj)), | |||||
| upper_bound_n(ranges::next(middle), | |||||
| dist - (half + 1), | |||||
| val, | |||||
| std::ref(pred), | |||||
| std::ref(proj))}; | |||||
| } | |||||
| } while(0 != dist); | |||||
| } | |||||
| return {first, first}; | |||||
| } | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(equal_range_n_fn, equal_range_n) | |||||
| } // namespace aux | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // Copyright Casey Carter 2016 | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_AUX_LOWER_BOUND_N_HPP | |||||
| #define RANGES_V3_ALGORITHM_AUX_LOWER_BOUND_N_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/aux_/partition_point_n.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \cond | |||||
| namespace detail | |||||
| { | |||||
| // [&](auto&& i){ return invoke(pred, i, val); } | |||||
| template<typename Pred, typename Val> | |||||
| struct lower_bound_predicate | |||||
| { | |||||
| Pred & pred_; | |||||
| Val & val_; | |||||
| template<typename T> | |||||
| bool operator()(T && t) const | |||||
| { | |||||
| return invoke(pred_, static_cast<T &&>(t), val_); | |||||
| } | |||||
| }; | |||||
| template<typename Pred, typename Val> | |||||
| lower_bound_predicate<Pred, Val> make_lower_bound_predicate(Pred & pred, | |||||
| Val & val) | |||||
| { | |||||
| return {pred, val}; | |||||
| } | |||||
| } // namespace detail | |||||
| /// \endcond | |||||
| namespace aux | |||||
| { | |||||
| struct lower_bound_n_fn | |||||
| { | |||||
| template<typename I, typename V, typename C = less, typename P = identity> | |||||
| auto operator()(I first, iter_difference_t<I> d, V const & val, C pred = C{}, | |||||
| P proj = P{}) const -> CPP_ret(I)( // | |||||
| requires forward_iterator<I> && | |||||
| indirect_strict_weak_order<C, V const *, projected<I, P>>) | |||||
| { | |||||
| return partition_point_n(std::move(first), | |||||
| d, | |||||
| detail::make_lower_bound_predicate(pred, val), | |||||
| std::move(proj)); | |||||
| } | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(lower_bound_n_fn, lower_bound_n) | |||||
| } // namespace aux | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| // Copyright (c) 2009 Alexander Stepanov and Paul McJones | |||||
| // | |||||
| // Permission to use, copy, modify, distribute and sell this software | |||||
| // and its documentation for any purpose is hereby granted without | |||||
| // fee, provided that the above copyright notice appear in all copies | |||||
| // and that both that copyright notice and this permission notice | |||||
| // appear in supporting documentation. The authors make no | |||||
| // representations about the suitability of this software for any | |||||
| // purpose. It is provided "as is" without express or implied | |||||
| // warranty. | |||||
| // | |||||
| // Algorithms from | |||||
| // Elements of Programming | |||||
| // by Alexander Stepanov and Paul McJones | |||||
| // Addison-Wesley Professional, 2009 | |||||
| #ifndef RANGES_V3_ALGORITHM_AUX_MERGE_N_HPP | |||||
| #define RANGES_V3_ALGORITHM_AUX_MERGE_N_HPP | |||||
| #include <tuple> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/copy_n.hpp> | |||||
| #include <range/v3/algorithm/result_types.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| namespace aux | |||||
| { | |||||
| template<typename I0, typename I1, typename O> | |||||
| using merge_n_result = detail::in1_in2_out_result<I0, I1, O>; | |||||
| struct merge_n_fn | |||||
| { | |||||
| template<typename I0, typename I1, typename O, typename C = less, | |||||
| typename P0 = identity, typename P1 = identity> | |||||
| auto operator()(I0 begin0, iter_difference_t<I0> n0, I1 begin1, | |||||
| iter_difference_t<I1> n1, O out, C r = C{}, P0 p0 = P0{}, | |||||
| P1 p1 = P1{}) const -> CPP_ret(merge_n_result<I0, I1, O>)( // | |||||
| requires mergeable<I0, I1, O, C, P0, P1>) | |||||
| { | |||||
| using T = merge_n_result<I0, I1, O>; | |||||
| auto n0orig = n0; | |||||
| auto n1orig = n1; | |||||
| auto b0 = uncounted(begin0); | |||||
| auto b1 = uncounted(begin1); | |||||
| while(true) | |||||
| { | |||||
| if(0 == n0) | |||||
| { | |||||
| auto res = copy_n(b1, n1, out); | |||||
| begin0 = recounted(begin0, b0, n0orig); | |||||
| begin1 = recounted(begin1, res.in, n1orig); | |||||
| return T{begin0, begin1, res.out}; | |||||
| } | |||||
| if(0 == n1) | |||||
| { | |||||
| auto res = copy_n(b0, n0, out); | |||||
| begin0 = recounted(begin0, res.in, n0orig); | |||||
| begin1 = recounted(begin1, b1, n1orig); | |||||
| return T{begin0, begin1, res.out}; | |||||
| } | |||||
| if(invoke(r, invoke(p1, *b1), invoke(p0, *b0))) | |||||
| { | |||||
| *out = *b1; | |||||
| ++b1; | |||||
| ++out; | |||||
| --n1; | |||||
| } | |||||
| else | |||||
| { | |||||
| *out = *b0; | |||||
| ++b0; | |||||
| ++out; | |||||
| --n0; | |||||
| } | |||||
| } | |||||
| } | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(merge_n_fn, merge_n) | |||||
| } // namespace aux | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| // Copyright (c) 2009 Alexander Stepanov and Paul McJones | |||||
| // | |||||
| // Permission to use, copy, modify, distribute and sell this software | |||||
| // and its documentation for any purpose is hereby granted without | |||||
| // fee, provided that the above copyright notice appear in all copies | |||||
| // and that both that copyright notice and this permission notice | |||||
| // appear in supporting documentation. The authors make no | |||||
| // representations about the suitability of this software for any | |||||
| // purpose. It is provided "as is" without express or implied | |||||
| // warranty. | |||||
| // | |||||
| // Algorithms from | |||||
| // Elements of Programming | |||||
| // by Alexander Stepanov and Paul McJones | |||||
| // Addison-Wesley Professional, 2009 | |||||
| #ifndef RANGES_V3_ALGORITHM_AUX_MERGE_N_WITH_BUFFER_HPP | |||||
| #define RANGES_V3_ALGORITHM_AUX_MERGE_N_WITH_BUFFER_HPP | |||||
| #include <tuple> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/aux_/merge_n.hpp> | |||||
| #include <range/v3/algorithm/copy_n.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| namespace aux | |||||
| { | |||||
| struct merge_n_with_buffer_fn | |||||
| { | |||||
| template<typename I, typename B, typename C = less, typename P = identity> | |||||
| auto operator()(I begin0, iter_difference_t<I> n0, I begin1, | |||||
| iter_difference_t<I> n1, B buff, C r = C{}, P p = P{}) const | |||||
| -> CPP_ret(I)( // | |||||
| requires same_as<iter_common_reference_t<I>, | |||||
| iter_common_reference_t<B>> && | |||||
| indirectly_copyable<I, B> && mergeable<B, I, I, C, P, P>) | |||||
| { | |||||
| copy_n(begin0, n0, buff); | |||||
| return merge_n(buff, n0, begin1, n1, begin0, r, p, p).out; | |||||
| } | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(merge_n_with_buffer_fn, merge_n_with_buffer) | |||||
| } // namespace aux | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // Copyright Casey Carter 2016 | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_AUX_PARTITION_POINT_N_HPP | |||||
| #define RANGES_V3_ALGORITHM_AUX_PARTITION_POINT_N_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| namespace aux | |||||
| { | |||||
| struct partition_point_n_fn | |||||
| { | |||||
| template<typename I, typename C, typename P = identity> | |||||
| auto operator()(I first, iter_difference_t<I> d, C pred, | |||||
| P proj = P{}) const // | |||||
| -> CPP_ret(I)( // | |||||
| requires forward_iterator<I> && | |||||
| indirect_unary_predicate<C, projected<I, P>>) | |||||
| { | |||||
| if(0 < d) | |||||
| { | |||||
| do | |||||
| { | |||||
| auto half = d / 2; | |||||
| auto middle = next(uncounted(first), half); | |||||
| if(invoke(pred, invoke(proj, *middle))) | |||||
| { | |||||
| first = recounted(first, std::move(++middle), half + 1); | |||||
| d -= half + 1; | |||||
| } | |||||
| else | |||||
| d = half; | |||||
| } while(0 != d); | |||||
| } | |||||
| return first; | |||||
| } | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(partition_point_n_fn, partition_point_n) | |||||
| } // namespace aux | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| // Copyright (c) 2009 Alexander Stepanov and Paul McJones | |||||
| // | |||||
| // Permission to use, copy, modify, distribute and sell this software | |||||
| // and its documentation for any purpose is hereby granted without | |||||
| // fee, provided that the above copyright notice appear in all copies | |||||
| // and that both that copyright notice and this permission notice | |||||
| // appear in supporting documentation. The authors make no | |||||
| // representations about the suitability of this software for any | |||||
| // purpose. It is provided "as is" without express or implied | |||||
| // warranty. | |||||
| // | |||||
| // Algorithms from | |||||
| // Elements of Programming | |||||
| // by Alexander Stepanov and Paul McJones | |||||
| // Addison-Wesley Professional, 2009 | |||||
| #ifndef RANGES_V3_ALGORITHM_AUX_SORT_N_WITH_BUFFER_HPP | |||||
| #define RANGES_V3_ALGORITHM_AUX_SORT_N_WITH_BUFFER_HPP | |||||
| #include <tuple> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/aux_/merge_n_with_buffer.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| namespace aux | |||||
| { | |||||
| struct sort_n_with_buffer_fn | |||||
| { | |||||
| template<typename I, typename B, typename C = less, typename P = identity> | |||||
| auto operator()(I first, iter_difference_t<I> n, B buff, C r = C{}, | |||||
| P p = P{}) const -> CPP_ret(I)( // | |||||
| requires same_as<iter_common_reference_t<I>, | |||||
| iter_common_reference_t<B>> && | |||||
| indirectly_copyable<I, B> && mergeable<B, I, I, C, P, P>) | |||||
| { | |||||
| auto half = n / 2; | |||||
| if(0 == half) | |||||
| return next(first, n); | |||||
| I m = (*this)(first, half, buff, r, p); | |||||
| (*this)(m, n - half, buff, r, p); | |||||
| return merge_n_with_buffer(first, half, m, n - half, buff, r, p); | |||||
| } | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(sort_n_with_buffer_fn, sort_n_with_buffer) | |||||
| } // namespace aux | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // Copyright Casey Carter 2016 | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_AUX_UPPER_BOUND_N_HPP | |||||
| #define RANGES_V3_ALGORITHM_AUX_UPPER_BOUND_N_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/aux_/partition_point_n.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \cond | |||||
| namespace detail | |||||
| { | |||||
| // [&](auto&& i){ return !invoke(pred, val, i); } | |||||
| template<typename Pred, typename Val> | |||||
| struct upper_bound_predicate | |||||
| { | |||||
| Pred * pred_; | |||||
| Val * val_; | |||||
| template<typename T> | |||||
| bool operator()(T && t) const | |||||
| { | |||||
| return !invoke(*pred_, *val_, static_cast<T &&>(t)); | |||||
| } | |||||
| }; | |||||
| template<typename Pred, typename Val> | |||||
| upper_bound_predicate<Pred, Val> make_upper_bound_predicate(Pred & pred, | |||||
| Val & val) | |||||
| { | |||||
| return {&pred, &val}; | |||||
| } | |||||
| } // namespace detail | |||||
| /// \endcond | |||||
| namespace aux | |||||
| { | |||||
| struct upper_bound_n_fn | |||||
| { | |||||
| /// \brief template function upper_bound | |||||
| /// | |||||
| /// range-based version of the `upper_bound` std algorithm | |||||
| /// | |||||
| /// \pre `Rng` is a model of the `Range` concept | |||||
| template<typename I, typename V, typename C = less, typename P = identity> | |||||
| auto operator()(I first, iter_difference_t<I> d, V const & val, C pred = C{}, | |||||
| P proj = P{}) const -> CPP_ret(I)( // | |||||
| requires forward_iterator<I> && | |||||
| indirect_strict_weak_order<C, V const *, projected<I, P>>) | |||||
| { | |||||
| return partition_point_n(std::move(first), | |||||
| d, | |||||
| detail::make_upper_bound_predicate(pred, val), | |||||
| std::move(proj)); | |||||
| } | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(upper_bound_n_fn, upper_bound_n) | |||||
| } // namespace aux | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_BINARY_SEARCH_HPP | |||||
| #define RANGES_V3_ALGORITHM_BINARY_SEARCH_HPP | |||||
| #include <functional> | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/lower_bound.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(binary_search) | |||||
| /// \brief function template \c binary_search | |||||
| /// | |||||
| /// range-based version of the \c binary_search std algorithm | |||||
| /// | |||||
| /// \pre `Rng` is a model of the `Range` concept | |||||
| template<typename I, | |||||
| typename S, | |||||
| typename V, | |||||
| typename C = less, | |||||
| typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(binary_search)( | |||||
| I first, S last, V const & val, C pred = C{}, P proj = P{}) | |||||
| ->CPP_ret(bool)( // | |||||
| requires forward_iterator<I> && sentinel_for<S, I> && | |||||
| indirect_strict_weak_order<C, V const *, projected<I, P>>) | |||||
| { | |||||
| first = | |||||
| lower_bound(std::move(first), last, val, std::ref(pred), std::ref(proj)); | |||||
| return first != last && !invoke(pred, val, invoke(proj, *first)); | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename V, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(binary_search)( | |||||
| Rng && rng, V const & val, C pred = C{}, P proj = P{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires forward_range<Rng> && | |||||
| indirect_strict_weak_order<C, V const *, projected<iterator_t<Rng>, P>>) | |||||
| { | |||||
| static_assert(!is_infinite<Rng>::value, | |||||
| "Trying to binary search an infinite range"); | |||||
| return (*this)(begin(rng), end(rng), val, std::move(pred), std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(binary_search) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::binary_search; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_COPY_HPP | |||||
| #define RANGES_V3_ALGORITHM_COPY_HPP | |||||
| #include <functional> | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/result_types.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/dangling.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/copy.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| template<typename I, typename O> | |||||
| using copy_result = detail::in_out_result<I, O>; | |||||
| RANGES_HIDDEN_DETAIL(namespace _copy CPP_PP_LBRACE()) | |||||
| RANGES_BEGIN_NIEBLOID(copy) | |||||
| /// \brief function template \c copy | |||||
| template<typename I, typename S, typename O> | |||||
| constexpr auto RANGES_FUN_NIEBLOID(copy)(I first, S last, O out) // | |||||
| ->CPP_ret(copy_result<I, O>)( // | |||||
| requires input_iterator<I> && sentinel_for<S, I> && | |||||
| weakly_incrementable<O> && indirectly_copyable<I, O>) | |||||
| { | |||||
| for(; first != last; ++first, ++out) | |||||
| *out = *first; | |||||
| return {first, out}; | |||||
| } // namespace ranges | |||||
| /// \overload | |||||
| template<typename Rng, typename O> | |||||
| constexpr auto RANGES_FUN_NIEBLOID(copy)(Rng && rng, O out) // | |||||
| ->CPP_ret(copy_result<safe_iterator_t<Rng>, O>)( // | |||||
| requires input_range<Rng> && weakly_incrementable<O> && | |||||
| indirectly_copyable<iterator_t<Rng>, O>) | |||||
| { | |||||
| return (*this)(begin(rng), end(rng), std::move(out)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(copy) | |||||
| RANGES_HIDDEN_DETAIL(CPP_PP_RBRACE()) | |||||
| #ifndef RANGES_DOXYGEN_INVOKED | |||||
| struct copy_fn | |||||
| : aux::copy_fn | |||||
| , _copy::copy_fn | |||||
| { | |||||
| using aux::copy_fn::operator(); | |||||
| using _copy::copy_fn::operator(); | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(copy_fn, copy) | |||||
| #endif | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::copy_result; | |||||
| using ranges::RANGES_HIDDEN_DETAIL(_copy::) copy; | |||||
| } // namespace cpp20 | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_COPY_BACKWARD_HPP | |||||
| #define RANGES_V3_ALGORITHM_COPY_BACKWARD_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/result_types.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/dangling.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| template<typename I, typename O> | |||||
| using copy_backward_result = detail::in_out_result<I, O>; | |||||
| RANGES_BEGIN_NIEBLOID(copy_backward) | |||||
| /// \brief function template \c copy_backward | |||||
| template<typename I, typename S, typename O> | |||||
| auto RANGES_FUN_NIEBLOID(copy_backward)(I first, S end_, O out) | |||||
| ->CPP_ret(copy_backward_result<I, O>)( // | |||||
| requires bidirectional_iterator<I> && sentinel_for<S, I> && | |||||
| bidirectional_iterator<O> && indirectly_copyable<I, O>) | |||||
| { | |||||
| I i = ranges::next(first, end_), last = i; | |||||
| while(first != i) | |||||
| *--out = *--i; | |||||
| return {last, out}; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename O> | |||||
| auto RANGES_FUN_NIEBLOID(copy_backward)(Rng && rng, O out) | |||||
| ->CPP_ret(copy_backward_result<safe_iterator_t<Rng>, O>)( // | |||||
| requires bidirectional_range<Rng> && bidirectional_iterator<O> && | |||||
| indirectly_copyable<iterator_t<Rng>, O>) | |||||
| { | |||||
| return (*this)(begin(rng), end(rng), std::move(out)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(copy_backward) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::copy_backward; | |||||
| using ranges::copy_backward_result; | |||||
| } // namespace cpp20 | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_COPY_IF_HPP | |||||
| #define RANGES_V3_ALGORITHM_COPY_IF_HPP | |||||
| #include <functional> | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/result_types.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/dangling.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| template<typename I, typename O> | |||||
| using copy_if_result = detail::in_out_result<I, O>; | |||||
| RANGES_BEGIN_NIEBLOID(copy_if) | |||||
| /// \brief function template \c copy_if | |||||
| template<typename I, typename S, typename O, typename F, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(copy_if)(I first, S last, O out, F pred, P proj = P{}) // | |||||
| ->CPP_ret(copy_if_result<I, O>)( // | |||||
| requires input_iterator<I> && sentinel_for<S, I> && | |||||
| weakly_incrementable<O> && indirect_unary_predicate<F, projected<I, P>> && | |||||
| indirectly_copyable<I, O>) | |||||
| { | |||||
| for(; first != last; ++first) | |||||
| { | |||||
| auto && x = *first; | |||||
| if(invoke(pred, invoke(proj, x))) | |||||
| { | |||||
| *out = (decltype(x) &&)x; | |||||
| ++out; | |||||
| } | |||||
| } | |||||
| return {first, out}; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename O, typename F, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(copy_if)(Rng && rng, O out, F pred, P proj = P{}) | |||||
| ->CPP_ret(copy_if_result<safe_iterator_t<Rng>, O>)( // | |||||
| requires input_range<Rng> && weakly_incrementable<O> && | |||||
| indirect_unary_predicate<F, projected<iterator_t<Rng>, P>> && | |||||
| indirectly_copyable<iterator_t<Rng>, O>) | |||||
| { | |||||
| return (*this)( | |||||
| begin(rng), end(rng), std::move(out), std::move(pred), std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(copy_if) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::copy_if; | |||||
| using ranges::copy_if_result; | |||||
| } // namespace cpp20 | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_COPY_N_HPP | |||||
| #define RANGES_V3_ALGORITHM_COPY_N_HPP | |||||
| #include <functional> | |||||
| #include <tuple> | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/result_types.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| template<typename I, typename O> | |||||
| using copy_n_result = detail::in_out_result<I, O>; | |||||
| RANGES_BEGIN_NIEBLOID(copy_n) | |||||
| /// \brief function template \c copy_n | |||||
| template<typename I, typename O, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(copy_n)(I first, iter_difference_t<I> n, O out) | |||||
| ->CPP_ret(copy_n_result<I, O>)( // | |||||
| requires input_iterator<I> && weakly_incrementable<O> && | |||||
| indirectly_copyable<I, O>) | |||||
| { | |||||
| RANGES_EXPECT(0 <= n); | |||||
| auto norig = n; | |||||
| auto b = uncounted(first); | |||||
| for(; n != 0; ++b, ++out, --n) | |||||
| *out = *b; | |||||
| return {recounted(first, b, norig), out}; | |||||
| } | |||||
| RANGES_END_NIEBLOID(copy_n) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::copy_n; | |||||
| using ranges::copy_n_result; | |||||
| } // namespace cpp20 | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_COUNT_HPP | |||||
| #define RANGES_V3_ALGORITHM_COUNT_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(count) | |||||
| /// \brief function template \c count | |||||
| template<typename I, typename S, typename V, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(count)(I first, S last, V const & val, P proj = P{}) | |||||
| ->CPP_ret(iter_difference_t<I>)( // | |||||
| requires input_iterator<I> && sentinel_for<S, I> && | |||||
| indirect_relation<equal_to, projected<I, P>, V const *>) | |||||
| { | |||||
| iter_difference_t<I> n = 0; | |||||
| for(; first != last; ++first) | |||||
| if(invoke(proj, *first) == val) | |||||
| ++n; | |||||
| return n; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename V, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(count)(Rng && rng, V const & val, P proj = P{}) | |||||
| ->CPP_ret(iter_difference_t<iterator_t<Rng>>)( // | |||||
| requires input_range<Rng> && | |||||
| indirect_relation<equal_to, projected<iterator_t<Rng>, P>, V const *>) | |||||
| { | |||||
| return (*this)(begin(rng), end(rng), val, std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(count) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::count; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_COUNT_IF_HPP | |||||
| #define RANGES_V3_ALGORITHM_COUNT_IF_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(count_if) | |||||
| /// \brief function template \c count_if | |||||
| template<typename I, typename S, typename R, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(count_if)(I first, S last, R pred, P proj = P{}) | |||||
| ->CPP_ret(iter_difference_t<I>)( // | |||||
| requires input_iterator<I> && sentinel_for<S, I> && | |||||
| indirect_unary_predicate<R, projected<I, P>>) | |||||
| { | |||||
| iter_difference_t<I> n = 0; | |||||
| for(; first != last; ++first) | |||||
| if(invoke(pred, invoke(proj, *first))) | |||||
| ++n; | |||||
| return n; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename R, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(count_if)(Rng && rng, R pred, P proj = P{}) | |||||
| ->CPP_ret(iter_difference_t<iterator_t<Rng>>)( // | |||||
| requires input_range<Rng> && | |||||
| indirect_unary_predicate<R, projected<iterator_t<Rng>, P>>) | |||||
| { | |||||
| return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(count_if) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::count_if; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Johel Guerrero 2019 | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 0.0. (See accompanying | |||||
| // file LICENSE_0_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_0_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_ENDS_WITH_HPP | |||||
| #define RANGES_V3_ALGORITHM_ENDS_WITH_HPP | |||||
| #include <utility> | |||||
| #include <concepts/concepts.hpp> | |||||
| #include <range/v3/algorithm/equal.hpp> | |||||
| #include <range/v3/detail/config.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(ends_with) | |||||
| /// \brief function template \c ends_with | |||||
| template<typename I0, | |||||
| typename S0, | |||||
| typename I1, | |||||
| typename S1, | |||||
| typename C = equal_to, | |||||
| typename P0 = identity, | |||||
| typename P1 = identity> | |||||
| constexpr auto RANGES_FUN_NIEBLOID(ends_with)(I0 begin0, | |||||
| S0 end0, | |||||
| I1 begin1, | |||||
| S1 end1, | |||||
| C pred = C{}, | |||||
| P0 proj0 = P0{}, | |||||
| P1 proj1 = P1{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires((forward_iterator<I0> && sentinel_for<S0, I0>) || | |||||
| (input_iterator<I0> && sized_sentinel_for<S0, I0>)) && | |||||
| ((forward_iterator<I1> && sentinel_for<S1, I1>) || | |||||
| (input_iterator<I1> && sized_sentinel_for<S1, I1>)) && | |||||
| indirectly_comparable<I0, I1, C, P0, P1>) | |||||
| { | |||||
| const auto drop = distance(begin0, end0) - distance(begin1, end1); | |||||
| if(drop < 0) | |||||
| return false; | |||||
| return equal(next(std::move(begin0), drop), | |||||
| std::move(end0), | |||||
| std::move(begin1), | |||||
| std::move(end1), | |||||
| std::move(pred), | |||||
| std::move(proj0), | |||||
| std::move(proj1)); | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng0, | |||||
| typename Rng1, | |||||
| typename C = equal_to, | |||||
| typename P0 = identity, | |||||
| typename P1 = identity> | |||||
| constexpr auto RANGES_FUN_NIEBLOID(ends_with)( | |||||
| Rng0 && rng0, Rng1 && rng1, C pred = C{}, P0 proj0 = P0{}, P1 proj1 = P1{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires(forward_range<Rng0> || | |||||
| (input_range<Rng0> && sized_range<Rng0>)) && | |||||
| (forward_range<Rng1> || (input_range<Rng1> && sized_range<Rng1>)) && | |||||
| indirectly_comparable<iterator_t<Rng0>, iterator_t<Rng1>, C, P0, P1>) | |||||
| { | |||||
| const auto drop = distance(rng0) - distance(rng1); | |||||
| if(drop < 0) | |||||
| return false; | |||||
| return equal(next(begin(rng0), drop), | |||||
| end(rng0), | |||||
| begin(rng1), | |||||
| end(rng1), | |||||
| std::move(pred), | |||||
| std::move(proj0), | |||||
| std::move(proj1)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(ends_with) | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 0.0. (See accompanying | |||||
| // file LICENSE_0_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_0_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_EQUAL_HPP | |||||
| #define RANGES_V3_ALGORITHM_EQUAL_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| /// \cond | |||||
| namespace detail | |||||
| { | |||||
| template<typename I0, typename S0, typename I1, typename S1, typename C, | |||||
| typename P0, typename P1> | |||||
| constexpr bool equal_nocheck(I0 begin0, S0 end0, I1 begin1, S1 end1, C pred, | |||||
| P0 proj0, P1 proj1) | |||||
| { | |||||
| for(; begin0 != end0 && begin1 != end1; ++begin0, ++begin1) | |||||
| if(!invoke(pred, invoke(proj0, *begin0), invoke(proj1, *begin1))) | |||||
| return false; | |||||
| return begin0 == end0 && begin1 == end1; | |||||
| } | |||||
| } // namespace detail | |||||
| /// \endcond | |||||
| RANGES_BEGIN_NIEBLOID(equal) | |||||
| /// \brief function template \c equal | |||||
| template<typename I0, | |||||
| typename S0, | |||||
| typename I1, | |||||
| typename C = equal_to, | |||||
| typename P0 = identity, | |||||
| typename P1 = identity> | |||||
| RANGES_DEPRECATED( | |||||
| "Use the variant of ranges::equal that takes an upper bound for " | |||||
| "both sequences") | |||||
| constexpr auto RANGES_FUN_NIEBLOID(equal)(I0 begin0, | |||||
| S0 end0, | |||||
| I1 begin1, | |||||
| C pred = C{}, | |||||
| P0 proj0 = P0{}, | |||||
| P1 proj1 = P1{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires input_iterator<I0> && sentinel_for<S0, I0> && | |||||
| input_iterator<I1> && indirectly_comparable<I0, I1, C, P0, P1>) | |||||
| { | |||||
| for(; begin0 != end0; ++begin0, ++begin1) | |||||
| if(!invoke(pred, invoke(proj0, *begin0), invoke(proj1, *begin1))) | |||||
| return false; | |||||
| return true; | |||||
| } | |||||
| /// \overload | |||||
| template<typename I0, | |||||
| typename S0, | |||||
| typename I1, | |||||
| typename S1, | |||||
| typename C = equal_to, | |||||
| typename P0 = identity, | |||||
| typename P1 = identity> | |||||
| constexpr auto RANGES_FUN_NIEBLOID(equal)(I0 begin0, | |||||
| S0 end0, | |||||
| I1 begin1, | |||||
| S1 end1, | |||||
| C pred = C{}, | |||||
| P0 proj0 = P0{}, | |||||
| P1 proj1 = P1{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires input_iterator<I0> && sentinel_for<S0, I0> && | |||||
| input_iterator<I1> && sentinel_for<S1, I1> && | |||||
| indirectly_comparable<I0, I1, C, P0, P1>) | |||||
| { | |||||
| if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S0, I0> && | |||||
| sized_sentinel_for<S1, I1>)) | |||||
| if(distance(begin0, end0) != distance(begin1, end1)) | |||||
| return false; | |||||
| return detail::equal_nocheck(std::move(begin0), | |||||
| std::move(end0), | |||||
| std::move(begin1), | |||||
| std::move(end1), | |||||
| std::move(pred), | |||||
| std::move(proj0), | |||||
| std::move(proj1)); | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng0, | |||||
| typename I1Ref, | |||||
| typename C = equal_to, | |||||
| typename P0 = identity, | |||||
| typename P1 = identity> | |||||
| RANGES_DEPRECATED( | |||||
| "Use the variant of ranges::equal that takes an upper bound for " | |||||
| "both sequences") | |||||
| constexpr auto RANGES_FUN_NIEBLOID(equal)(Rng0 && rng0, | |||||
| I1Ref && begin1, | |||||
| C pred = C{}, | |||||
| P0 proj0 = P0{}, | |||||
| P1 proj1 = P1{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires input_range<Rng0> && input_iterator<uncvref_t<I1Ref>> && | |||||
| indirectly_comparable<iterator_t<Rng0>, uncvref_t<I1Ref>, C, P0, P1>) | |||||
| { | |||||
| RANGES_DIAGNOSTIC_PUSH | |||||
| RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS | |||||
| return (*this)(begin(rng0), | |||||
| end(rng0), | |||||
| (I1Ref &&) begin1, | |||||
| std::move(pred), | |||||
| std::move(proj0), | |||||
| std::move(proj1)); | |||||
| RANGES_DIAGNOSTIC_POP | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng0, | |||||
| typename Rng1, | |||||
| typename C = equal_to, | |||||
| typename P0 = identity, | |||||
| typename P1 = identity> | |||||
| constexpr auto RANGES_FUN_NIEBLOID(equal)( | |||||
| Rng0 && rng0, Rng1 && rng1, C pred = C{}, P0 proj0 = P0{}, P1 proj1 = P1{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires input_range<Rng0> && input_range<Rng1> && | |||||
| indirectly_comparable<iterator_t<Rng0>, iterator_t<Rng1>, C, P0, P1>) | |||||
| { | |||||
| if(RANGES_CONSTEXPR_IF(sized_range<Rng0> && sized_range<Rng1>)) | |||||
| if(distance(rng0) != distance(rng1)) | |||||
| return false; | |||||
| return detail::equal_nocheck(begin(rng0), | |||||
| end(rng0), | |||||
| begin(rng1), | |||||
| end(rng1), | |||||
| std::move(pred), | |||||
| std::move(proj0), | |||||
| std::move(proj1)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(equal) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::equal; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // Copyright Casey Carter 2016 | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_EQUAL_RANGE_HPP | |||||
| #define RANGES_V3_ALGORITHM_EQUAL_RANGE_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/aux_/equal_range_n.hpp> | |||||
| #include <range/v3/algorithm/aux_/lower_bound_n.hpp> | |||||
| #include <range/v3/algorithm/upper_bound.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| #include <range/v3/view/subrange.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(equal_range) | |||||
| /// \brief function template \c equal_range | |||||
| template<typename I, | |||||
| typename S, | |||||
| typename V, | |||||
| typename C = less, | |||||
| typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(equal_range)( | |||||
| I first, S last, V const & val, C pred = C{}, P proj = P{}) | |||||
| ->CPP_ret(subrange<I>)( // | |||||
| requires forward_iterator<I> && sentinel_for<S, I> && | |||||
| indirect_strict_weak_order<C, V const *, projected<I, P>>) | |||||
| { | |||||
| if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S, I>)) | |||||
| { | |||||
| auto const len = distance(first, last); | |||||
| return aux::equal_range_n( | |||||
| std::move(first), len, val, std::move(pred), std::move(proj)); | |||||
| } | |||||
| // Probe exponentially for either end-of-range, an iterator that | |||||
| // is past the equal range (i.e., denotes an element greater | |||||
| // than val), or is in the equal range (denotes an element equal | |||||
| // to val). | |||||
| auto dist = iter_difference_t<I>{1}; | |||||
| while(true) | |||||
| { | |||||
| auto mid = first; | |||||
| auto d = advance(mid, dist, last); | |||||
| if(d || mid == last) | |||||
| { | |||||
| // at the end of the input range | |||||
| dist -= d; | |||||
| return aux::equal_range_n( | |||||
| std::move(first), dist, val, std::ref(pred), std::ref(proj)); | |||||
| } | |||||
| // if val < *mid, mid is after the target range. | |||||
| auto && v = *mid; | |||||
| auto && pv = invoke(proj, (decltype(v) &&)v); | |||||
| if(invoke(pred, val, pv)) | |||||
| { | |||||
| return aux::equal_range_n( | |||||
| std::move(first), dist, val, std::ref(pred), std::ref(proj)); | |||||
| } | |||||
| else if(!invoke(pred, pv, val)) | |||||
| { | |||||
| // *mid == val: the lower bound is <= mid, and the upper bound is > | |||||
| // mid. | |||||
| return { | |||||
| aux::lower_bound_n( | |||||
| std::move(first), dist, val, std::ref(pred), std::ref(proj)), | |||||
| upper_bound(std::move(mid), | |||||
| std::move(last), | |||||
| val, | |||||
| std::ref(pred), | |||||
| std::ref(proj))}; | |||||
| } | |||||
| // *mid < val, mid is before the target range. | |||||
| first = std::move(mid); | |||||
| ++first; | |||||
| dist *= 2; | |||||
| } | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename V, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(equal_range)( | |||||
| Rng && rng, V const & val, C pred = C{}, P proj = P{}) // | |||||
| ->CPP_ret(safe_subrange_t<Rng>)( // | |||||
| requires forward_range<Rng> && | |||||
| indirect_strict_weak_order<C, V const *, projected<iterator_t<Rng>, P>>) | |||||
| { | |||||
| if(RANGES_CONSTEXPR_IF(sized_range<Rng>)) | |||||
| { | |||||
| auto const len = distance(rng); | |||||
| return aux::equal_range_n( | |||||
| begin(rng), len, val, std::move(pred), std::move(proj)); | |||||
| } | |||||
| return (*this)(begin(rng), end(rng), val, std::move(pred), std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(equal_range) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::equal_range; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_FILL_HPP | |||||
| #define RANGES_V3_ALGORITHM_FILL_HPP | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/dangling.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(fill) | |||||
| /// \brief function template \c fill | |||||
| template<typename O, typename S, typename V> | |||||
| auto RANGES_FUN_NIEBLOID(fill)(O first, S last, V const & val) // | |||||
| ->CPP_ret(O)( // | |||||
| requires output_iterator<O, V const &> && sentinel_for<S, O>) | |||||
| { | |||||
| for(; first != last; ++first) | |||||
| *first = val; | |||||
| return first; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename V> | |||||
| auto RANGES_FUN_NIEBLOID(fill)(Rng && rng, V const & val) | |||||
| ->CPP_ret(safe_iterator_t<Rng>)( // | |||||
| requires output_range<Rng, V const &>) | |||||
| { | |||||
| return (*this)(begin(rng), end(rng), val); | |||||
| } | |||||
| RANGES_END_NIEBLOID(fill) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::fill; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_FILL_N_HPP | |||||
| #define RANGES_V3_ALGORITHM_FILL_N_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(fill_n) | |||||
| /// \brief function template \c equal | |||||
| template<typename O, typename V> | |||||
| auto RANGES_FUN_NIEBLOID(fill_n)(O first, iter_difference_t<O> n, V const & val) | |||||
| ->CPP_ret(O)( // | |||||
| requires output_iterator<O, V const &>) | |||||
| { | |||||
| RANGES_EXPECT(n >= 0); | |||||
| auto norig = n; | |||||
| auto b = uncounted(first); | |||||
| for(; n != 0; ++b, --n) | |||||
| *b = val; | |||||
| return recounted(first, b, norig); | |||||
| } | |||||
| RANGES_END_NIEBLOID(fill_n) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::fill_n; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_FIND_HPP | |||||
| #define RANGES_V3_ALGORITHM_FIND_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/dangling.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(find) | |||||
| /// \brief template function \c find | |||||
| /// | |||||
| /// range-based version of the \c find std algorithm | |||||
| /// | |||||
| /// \pre `Rng` is a model of the `Range` concept | |||||
| /// \pre `I` is a model of the `input_iterator` concept | |||||
| /// \pre `S` is a model of the `sentinel_for<I>` concept | |||||
| /// \pre `P` is a model of the `invocable<iter_common_reference_t<I>>` concept | |||||
| /// \pre The ResultType of `P` is equality_comparable with V | |||||
| template<typename I, typename S, typename V, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(find)(I first, S last, V const & val, P proj = P{}) | |||||
| ->CPP_ret(I)( // | |||||
| requires input_iterator<I> && sentinel_for<S, I> && | |||||
| indirect_relation<equal_to, projected<I, P>, V const *>) | |||||
| { | |||||
| for(; first != last; ++first) | |||||
| if(invoke(proj, *first) == val) | |||||
| break; | |||||
| return first; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename V, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(find)(Rng && rng, V const & val, P proj = P{}) | |||||
| ->CPP_ret(safe_iterator_t<Rng>)( // | |||||
| requires input_range<Rng> && | |||||
| indirect_relation<equal_to, projected<iterator_t<Rng>, P>, V const *>) | |||||
| { | |||||
| return (*this)(begin(rng), end(rng), val, std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(find) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::find; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_FIND_END_HPP | |||||
| #define RANGES_V3_ALGORITHM_FIND_END_HPP | |||||
| #include <utility> | |||||
| #include <meta/meta.hpp> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| #include <range/v3/view/subrange.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \cond | |||||
| namespace detail | |||||
| { | |||||
| template<typename I, typename S> | |||||
| auto next_to_if(I i, S s, std::true_type) -> CPP_ret(I)( // | |||||
| requires input_iterator<I> && sentinel_for<S, I>) | |||||
| { | |||||
| return ranges::next(i, s); | |||||
| } | |||||
| template<typename I, typename S> | |||||
| auto next_to_if(I, S s, std::false_type) -> CPP_ret(S)( // | |||||
| requires input_iterator<I> && sentinel_for<S, I>) | |||||
| { | |||||
| return s; | |||||
| } | |||||
| template<bool B, typename I, typename S> | |||||
| auto next_to_if(I i, S s) -> CPP_ret(meta::if_c<B, I, S>)( // | |||||
| requires input_iterator<I> && sentinel_for<S, I>) | |||||
| { | |||||
| return detail::next_to_if(std::move(i), std::move(s), meta::bool_<B>{}); | |||||
| } | |||||
| template<typename I1, typename S1, typename I2, typename S2, typename R, | |||||
| typename P> | |||||
| subrange<I1> find_end_impl(I1 begin1, S1 end1, I2 begin2, S2 end2, R pred, P proj, | |||||
| detail::forward_iterator_tag_, | |||||
| detail::forward_iterator_tag_) | |||||
| { | |||||
| bool found = false; | |||||
| I1 res_begin, res_end; | |||||
| if(begin2 == end2) | |||||
| { | |||||
| auto e1 = ranges::next(begin1, end1); | |||||
| return {e1, e1}; | |||||
| } | |||||
| while(true) | |||||
| { | |||||
| while(true) | |||||
| { | |||||
| if(begin1 == end1) | |||||
| return {(found ? res_begin : begin1), (found ? res_end : begin1)}; | |||||
| if(invoke(pred, invoke(proj, *begin1), *begin2)) | |||||
| break; | |||||
| ++begin1; | |||||
| } | |||||
| auto tmp1 = begin1; | |||||
| auto tmp2 = begin2; | |||||
| while(true) | |||||
| { | |||||
| if(++tmp2 == end2) | |||||
| { | |||||
| res_begin = begin1++; | |||||
| res_end = ++tmp1; | |||||
| found = true; | |||||
| break; | |||||
| } | |||||
| if(++tmp1 == end1) | |||||
| return {(found ? res_begin : tmp1), (found ? res_end : tmp1)}; | |||||
| if(!invoke(pred, invoke(proj, *tmp1), *tmp2)) | |||||
| { | |||||
| ++begin1; | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| template<typename I1, typename I2, typename R, typename P> | |||||
| subrange<I1> find_end_impl(I1 begin1, I1 end1, I2 begin2, I2 end2, R pred, P proj, | |||||
| detail::bidirectional_iterator_tag_, | |||||
| detail::bidirectional_iterator_tag_) | |||||
| { | |||||
| // modeled after search algorithm (in reverse) | |||||
| if(begin2 == end2) | |||||
| return {end1, end1}; // Everything matches an empty sequence | |||||
| I1 l1 = end1; | |||||
| I2 l2 = end2; | |||||
| --l2; | |||||
| while(true) | |||||
| { | |||||
| // Find end element in sequence 1 that matches *(end2-1), with a mininum | |||||
| // of loop checks | |||||
| do | |||||
| // return {end1,end1} if no element matches *begin2 | |||||
| if(begin1 == l1) | |||||
| return {end1, end1}; | |||||
| while(!invoke(pred, invoke(proj, *--l1), *l2)); | |||||
| // *l1 matches *l2, now match elements before here | |||||
| I1 m1 = l1; | |||||
| I2 m2 = l2; | |||||
| do | |||||
| // If pattern exhausted, {m1,++l1} is the answer | |||||
| // (works for 1 element pattern) | |||||
| if(m2 == begin2) | |||||
| return {m1, ++l1}; | |||||
| // Otherwise if source exhausted, pattern not found | |||||
| else if(m1 == begin1) | |||||
| return {end1, end1}; | |||||
| // if there is a mismatch, restart with a new l1 | |||||
| // else there is a match, check next elements | |||||
| while(invoke(pred, invoke(proj, *--m1), *--m2)); | |||||
| } | |||||
| } | |||||
| template<typename I1, typename I2, typename R, typename P> | |||||
| subrange<I1> find_end_impl(I1 begin1, I1 end1, I2 begin2, I2 end2, R pred, P proj, | |||||
| detail::random_access_iterator_tag_, | |||||
| detail::random_access_iterator_tag_) | |||||
| { | |||||
| // Take advantage of knowing source and pattern lengths. Stop short when | |||||
| // source is smaller than pattern | |||||
| auto len2 = end2 - begin2; | |||||
| if(len2 == 0) | |||||
| return {end1, end1}; | |||||
| auto len1 = end1 - begin1; | |||||
| if(len1 < len2) | |||||
| return {end1, end1}; | |||||
| I1 const start = | |||||
| begin1 + (len2 - 1); // End of pattern match can't go before here | |||||
| I1 l1 = end1; | |||||
| I2 l2 = end2; | |||||
| --l2; | |||||
| while(true) | |||||
| { | |||||
| do | |||||
| if(start == l1) | |||||
| return {end1, end1}; | |||||
| while(!invoke(pred, invoke(proj, *--l1), *l2)); | |||||
| I1 m1 = l1; | |||||
| I2 m2 = l2; | |||||
| do | |||||
| if(m2 == begin2) | |||||
| return {m1, ++l1}; | |||||
| // no need to check range on m1 because s guarantees we have enough source | |||||
| while(invoke(pred, invoke(proj, *--m1), *--m2)); | |||||
| } | |||||
| } | |||||
| } // namespace detail | |||||
| /// \endcond | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(find_end) | |||||
| /// \brief function template \c find_end | |||||
| template<typename I1, | |||||
| typename S1, | |||||
| typename I2, | |||||
| typename S2, | |||||
| typename R = equal_to, | |||||
| typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(find_end)( | |||||
| I1 begin1, S1 end1, I2 begin2, S2 end2, R pred = R{}, P proj = P{}) // | |||||
| ->CPP_ret(subrange<I1>)( // | |||||
| requires forward_iterator<I1> && sentinel_for<S1, I1> && | |||||
| forward_iterator<I2> && sentinel_for<S2, I2> && | |||||
| indirect_relation<R, projected<I1, P>, I2>) | |||||
| { | |||||
| constexpr bool Bidi = | |||||
| bidirectional_iterator<I1> && bidirectional_iterator<I2>; | |||||
| return detail::find_end_impl(begin1, | |||||
| detail::next_to_if<Bidi>(begin1, end1), | |||||
| begin2, | |||||
| detail::next_to_if<Bidi>(begin2, end2), | |||||
| std::move(pred), | |||||
| std::move(proj), | |||||
| iterator_tag_of<I1>(), | |||||
| iterator_tag_of<I2>()); | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng1, | |||||
| typename Rng2, | |||||
| typename R = equal_to, | |||||
| typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(find_end)( | |||||
| Rng1 && rng1, Rng2 && rng2, R pred = R{}, P proj = P{}) // | |||||
| ->CPP_ret(safe_subrange_t<Rng1>)( // | |||||
| requires forward_range<Rng1> && forward_range<Rng2> && | |||||
| indirect_relation<R, projected<iterator_t<Rng1>, P>, iterator_t<Rng2>>) | |||||
| { | |||||
| return (*this)(begin(rng1), | |||||
| end(rng1), | |||||
| begin(rng2), | |||||
| end(rng2), | |||||
| std::move(pred), | |||||
| std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(find_end) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::find_end; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 0.0. (See accompanying | |||||
| // file LICENSE_0_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_0_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_FIND_FIRST_OF_HPP | |||||
| #define RANGES_V3_ALGORITHM_FIND_FIRST_OF_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/dangling.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(find_first_of) | |||||
| // Rationale: return I0 instead of pair<I0,I1> because find_first_of need | |||||
| // not actually compute the end of [I1,S0); therefore, it is not necessarily | |||||
| // losing information. E.g., if begin0 == end0, we can return begin0 immediately. | |||||
| // If we returned pair<I0,I1>, we would need to do an O(N) scan to find the | |||||
| // end position. | |||||
| /// \brief function template \c find_first_of | |||||
| template<typename I0, | |||||
| typename S0, | |||||
| typename I1, | |||||
| typename S1, | |||||
| typename R = equal_to, | |||||
| typename P0 = identity, | |||||
| typename P1 = identity> | |||||
| constexpr auto RANGES_FUN_NIEBLOID(find_first_of)(I0 begin0, | |||||
| S0 end0, | |||||
| I1 begin1, | |||||
| S1 end1, | |||||
| R pred = R{}, | |||||
| P0 proj0 = P0{}, | |||||
| P1 proj1 = P1{}) // | |||||
| ->CPP_ret(I0)( // | |||||
| requires input_iterator<I0> && sentinel_for<S0, I0> && | |||||
| forward_iterator<I1> && sentinel_for<S1, I1> && | |||||
| indirect_relation<R, projected<I0, P0>, projected<I1, P1>>) | |||||
| { | |||||
| for(; begin0 != end0; ++begin0) | |||||
| for(auto tmp = begin1; tmp != end1; ++tmp) | |||||
| if(invoke(pred, invoke(proj0, *begin0), invoke(proj1, *tmp))) | |||||
| return begin0; | |||||
| return begin0; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng0, | |||||
| typename Rng1, | |||||
| typename R = equal_to, | |||||
| typename P0 = identity, | |||||
| typename P1 = identity> | |||||
| constexpr auto RANGES_FUN_NIEBLOID(find_first_of)( | |||||
| Rng0 && rng0, Rng1 && rng1, R pred = R{}, P0 proj0 = P0{}, P1 proj1 = P1{}) // | |||||
| ->CPP_ret(safe_iterator_t<Rng0>)( // | |||||
| requires input_range<Rng0> && forward_range<Rng1> && | |||||
| indirect_relation<R, | |||||
| projected<iterator_t<Rng0>, P0>, | |||||
| projected<iterator_t<Rng1>, P1>>) | |||||
| { | |||||
| return (*this)(begin(rng0), | |||||
| end(rng0), | |||||
| begin(rng1), | |||||
| end(rng1), | |||||
| std::move(pred), | |||||
| std::move(proj0), | |||||
| std::move(proj1)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(find_first_of) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::find_first_of; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_FIND_IF_HPP | |||||
| #define RANGES_V3_ALGORITHM_FIND_IF_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/dangling.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(find_if) | |||||
| /// \brief template function \c find | |||||
| /// | |||||
| /// range-based version of the \c find std algorithm | |||||
| /// | |||||
| /// \pre `Rng` is a model of the `Range` concept | |||||
| /// \pre `I` is a model of the `input_iterator` concept | |||||
| /// \pre `S` is a model of the `sentinel_for<I>` concept | |||||
| /// \pre `P` is a model of the `invocable<V>` concept, where `V` is the | |||||
| /// value type of I. | |||||
| /// \pre `F` models `predicate<X>`, where `X` is the result type | |||||
| /// of `invocable<P, V>` | |||||
| template<typename I, typename S, typename F, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(find_if)(I first, S last, F pred, P proj = P{}) // | |||||
| ->CPP_ret(I)( // | |||||
| requires input_iterator<I> && sentinel_for<S, I> && | |||||
| indirect_unary_predicate<F, projected<I, P>>) | |||||
| { | |||||
| for(; first != last; ++first) | |||||
| if(invoke(pred, invoke(proj, *first))) | |||||
| break; | |||||
| return first; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename F, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(find_if)(Rng && rng, F pred, P proj = P{}) | |||||
| ->CPP_ret(safe_iterator_t<Rng>)( // | |||||
| requires input_range<Rng> && | |||||
| indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>) | |||||
| { | |||||
| return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(find_if) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::find_if; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2013-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_FIND_IF_NOT_HPP | |||||
| #define RANGES_V3_ALGORITHM_FIND_IF_NOT_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/dangling.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(find_if_not) | |||||
| /// \brief template function \c find_if_not | |||||
| /// | |||||
| /// range-based version of the \c find_if_not std algorithm | |||||
| /// | |||||
| /// \pre `Rng` is a model of the `Range` concept | |||||
| /// \pre `I` is a model of the `input_iterator` concept | |||||
| /// \pre `S` is a model of the `sentinel_for<I>` concept | |||||
| /// \pre `P` is a model of the `invocable<V>` concept, where `V` is the | |||||
| /// value type of I. | |||||
| /// \pre `F` models `predicate<X>`, where `X` is the result type | |||||
| /// of `invocable<P, V>` | |||||
| template<typename I, typename S, typename F, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(find_if_not)(I first, S last, F pred, P proj = P{}) // | |||||
| ->CPP_ret(I)( // | |||||
| requires input_iterator<I> && sentinel_for<S, I> && | |||||
| indirect_unary_predicate<F, projected<I, P>>) | |||||
| { | |||||
| for(; first != last; ++first) | |||||
| if(!invoke(pred, invoke(proj, *first))) | |||||
| break; | |||||
| return first; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename F, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(find_if_not)(Rng && rng, F pred, P proj = P{}) | |||||
| ->CPP_ret(safe_iterator_t<Rng>)( // | |||||
| requires input_range<Rng> && | |||||
| indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>) | |||||
| { | |||||
| return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(find_if_not) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::find_if_not; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_FOR_EACH_HPP | |||||
| #define RANGES_V3_ALGORITHM_FOR_EACH_HPP | |||||
| #include <functional> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/result_types.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/functional/reference_wrapper.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/dangling.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| template<typename I, typename F> | |||||
| using for_each_result = detail::in_fun_result<I, F>; | |||||
| RANGES_BEGIN_NIEBLOID(for_each) | |||||
| /// \brief function template \c for_each | |||||
| template<typename I, typename S, typename F, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(for_each)(I first, S last, F fun, P proj = P{}) | |||||
| ->CPP_ret(for_each_result<I, F>)( // | |||||
| requires input_iterator<I> && sentinel_for<S, I> && | |||||
| indirectly_unary_invocable<F, projected<I, P>>) | |||||
| { | |||||
| for(; first != last; ++first) | |||||
| { | |||||
| invoke(fun, invoke(proj, *first)); | |||||
| } | |||||
| return {detail::move(first), detail::move(fun)}; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename F, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(for_each)(Rng && rng, F fun, P proj = P{}) | |||||
| ->CPP_ret(for_each_result<safe_iterator_t<Rng>, F>)( // | |||||
| requires input_range<Rng> && | |||||
| indirectly_unary_invocable<F, projected<iterator_t<Rng>, P>>) | |||||
| { | |||||
| return {(*this)(begin(rng), end(rng), ref(fun), detail::move(proj)).in, | |||||
| detail::move(fun)}; | |||||
| } | |||||
| RANGES_END_NIEBLOID(for_each) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::for_each; | |||||
| using ranges::for_each_result; | |||||
| } // namespace cpp20 | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // Copyright Rostislav Khlebnikov 2017 | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_FOR_EACH_N_HPP | |||||
| #define RANGES_V3_ALGORITHM_FOR_EACH_N_HPP | |||||
| #include <functional> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/result_types.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/dangling.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(for_each_n) | |||||
| /// \brief function template \c for_each_n | |||||
| template<typename I, typename F, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(for_each_n)( | |||||
| I first, iter_difference_t<I> n, F fun, P proj = P{}) // | |||||
| ->CPP_ret(I)( // | |||||
| requires input_iterator<I> && | |||||
| indirectly_unary_invocable<F, projected<I, P>>) | |||||
| { | |||||
| RANGES_EXPECT(0 <= n); | |||||
| auto norig = n; | |||||
| auto b = uncounted(first); | |||||
| for(; 0 < n; ++b, --n) | |||||
| invoke(fun, invoke(proj, *b)); | |||||
| return recounted(first, b, norig); | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename F, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(for_each_n)( | |||||
| Rng && rng, range_difference_t<Rng> n, F fun, P proj = P{}) | |||||
| ->CPP_ret(safe_iterator_t<Rng>)( // | |||||
| requires input_range<Rng> && | |||||
| indirectly_unary_invocable<F, projected<iterator_t<Rng>, P>>) | |||||
| { | |||||
| if(sized_range<Rng>) | |||||
| RANGES_EXPECT(n <= distance(rng)); | |||||
| return (*this)(begin(rng), n, detail::move(fun), detail::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(for_each_n) | |||||
| // Not yet! | |||||
| // namespace cpp20 | |||||
| // { | |||||
| // using ranges::for_each_n; | |||||
| // } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_GENERATE_HPP | |||||
| #define RANGES_V3_ALGORITHM_GENERATE_HPP | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/result_types.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/functional/reference_wrapper.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/dangling.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| template<typename O, typename F> | |||||
| using generate_result = detail::out_fun_result<O, F>; | |||||
| RANGES_BEGIN_NIEBLOID(generate) | |||||
| /// \brief function template \c generate_n | |||||
| template<typename O, typename S, typename F> | |||||
| auto RANGES_FUN_NIEBLOID(generate)(O first, S last, F fun) // | |||||
| ->CPP_ret(generate_result<O, F>)( // | |||||
| requires invocable<F &> && output_iterator<O, invoke_result_t<F &>> && | |||||
| sentinel_for<S, O>) | |||||
| { | |||||
| for(; first != last; ++first) | |||||
| *first = invoke(fun); | |||||
| return {detail::move(first), detail::move(fun)}; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename F> | |||||
| auto RANGES_FUN_NIEBLOID(generate)(Rng && rng, F fun) | |||||
| ->CPP_ret(generate_result<safe_iterator_t<Rng>, F>)( // | |||||
| requires invocable<F &> && output_range<Rng, invoke_result_t<F &>>) | |||||
| { | |||||
| return {(*this)(begin(rng), end(rng), ref(fun)).out, detail::move(fun)}; | |||||
| } | |||||
| RANGES_END_NIEBLOID(generate) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::generate; | |||||
| using ranges::generate_result; | |||||
| } // namespace cpp20 | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| #ifndef RANGES_V3_ALGORITHM_GENERATE_N_HPP | |||||
| #define RANGES_V3_ALGORITHM_GENERATE_N_HPP | |||||
| #include <tuple> | |||||
| #include <utility> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/result_types.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| template<typename O, typename F> | |||||
| using generate_n_result = detail::out_fun_result<O, F>; | |||||
| RANGES_BEGIN_NIEBLOID(generate_n) | |||||
| /// \brief function template \c generate_n | |||||
| template<typename O, typename F> | |||||
| auto RANGES_FUN_NIEBLOID(generate_n)(O first, iter_difference_t<O> n, F fun) | |||||
| ->CPP_ret(generate_n_result<O, F>)( // | |||||
| requires invocable<F &> && output_iterator<O, invoke_result_t<F &>>) | |||||
| { | |||||
| RANGES_EXPECT(n >= 0); | |||||
| auto norig = n; | |||||
| auto b = uncounted(first); | |||||
| for(; 0 != n; ++b, --n) | |||||
| *b = invoke(fun); | |||||
| return {recounted(first, b, norig), detail::move(fun)}; | |||||
| } | |||||
| RANGES_END_NIEBLOID(generate_n) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::generate_n; | |||||
| using ranges::generate_n_result; | |||||
| } // namespace cpp20 | |||||
| // @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| //===----------------------------------------------------------------------===// | |||||
| // | |||||
| // The LLVM Compiler Infrastructure | |||||
| // | |||||
| // This file is dual licensed under the MIT and the University of Illinois Open | |||||
| // Source Licenses. See LICENSE.TXT for details. | |||||
| // | |||||
| //===----------------------------------------------------------------------===// | |||||
| #ifndef RANGES_V3_ALGORITHM_HEAP_ALGORITHM_HPP | |||||
| #define RANGES_V3_ALGORITHM_HEAP_ALGORITHM_HPP | |||||
| #include <functional> | |||||
| #include <meta/meta.hpp> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/dangling.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \cond | |||||
| namespace detail | |||||
| { | |||||
| struct is_heap_until_n_fn | |||||
| { | |||||
| template<typename I, typename C = less, typename P = identity> | |||||
| auto operator()(I const begin_, iter_difference_t<I> const n_, C pred = C{}, | |||||
| P proj = P{}) const -> CPP_ret(I)( // | |||||
| requires random_access_iterator<I> && | |||||
| indirect_strict_weak_order<C, projected<I, P>>) | |||||
| { | |||||
| RANGES_EXPECT(0 <= n_); | |||||
| iter_difference_t<I> p = 0, c = 1; | |||||
| I pp = begin_; | |||||
| while(c < n_) | |||||
| { | |||||
| I cp = begin_ + c; | |||||
| if(invoke(pred, invoke(proj, *pp), invoke(proj, *cp))) | |||||
| return cp; | |||||
| ++c; | |||||
| ++cp; | |||||
| if(c == n_ || invoke(pred, invoke(proj, *pp), invoke(proj, *cp))) | |||||
| return cp; | |||||
| ++p; | |||||
| ++pp; | |||||
| c = 2 * p + 1; | |||||
| } | |||||
| return begin_ + n_; | |||||
| } | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(is_heap_until_n_fn, is_heap_until_n) | |||||
| struct is_heap_n_fn | |||||
| { | |||||
| template<typename I, typename C = less, typename P = identity> | |||||
| auto operator()(I first, iter_difference_t<I> n, C pred = C{}, | |||||
| P proj = P{}) const -> CPP_ret(bool)( // | |||||
| requires random_access_iterator<I> && | |||||
| indirect_strict_weak_order<C, projected<I, P>>) | |||||
| { | |||||
| return is_heap_until_n(first, n, std::move(pred), std::move(proj)) == | |||||
| first + n; | |||||
| } | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(is_heap_n_fn, is_heap_n) | |||||
| } // namespace detail | |||||
| /// \endcond | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(is_heap_until) | |||||
| /// \brief function template \c is_heap_until | |||||
| template<typename I, typename S, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(is_heap_until)( | |||||
| I first, S last, C pred = C{}, P proj = P{}) | |||||
| ->CPP_ret(I)( // | |||||
| requires random_access_iterator<I> && sentinel_for<S, I> && | |||||
| indirect_strict_weak_order<C, projected<I, P>>) | |||||
| { | |||||
| return detail::is_heap_until_n(std::move(first), | |||||
| distance(first, last), | |||||
| std::move(pred), | |||||
| std::move(proj)); | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(is_heap_until)(Rng && rng, C pred = C{}, P proj = P{}) | |||||
| ->CPP_ret(safe_iterator_t<Rng>)( // | |||||
| requires random_access_range<Rng> && | |||||
| indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>) | |||||
| { | |||||
| return detail::is_heap_until_n( | |||||
| begin(rng), distance(rng), std::move(pred), std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(is_heap_until) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::is_heap_until; | |||||
| } | |||||
| RANGES_BEGIN_NIEBLOID(is_heap) | |||||
| /// \brief function template \c is_heap | |||||
| template<typename I, typename S, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(is_heap)(I first, S last, C pred = C{}, P proj = P{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires random_access_iterator<I> && sentinel_for<S, I> && | |||||
| indirect_strict_weak_order<C, projected<I, P>>) | |||||
| { | |||||
| return detail::is_heap_n(std::move(first), | |||||
| distance(first, last), | |||||
| std::move(pred), | |||||
| std::move(proj)); | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(is_heap)(Rng && rng, C pred = C{}, P proj = P{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires random_access_range<Rng> && | |||||
| indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>) | |||||
| { | |||||
| return detail::is_heap_n( | |||||
| begin(rng), distance(rng), std::move(pred), std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(is_heap) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::is_heap; | |||||
| } | |||||
| /// @} | |||||
| /// \cond | |||||
| namespace detail | |||||
| { | |||||
| struct sift_up_n_fn | |||||
| { | |||||
| template<typename I, typename C = less, typename P = identity> | |||||
| void operator()(I first, iter_difference_t<I> len, C pred = C{}, | |||||
| P proj = P{}) const | |||||
| { | |||||
| if(len > 1) | |||||
| { | |||||
| I last = first + len; | |||||
| len = (len - 2) / 2; | |||||
| I i = first + len; | |||||
| if(invoke(pred, invoke(proj, *i), invoke(proj, *--last))) | |||||
| { | |||||
| iter_value_t<I> v = iter_move(last); | |||||
| do | |||||
| { | |||||
| *last = iter_move(i); | |||||
| last = i; | |||||
| if(len == 0) | |||||
| break; | |||||
| len = (len - 1) / 2; | |||||
| i = first + len; | |||||
| } while(invoke(pred, invoke(proj, *i), invoke(proj, v))); | |||||
| *last = std::move(v); | |||||
| } | |||||
| } | |||||
| } | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(sift_up_n_fn, sift_up_n) | |||||
| struct sift_down_n_fn | |||||
| { | |||||
| template<typename I, typename C = less, typename P = identity> | |||||
| void operator()(I first, iter_difference_t<I> len, I start, C pred = C{}, | |||||
| P proj = P{}) const | |||||
| { | |||||
| // left-child of start is at 2 * start + 1 | |||||
| // right-child of start is at 2 * start + 2 | |||||
| auto child = start - first; | |||||
| if(len < 2 || (len - 2) / 2 < child) | |||||
| return; | |||||
| child = 2 * child + 1; | |||||
| I child_i = first + child; | |||||
| if((child + 1) < len && | |||||
| invoke(pred, invoke(proj, *child_i), invoke(proj, *(child_i + 1)))) | |||||
| { | |||||
| // right-child exists and is greater than left-child | |||||
| ++child_i; | |||||
| ++child; | |||||
| } | |||||
| // check if we are in heap-order | |||||
| if(invoke(pred, invoke(proj, *child_i), invoke(proj, *start))) | |||||
| // we are, start is larger than it's largest child | |||||
| return; | |||||
| iter_value_t<I> top = iter_move(start); | |||||
| do | |||||
| { | |||||
| // we are not in heap-order, swap the parent with it's largest child | |||||
| *start = iter_move(child_i); | |||||
| start = child_i; | |||||
| if((len - 2) / 2 < child) | |||||
| break; | |||||
| // recompute the child based off of the updated parent | |||||
| child = 2 * child + 1; | |||||
| child_i = first + child; | |||||
| if((child + 1) < len && | |||||
| invoke(pred, invoke(proj, *child_i), invoke(proj, *(child_i + 1)))) | |||||
| { | |||||
| // right-child exists and is greater than left-child | |||||
| ++child_i; | |||||
| ++child; | |||||
| } | |||||
| // check if we are in heap-order | |||||
| } while(!invoke(pred, invoke(proj, *child_i), invoke(proj, top))); | |||||
| *start = std::move(top); | |||||
| } | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(sift_down_n_fn, sift_down_n) | |||||
| } // namespace detail | |||||
| /// \endcond | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(push_heap) | |||||
| /// \brief function template \c push_heap | |||||
| template<typename I, typename S, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(push_heap)( | |||||
| I first, S last, C pred = C{}, P proj = P{}) // | |||||
| ->CPP_ret(I)( // | |||||
| requires random_access_iterator<I> && sentinel_for<S, I> && | |||||
| sortable<I, C, P>) | |||||
| { | |||||
| auto n = distance(first, last); | |||||
| detail::sift_up_n(first, n, std::move(pred), std::move(proj)); | |||||
| return first + n; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(push_heap)(Rng && rng, C pred = C{}, P proj = P{}) // | |||||
| ->CPP_ret(safe_iterator_t<Rng>)( // | |||||
| requires random_access_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||||
| { | |||||
| iterator_t<Rng> first = ranges::begin(rng); | |||||
| auto n = distance(rng); | |||||
| detail::sift_up_n(first, n, std::move(pred), std::move(proj)); | |||||
| return first + n; | |||||
| } | |||||
| RANGES_END_NIEBLOID(push_heap) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::push_heap; | |||||
| } | |||||
| /// @} | |||||
| /// \cond | |||||
| namespace detail | |||||
| { | |||||
| struct pop_heap_n_fn | |||||
| { | |||||
| template<typename I, typename C = less, typename P = identity> | |||||
| auto operator()(I first, iter_difference_t<I> len, C pred = C{}, | |||||
| P proj = P{}) const -> CPP_ret(void)( // | |||||
| requires random_access_iterator<I> && sortable<I, C, P>) | |||||
| { | |||||
| if(len > 1) | |||||
| { | |||||
| ranges::iter_swap(first, first + (len - 1)); | |||||
| detail::sift_down_n( | |||||
| first, len - 1, first, std::move(pred), std::move(proj)); | |||||
| } | |||||
| } | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(pop_heap_n_fn, pop_heap_n) | |||||
| } // namespace detail | |||||
| /// \endcond | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(pop_heap) | |||||
| /// \brief function template \c pop_heap | |||||
| template<typename I, typename S, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(pop_heap)(I first, S last, C pred = C{}, P proj = P{}) | |||||
| ->CPP_ret(I)( // | |||||
| requires random_access_iterator<I> && sentinel_for<S, I> && | |||||
| sortable<I, C, P>) | |||||
| { | |||||
| auto n = distance(first, last); | |||||
| detail::pop_heap_n(first, n, std::move(pred), std::move(proj)); | |||||
| return first + n; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(pop_heap)(Rng && rng, C pred = C{}, P proj = P{}) | |||||
| ->CPP_ret(safe_iterator_t<Rng>)( // | |||||
| requires random_access_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||||
| { | |||||
| iterator_t<Rng> first = ranges::begin(rng); | |||||
| auto n = distance(rng); | |||||
| detail::pop_heap_n(first, n, std::move(pred), std::move(proj)); | |||||
| return first + n; | |||||
| } | |||||
| RANGES_END_NIEBLOID(pop_heap) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::pop_heap; | |||||
| } | |||||
| RANGES_BEGIN_NIEBLOID(make_heap) | |||||
| /// \brief function template \c make_heap | |||||
| template<typename I, typename S, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(make_heap)(I first, S last, C pred = C{}, P proj = P{}) | |||||
| ->CPP_ret(I)( // | |||||
| requires random_access_iterator<I> && sentinel_for<S, I> && | |||||
| sortable<I, C, P>) | |||||
| { | |||||
| iter_difference_t<I> const n = distance(first, last); | |||||
| if(n > 1) | |||||
| // start from the first parent, there is no need to consider children | |||||
| for(auto start = (n - 2) / 2; start >= 0; --start) | |||||
| detail::sift_down_n( | |||||
| first, n, first + start, std::ref(pred), std::ref(proj)); | |||||
| return first + n; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(make_heap)(Rng && rng, C pred = C{}, P proj = P{}) | |||||
| ->CPP_ret(safe_iterator_t<Rng>)( // | |||||
| requires random_access_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||||
| { | |||||
| iterator_t<Rng> first = ranges::begin(rng); | |||||
| auto const n = distance(rng); | |||||
| if(n > 1) | |||||
| // start from the first parent, there is no need to consider children | |||||
| for(auto start = (n - 2) / 2; start >= 0; --start) | |||||
| detail::sift_down_n( | |||||
| first, n, first + start, std::ref(pred), std::ref(proj)); | |||||
| return first + n; | |||||
| } | |||||
| RANGES_END_NIEBLOID(make_heap) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::make_heap; | |||||
| } | |||||
| RANGES_BEGIN_NIEBLOID(sort_heap) | |||||
| template<typename I, typename S, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(sort_heap)(I first, S last, C pred = C{}, P proj = P{}) | |||||
| ->CPP_ret(I)( // | |||||
| requires random_access_iterator<I> && sentinel_for<S, I> && | |||||
| sortable<I, C, P>) | |||||
| { | |||||
| iter_difference_t<I> const n = distance(first, last); | |||||
| for(auto i = n; i > 1; --i) | |||||
| detail::pop_heap_n(first, i, std::ref(pred), std::ref(proj)); | |||||
| return first + n; | |||||
| } | |||||
| template<typename Rng, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(sort_heap)(Rng && rng, C pred = C{}, P proj = P{}) | |||||
| ->CPP_ret(safe_iterator_t<Rng>)( // | |||||
| requires random_access_range<Rng &> && sortable<iterator_t<Rng>, C, P>) | |||||
| { | |||||
| iterator_t<Rng> first = ranges::begin(rng); | |||||
| auto const n = distance(rng); | |||||
| for(auto i = n; i > 1; --i) | |||||
| detail::pop_heap_n(first, i, std::ref(pred), std::ref(proj)); | |||||
| return first + n; | |||||
| } | |||||
| RANGES_END_NIEBLOID(sort_heap) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::sort_heap; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| //===----------------------------------------------------------------------===// | |||||
| // | |||||
| // The LLVM Compiler Infrastructure | |||||
| // | |||||
| // This file is dual licensed under the MIT and the University of Illinois Open | |||||
| // Source Licenses. See LICENSE.TXT for details. | |||||
| // | |||||
| //===----------------------------------------------------------------------===// | |||||
| #ifndef RANGES_V3_ALGORITHM_INPLACE_MERGE_HPP | |||||
| #define RANGES_V3_ALGORITHM_INPLACE_MERGE_HPP | |||||
| #include <functional> | |||||
| #include <memory> | |||||
| #include <new> | |||||
| #include <type_traits> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/algorithm/lower_bound.hpp> | |||||
| #include <range/v3/algorithm/merge.hpp> | |||||
| #include <range/v3/algorithm/min.hpp> | |||||
| #include <range/v3/algorithm/move.hpp> | |||||
| #include <range/v3/algorithm/rotate.hpp> | |||||
| #include <range/v3/algorithm/upper_bound.hpp> | |||||
| #include <range/v3/functional/comparisons.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/functional/not_fn.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/move_iterators.hpp> | |||||
| #include <range/v3/iterator/operations.hpp> | |||||
| #include <range/v3/iterator/reverse_iterator.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/dangling.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/memory.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| #include <range/v3/utility/swap.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \cond | |||||
| namespace detail | |||||
| { | |||||
| struct merge_adaptive_fn | |||||
| { | |||||
| private: | |||||
| template<typename I, typename C, typename P> | |||||
| static void impl(I first, I middle, I last, iter_difference_t<I> len1, | |||||
| iter_difference_t<I> len2, iter_value_t<I> * const buf, | |||||
| C & pred, P & proj) | |||||
| { | |||||
| auto tmpbuf = make_raw_buffer(buf); | |||||
| if(len1 <= len2) | |||||
| { | |||||
| auto p = ranges::move(first, middle, tmpbuf.begin()).out; | |||||
| merge(make_move_iterator(buf), | |||||
| make_move_iterator(p.base().base()), | |||||
| make_move_iterator(std::move(middle)), | |||||
| make_move_iterator(std::move(last)), | |||||
| std::move(first), | |||||
| std::ref(pred), | |||||
| std::ref(proj), | |||||
| std::ref(proj)); | |||||
| } | |||||
| else | |||||
| { | |||||
| auto p = ranges::move(middle, last, tmpbuf.begin()).out; | |||||
| using RBi = ranges::reverse_iterator<I>; | |||||
| using Rv = ranges::reverse_iterator<iter_value_t<I> *>; | |||||
| merge(make_move_iterator(RBi{std::move(middle)}), | |||||
| make_move_iterator(RBi{std::move(first)}), | |||||
| make_move_iterator(Rv{p.base().base()}), | |||||
| make_move_iterator(Rv{buf}), | |||||
| RBi{std::move(last)}, | |||||
| not_fn(std::ref(pred)), | |||||
| std::ref(proj), | |||||
| std::ref(proj)); | |||||
| } | |||||
| } | |||||
| public: | |||||
| template<typename I, typename C = less, typename P = identity> | |||||
| auto operator()(I first, I middle, I last, iter_difference_t<I> len1, | |||||
| iter_difference_t<I> len2, iter_value_t<I> * buf, | |||||
| std::ptrdiff_t buf_size, C pred = C{}, P proj = P{}) const | |||||
| -> CPP_ret(void)( // | |||||
| requires bidirectional_iterator<I> && sortable<I, C, P>) | |||||
| { | |||||
| using D = iter_difference_t<I>; | |||||
| while(true) | |||||
| { | |||||
| // if middle == last, we're done | |||||
| if(len2 == 0) | |||||
| return; | |||||
| // shrink [first, middle) as much as possible (with no moves), | |||||
| // returning if it shrinks to 0 | |||||
| for(; true; ++first, --len1) | |||||
| { | |||||
| if(len1 == 0) | |||||
| return; | |||||
| if(invoke(pred, invoke(proj, *middle), invoke(proj, *first))) | |||||
| break; | |||||
| } | |||||
| if(len1 <= buf_size || len2 <= buf_size) | |||||
| { | |||||
| merge_adaptive_fn::impl(std::move(first), | |||||
| std::move(middle), | |||||
| std::move(last), | |||||
| len1, | |||||
| len2, | |||||
| buf, | |||||
| pred, | |||||
| proj); | |||||
| return; | |||||
| } | |||||
| // first < middle < end | |||||
| // *first > *middle | |||||
| // partition [first, m1) [m1, middle) [middle, m2) [m2, last) such | |||||
| // that | |||||
| // all elements in: | |||||
| // [first, m1) <= [middle, m2) | |||||
| // [middle, m2) < [m1, middle) | |||||
| // [m1, middle) <= [m2, last) | |||||
| // and m1 or m2 is in the middle of its range | |||||
| I m1; // "median" of [first, middle) | |||||
| I m2; // "median" of [middle, last) | |||||
| D len11; // distance(first, m1) | |||||
| D len21; // distance(middle, m2) | |||||
| // binary search smaller range | |||||
| if(len1 < len2) | |||||
| { // len >= 1, len2 >= 2 | |||||
| len21 = len2 / 2; | |||||
| m2 = next(middle, len21); | |||||
| m1 = upper_bound(first, | |||||
| middle, | |||||
| invoke(proj, *m2), | |||||
| std::ref(pred), | |||||
| std::ref(proj)); | |||||
| len11 = distance(first, m1); | |||||
| } | |||||
| else | |||||
| { | |||||
| if(len1 == 1) | |||||
| { // len1 >= len2 && len2 > 0, therefore len2 == 1 | |||||
| // It is known *first > *middle | |||||
| ranges::iter_swap(first, middle); | |||||
| return; | |||||
| } | |||||
| // len1 >= 2, len2 >= 1 | |||||
| len11 = len1 / 2; | |||||
| m1 = next(first, len11); | |||||
| m2 = lower_bound(middle, | |||||
| last, | |||||
| invoke(proj, *m1), | |||||
| std::ref(pred), | |||||
| std::ref(proj)); | |||||
| len21 = distance(middle, m2); | |||||
| } | |||||
| D len12 = len1 - len11; // distance(m1, middle) | |||||
| D len22 = len2 - len21; // distance(m2, last) | |||||
| // [first, m1) [m1, middle) [middle, m2) [m2, last) | |||||
| // swap middle two partitions | |||||
| middle = rotate(m1, std::move(middle), m2).begin(); | |||||
| // len12 and len21 now have swapped meanings | |||||
| // merge smaller range with recursive call and larger with tail | |||||
| // recursion elimination | |||||
| if(len11 + len21 < len12 + len22) | |||||
| { | |||||
| (*this)(std::move(first), | |||||
| std::move(m1), | |||||
| middle, | |||||
| len11, | |||||
| len21, | |||||
| buf, | |||||
| buf_size, | |||||
| std::ref(pred), | |||||
| std::ref(proj)); | |||||
| first = std::move(middle); | |||||
| middle = std::move(m2); | |||||
| len1 = len12; | |||||
| len2 = len22; | |||||
| } | |||||
| else | |||||
| { | |||||
| (*this)(middle, | |||||
| std::move(m2), | |||||
| std::move(last), | |||||
| len12, | |||||
| len22, | |||||
| buf, | |||||
| buf_size, | |||||
| std::ref(pred), | |||||
| std::ref(proj)); | |||||
| last = std::move(middle); | |||||
| middle = std::move(m1); | |||||
| len1 = len11; | |||||
| len2 = len21; | |||||
| } | |||||
| } | |||||
| } | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(merge_adaptive_fn, merge_adaptive) | |||||
| struct inplace_merge_no_buffer_fn | |||||
| { | |||||
| template<typename I, typename C = less, typename P = identity> | |||||
| auto operator()(I first, I middle, I last, iter_difference_t<I> len1, | |||||
| iter_difference_t<I> len2, C pred = C{}, P proj = P{}) const | |||||
| -> CPP_ret(void)( // | |||||
| requires bidirectional_iterator<I> && sortable<I, C, P>) | |||||
| { | |||||
| merge_adaptive(std::move(first), | |||||
| std::move(middle), | |||||
| std::move(last), | |||||
| len1, | |||||
| len2, | |||||
| static_cast<iter_value_t<I> *>(nullptr), | |||||
| 0, | |||||
| std::move(pred), | |||||
| std::move(proj)); | |||||
| } | |||||
| }; | |||||
| RANGES_INLINE_VARIABLE(inplace_merge_no_buffer_fn, inplace_merge_no_buffer) | |||||
| } // namespace detail | |||||
| /// \endcond | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(inplace_merge) | |||||
| // TODO reimplement to only need forward iterators | |||||
| /// \brief function template \c inplace_merge | |||||
| template<typename I, typename S, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(inplace_merge)( | |||||
| I first, I middle, S last, C pred = C{}, P proj = P{}) | |||||
| ->CPP_ret(I)( // | |||||
| requires bidirectional_iterator<I> && sortable<I, C, P>) | |||||
| { | |||||
| using value_type = iter_value_t<I>; | |||||
| auto len1 = distance(first, middle); | |||||
| auto len2_and_end = enumerate(middle, last); | |||||
| auto buf_size = ranges::min(len1, len2_and_end.first); | |||||
| std::pair<value_type *, std::ptrdiff_t> buf{nullptr, 0}; | |||||
| std::unique_ptr<value_type, detail::return_temporary_buffer> h; | |||||
| if(detail::is_trivially_copy_assignable<value_type>::value && 8 < buf_size) | |||||
| { | |||||
| buf = detail::get_temporary_buffer<value_type>(buf_size); | |||||
| h.reset(buf.first); | |||||
| } | |||||
| detail::merge_adaptive(std::move(first), | |||||
| std::move(middle), | |||||
| len2_and_end.second, | |||||
| len1, | |||||
| len2_and_end.first, | |||||
| buf.first, | |||||
| buf.second, | |||||
| std::move(pred), | |||||
| std::move(proj)); | |||||
| return len2_and_end.second; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename C = less, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(inplace_merge)( | |||||
| Rng && rng, iterator_t<Rng> middle, C pred = C{}, P proj = P{}) | |||||
| ->CPP_ret(safe_iterator_t<Rng>)( // | |||||
| requires bidirectional_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||||
| { | |||||
| return (*this)(begin(rng), | |||||
| std::move(middle), | |||||
| end(rng), | |||||
| std::move(pred), | |||||
| std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(inplace_merge) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::inplace_merge; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |
| /// \file | |||||
| // Range v3 library | |||||
| // | |||||
| // Copyright Eric Niebler 2014-present | |||||
| // | |||||
| // Use, modification and distribution is subject to the | |||||
| // Boost Software License, Version 1.0. (See accompanying | |||||
| // file LICENSE_1_0.txt or copy at | |||||
| // http://www.boost.org/LICENSE_1_0.txt) | |||||
| // | |||||
| // Project home: https://github.com/ericniebler/range-v3 | |||||
| // | |||||
| //===-------------------------- algorithm ---------------------------------===// | |||||
| // | |||||
| // The LLVM Compiler Infrastructure | |||||
| // | |||||
| // This file is dual licensed under the MIT and the University of Illinois Open | |||||
| // Source Licenses. See LICENSE.TXT for details. | |||||
| // | |||||
| //===----------------------------------------------------------------------===// | |||||
| #ifndef RANGES_V3_ALGORITHM_IS_PARTITIONED_HPP | |||||
| #define RANGES_V3_ALGORITHM_IS_PARTITIONED_HPP | |||||
| #include <meta/meta.hpp> | |||||
| #include <range/v3/range_fwd.hpp> | |||||
| #include <range/v3/functional/identity.hpp> | |||||
| #include <range/v3/functional/invoke.hpp> | |||||
| #include <range/v3/iterator/concepts.hpp> | |||||
| #include <range/v3/iterator/traits.hpp> | |||||
| #include <range/v3/range/access.hpp> | |||||
| #include <range/v3/range/concepts.hpp> | |||||
| #include <range/v3/range/traits.hpp> | |||||
| #include <range/v3/utility/static_const.hpp> | |||||
| namespace ranges | |||||
| { | |||||
| /// \addtogroup group-algorithms | |||||
| /// @{ | |||||
| RANGES_BEGIN_NIEBLOID(is_partitioned) | |||||
| /// \brief function template \c is_partitioned | |||||
| template<typename I, typename S, typename C, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(is_partitioned)(I first, S last, C pred, P proj = P{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires input_iterator<I> && sentinel_for<S, I> && | |||||
| indirect_unary_predicate<C, projected<I, P>>) | |||||
| { | |||||
| for(; first != last; ++first) | |||||
| if(!invoke(pred, invoke(proj, *first))) | |||||
| break; | |||||
| for(; first != last; ++first) | |||||
| if(invoke(pred, invoke(proj, *first))) | |||||
| return false; | |||||
| return true; | |||||
| } | |||||
| /// \overload | |||||
| template<typename Rng, typename C, typename P = identity> | |||||
| auto RANGES_FUN_NIEBLOID(is_partitioned)(Rng && rng, C pred, P proj = P{}) // | |||||
| ->CPP_ret(bool)( // | |||||
| requires input_range<Rng> && | |||||
| indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>) | |||||
| { | |||||
| return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||||
| } | |||||
| RANGES_END_NIEBLOID(is_partitioned) | |||||
| namespace cpp20 | |||||
| { | |||||
| using ranges::is_partitioned; | |||||
| } | |||||
| /// @} | |||||
| } // namespace ranges | |||||
| #endif // include guard |