Working on c++23

There are many more efficient features on future c++23 standard
This commit is contained in:
halx99 2023-02-18 11:39:31 +08:00
parent ff75289a07
commit 49284f4cc2
333 changed files with 60598 additions and 757 deletions

View File

@ -4,6 +4,36 @@
#include <memory> #include <memory>
#include "pod_vector.h" #include "pod_vector.h"
// Tests whether compiler has c++23 support
#if (defined(__cplusplus) && __cplusplus > 202002L) || \
(defined(_MSC_VER) && _MSC_VER > 1934 && \
((defined(_HAS_CXX23) && _HAS_CXX23 == 1) || (defined(_MSVC_LANG) && (_MSVC_LANG > 202002L))))
# ifndef _AX_HAS_CXX23
# define _AX_HAS_CXX23 1
# endif // C++23 features macro
#endif // C++23 features check
#if !defined(_AX_HAS_CXX23)
# define _AX_HAS_CXX23 0
#endif
#if !_AX_HAS_CXX23
# include "range/v3/range.hpp"
# include "range/v3/view.hpp"
namespace axstd
{
using namespace ::ranges;
namespace ranges
{
using namespace ::ranges;
}
} // namespace axstd
#else
namespace axstd
{
using namespace std;
}
#endif
namespace axstd namespace axstd
{ {
/* make_unique_for_overwrite since c++20, but not all platformm support */ /* make_unique_for_overwrite since c++20, but not all platformm support */

View File

@ -57,6 +57,7 @@ THE SOFTWARE.
#include "2d/CCRenderTexture.h" #include "2d/CCRenderTexture.h"
#include "base/base64.h" #include "base/base64.h"
#include "base/axstd.h"
using namespace std::string_view_literals; using namespace std::string_view_literals;
@ -809,7 +810,7 @@ AX_DLL std::string base64Encode(std::string_view s)
* - https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-170 * - https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-170
* *
*/ */
#if defined(_HAS_CXX23) && _HAS_CXX23 && (_MSC_VER >= 1931) #if _AX_HAS_CXX23
ret.resize_and_overwrite(n, [&](char* p, size_t) { return ax::base64::encode(p, s.data(), s.length()); }); ret.resize_and_overwrite(n, [&](char* p, size_t) { return ax::base64::encode(p, s.data(), s.length()); });
#else #else
ret.resize(n); ret.resize(n);
@ -828,7 +829,7 @@ AX_DLL std::string base64Decode(std::string_view s)
{ {
std::string ret; std::string ret;
#if defined(_HAS_CXX23) && _HAS_CXX23 && (_MSC_VER >= 1931) #if _AX_HAS_CXX23
ret.resize_and_overwrite(n, [&](char* p, size_t) { return ax::base64::decode(p, s.data(), s.length()); }); ret.resize_and_overwrite(n, [&](char* p, size_t) { return ax::base64::decode(p, s.data(), s.length()); });
#else #else
ret.resize(n); ret.resize(n);

View File

@ -2,15 +2,19 @@
Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
Copyright (c) 2021 Bytedance Inc. Copyright (c) 2021 Bytedance Inc.
https://axmolengine.github.io/ https://axmolengine.github.io/
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -25,13 +29,14 @@
#include "platform/CCFileUtils.h" #include "platform/CCFileUtils.h"
#include "yasio/detail/utils.hpp" #include "yasio/detail/utils.hpp"
#include "yasio/stl/string_view.hpp" #include "yasio/stl/string_view.hpp"
#include "xsbase/fast_split.hpp"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <locale> #include <locale>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <charconv>
#include "base/axstd.h"
NS_AX_BEGIN NS_AX_BEGIN
@ -53,42 +58,41 @@ void HttpCookie::readFile()
std::string inString = ax::FileUtils::getInstance()->getStringFromFile(_cookieFileName); std::string inString = ax::FileUtils::getInstance()->getStringFromFile(_cookieFileName);
if (!inString.empty()) if (!inString.empty())
{ {
xsbase::fast_split(inString, '\n', [this](char* s, char* e) { for (auto line : axstd::views::split(inString, '\n'))
if (*s == '#') // skip comment {
return; if (line.empty() || *line.begin() == '#') // skip comment
continue;
int count = 0; int count = 0;
CookieInfo cookieInfo; CookieInfo cookieInfo;
using namespace cxx17; using namespace cxx17;
xsbase::fast_split(s, e - s, '\t', [&, this](char* ss, char* ee) { for (auto subrgn : axstd::views::split(line, '\t')) {
auto ch = *ee; // store std::string_view word{&*subrgn.begin(), static_cast<size_t>(axstd::ranges::distance(subrgn))};
*ee = '\0';
switch (count) switch (count)
{ {
case DOMAIN_INDEX: case DOMAIN_INDEX:
cookieInfo.domain.assign(ss, ee - ss); cookieInfo.domain = word;
break; break;
case PATH_INDEX: case PATH_INDEX:
cookieInfo.path.assign(ss, ee - ss); cookieInfo.path = word;
break; break;
case SECURE_INDEX: case SECURE_INDEX:
cookieInfo.secure = cxx17::string_view{ss, (size_t)(ee - ss)} == "TRUE"_sv; cookieInfo.secure = word == "TRUE"_sv;
break; break;
case EXPIRES_INDEX: case EXPIRES_INDEX:
cookieInfo.expires = static_cast<time_t>(strtoll(ss, nullptr, 10)); std::from_chars(word.data(), word.data() + word.size(), cookieInfo.expires);
break; break;
case NAME_INDEX: case NAME_INDEX:
cookieInfo.name.assign(ss, ee - ss); cookieInfo.name = word;
break; break;
case VALUE_INDEX: case VALUE_INDEX:
cookieInfo.value.assign(ss, ee - ss); cookieInfo.value = word;
break; break;
} }
*ee = ch; // restore
++count; ++count;
}); }
if (count >= 7) if (count >= 7)
_cookies.emplace_back(std::move(cookieInfo)); _cookies.emplace_back(std::move(cookieInfo));
}); }
} }
} }
@ -151,25 +155,29 @@ bool HttpCookie::updateOrAddCookie(std::string_view cookie, const Uri& uri)
{ {
unsigned int count = 0; unsigned int count = 0;
CookieInfo info; CookieInfo info;
xsbase::nzls::fast_split(cookie.data(), cookie.length(), ';', [&](const char* start, const char* end) { for (auto rgn : axstd::views::split(cookie, ';'))
{
unsigned int count_ = 0; unsigned int count_ = 0;
while (*start == ' ') std::string_view citem{&*rgn.begin(), static_cast<size_t>(axstd::ranges::distance(rgn))};
++start; // skip ws while (*citem.data() == ' ')
citem.remove_prefix(1); // skip ws
if (++count > 1) if (++count > 1)
{ {
cxx17::string_view key; cxx17::string_view key;
cxx17::string_view value; cxx17::string_view value;
xsbase::fast_split(start, end - start, '=', [&](const char* s, const char* e) { for (auto subrgn : axstd::views::split(citem, '='))
{
std::string_view word{&*subrgn.begin(), static_cast<size_t>(axstd::ranges::distance(subrgn))};
switch (++count_) switch (++count_)
{ {
case 1: case 1:
key = cxx17::string_view(s, e - s); key = word;
break; break;
case 2: case 2:
value = cxx17::string_view(s, e - s); value = word;
break; break;
} }
}); }
using namespace cxx17; using namespace cxx17;
if (cxx20::ic::iequals(key, "domain"_sv)) if (cxx20::ic::iequals(key, "domain"_sv))
@ -188,7 +196,7 @@ bool HttpCookie::updateOrAddCookie(std::string_view cookie, const Uri& uri)
if (cxx20::ends_with(expires_ctime, " GMT"_sv)) if (cxx20::ends_with(expires_ctime, " GMT"_sv))
expires_ctime.resize(expires_ctime.length() - sizeof(" GMT") + 1); expires_ctime.resize(expires_ctime.length() - sizeof(" GMT") + 1);
if (expires_ctime.empty()) if (expires_ctime.empty())
return; continue;
size_t off = 0; size_t off = 0;
auto p = expires_ctime.find_first_of(','); auto p = expires_ctime.find_first_of(',');
if (p != std::string::npos) if (p != std::string::npos)
@ -220,19 +228,21 @@ bool HttpCookie::updateOrAddCookie(std::string_view cookie, const Uri& uri)
} }
else else
{ // first is cookie name { // first is cookie name
xsbase::fast_split(start, end - start, '=', [&](const char* s, const char* e) { for (auto rgn : axstd::views::split(citem, '='))
{
std::string_view word{&*rgn.begin(), static_cast<size_t>(axstd::ranges::distance(rgn))};
switch (++count_) switch (++count_)
{ {
case 1: case 1:
info.name.assign(s, e - s); info.name = word;
break; break;
case 2: case 2:
info.value.assign(s, e - s); info.value = word;
break; break;
} }
}); }
} }
}); }
if (info.path.empty()) if (info.path.empty())
info.path.push_back('/'); info.path.push_back('/');

View File

@ -29,7 +29,7 @@
#include <vector> // because its based on windows 8 build :P #include <vector> // because its based on windows 8 build :P
#include "platform/CCFileUtils.h" #include "platform/CCFileUtils.h"
#include "xsbase/xsxml/xsxml.hpp" #include "xsxml/xsxml.hpp"
NS_AX_BEGIN NS_AX_BEGIN

View File

@ -163,6 +163,7 @@ add_library(thirdparty STATIC empty.cpp)
# bellow are header only libs # bellow are header only libs
target_include_directories(thirdparty target_include_directories(thirdparty
INTERFACE "robin-map/include" INTERFACE "robin-map/include"
INTERFACE "range-v3/include"
) )
if (ANDROID) if (ANDROID)

View File

@ -59,6 +59,17 @@
# define PUGI_CXX_STD 20 # define PUGI_CXX_STD 20
#endif // C++20 features check #endif // C++20 features check
// Tests whether compiler has c++23 support
#if (defined(__cplusplus) && __cplusplus > 202002L) || \
(defined(_MSC_VER) && _MSC_VER > 1934 && \
((defined(_HAS_CXX23) && _HAS_CXX23 == 1) || \
(defined(_MSVC_LANG) && (_MSVC_LANG > 202002L))))
# ifdef PUGI_CXX_STD
# undef PUGI_CXX_STD
# endif
# define PUGI_CXX_STD 23
#endif // C++20 features check
#if !defined(PUGI_CXX_STD) #if !defined(PUGI_CXX_STD)
# define PUGI_CXX_STD 11 # define PUGI_CXX_STD 11
#endif #endif

151
thirdparty/range-v3/LICENSE.txt vendored Normal file
View File

@ -0,0 +1,151 @@
========================================================
Boost Software License - Version 1.0 - August 17th, 2003
========================================================
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
==============================================================================
libc++ License
==============================================================================
The libc++ library is dual licensed under both the University of Illinois
"BSD-Like" license and the MIT license. As a user of this code you may choose
to use it under either license. As a contributor, you agree to allow your code
to be used under both.
Full text of the relevant licenses is included below.
==============================================================================
University of Illinois/NCSA
Open Source License
Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
http://llvm.org/svn/llvm-project/libcxx/trunk/CREDITS.TXT
All rights reserved.
Developed by:
LLVM Team
University of Illinois at Urbana-Champaign
http://llvm.org
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal with
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimers in the
documentation and/or other materials provided with the distribution.
* Neither the names of the LLVM Team, University of Illinois at
Urbana-Champaign, nor the names of its contributors may be used to
endorse or promote products derived from this Software without specific
prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
==============================================================================
Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
http://llvm.org/svn/llvm-project/libcxx/trunk/CREDITS.TXT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
==============================================================================
Stepanov and McJones, "Elements of Programming" license
==============================================================================
// 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
==============================================================================
SGI C++ Standard Template Library license
==============================================================================
// Copyright (c) 1994
// Hewlett-Packard Company
//
// 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. Hewlett-Packard Company makes no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied warranty.
//
// Copyright (c) 1996
// Silicon Graphics Computer Systems, Inc.
//
// 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. Silicon Graphics makes no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied warranty.
//

158
thirdparty/range-v3/README.md vendored Normal file
View File

@ -0,0 +1,158 @@
range-v3
========
Range library for C++14/17/20. This code was the basis of [a formal proposal](https://ericniebler.github.io/std/wg21/D4128.html) to add range support to the C++ standard library. That proposal evolved through a Technical Specification, and finally into [P0896R4 "The One Ranges Proposal"](https://wg21.link/p0896r4) which was merged into the C++20 working drafts in November 2018.
About:
------
Ranges are an extension of the Standard Template Library that makes its iterators and algorithms more powerful by making them _composable_. Unlike other range-like solutions which seek to do away with iterators, in range-v3 ranges are an abstration layer _on top_ of iterators.
Range-v3 is built on three pillars: Views, Actions, and Algorithms. The algorithms are the same as those with which you are already familiar in the STL, except that in range-v3 all the algorithms have overloads that take ranges in addition to the overloads that take iterators. Views are composable adaptations of ranges where the adaptation happens lazily as the view is iterated. And an action is an eager application of an algorithm to a container that mutates the container in-place and returns it for further processing.
Views and actions use the pipe syntax (e.g., `rng | adapt1 | adapt2 | ...`) so your code is terse and readable from left to right.
Documentation:
--------------
Check out the (woefully incomplete) documentation [here](https://ericniebler.github.io/range-v3/).
Other resources (mind the dates, the library probably has changed since then):
- Usage:
- Talk: [CppCon 2015: Eric Niebler "Ranges for the Standard Library"](https://www.youtube.com/watch?v=mFUXNMfaciE), 2015.
- [A slice of Python in C++](http://ericniebler.com/2014/12/07/a-slice-of-python-in-c/), 07.12.2014.
- Actions (back then called [Container Algorithms](http://ericniebler.com/2014/11/23/container-algorithms/)), 23.11.2014.
- [Range comprehensions](http://ericniebler.com/2014/04/27/range-comprehensions/), 27.04.2014.
- [Input iterators vs input ranges](http://ericniebler.com/2013/11/07/input-iterators-vs-input-ranges/), 07.11.2013.
- Design / Implementation:
- Rationale behind range-v3: [N4128: Ranges for the standard library Revision 1](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4128.html), 2014.
- Ranges TS: [N4560: C++ Extensions for Ranges](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4560.pdf), 2015.
- Implementation of customization points in range-v3:
- [N4381: Suggested Design for Customization Points](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html), 2015.
- [P0386: Inline variables](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0386r0.pdf), 2016.
- [Customization Point Design in C++11 and Beyond](http://ericniebler.com/2014/10/21/customization-point-design-in-c11-and-beyond/), 2014.
- Proxy iterators in range-v3:
- [D0022: Proxy Iterators for the Ranges Extensions](https://ericniebler.github.io/std/wg21/D0022.html).
- [To Be or Not to Be (an Iterator)](http://ericniebler.com/2015/01/28/to-be-or-not-to-be-an-iterator/), 2015.
- [Iterators++: Part1](http://ericniebler.com/2015/02/03/iterators-plus-plus-part-1/), 2015.
- [Iterators++: Part2](http://ericniebler.com/2015/02/13/iterators-plus-plus-part-2/), 2015.
- [Iterators++: Part3](http://ericniebler.com/2015/03/03/iterators-plus-plus-part-3/), 2015.
- Metaprogramming utilities:
- See the [meta documentation](https://ericniebler.github.io/meta/index.html), the library has changed significantly since the [2014 blog post](http://ericniebler.com/2014/11/13/tiny-metaprogramming-library/).
- Concept emulation layer: [Concept checking in C++11](http://ericniebler.com/2013/11/23/concept-checking-in-c11/), 2013.
- [C++Now 2014: Eric Niebler "C++11 Library Design"](https://www.youtube.com/watch?v=zgOF4NrQllo), 2014.
License:
--------
Most of the source code in this project are mine, and those are under the Boost Software License. Parts are taken from Alex Stepanov's Elements of Programming, Howard Hinnant's libc++, and from the SGI STL. Please see the attached LICENSE file and the CREDITS file for the licensing and acknowledgments.
Supported Compilers
-------------------
The code is known to work on the following compilers:
- clang 5.0 (or later)
- GCC 6.5 (or later)
- Clang/LLVM 6 (or later) on Windows (older versions may work - we haven't tested.)
- Visual Studio 2019 (or later) on Windows, with some caveats due to range-v3's strict conformance requirements:
- range-v3 needs `/permissive-` and either `/std:c++latest`, `/std:c++20`, or `/std:c++17`
**Development Status:** This code is fairly stable, well-tested, and suitable for casual use, although currently lacking documentation. _In general_, no promise is made about support or long-term stability. This code *will* evolve without regard to backwards compatibility.
A notable exception is anything found within the `ranges::cpp20` namespace. Those components will change rarely or (preferably) never at all.
**Build status**
- on GitHub Actions: [![GitHub Actions Status](https://github.com/ericniebler/range-v3/workflows/range-v3%20CI/badge.svg?branch=master)](https://github.com/ericniebler/range-v3/actions)
Building range-v3 - Using vcpkg
-------------------------------
You can download and install range-v3 using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install range-v3
The range-v3 port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
Building range-v3 - Using Conan
-------------------------------
You can download and install range-v3 using the [Conan](https://github.com/conan-io/conan) dependency manager.
Setup your CMakeLists.txt (see [Conan documentation](https://docs.conan.io/en/latest/integrations/build_system.html) on how to use MSBuild, Meson and others):
```
project(myproject CXX)
add_executable(${PROJECT_NAME} main.cpp)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) # Include Conan-generated file
conan_basic_setup(TARGETS) # Introduce Conan-generated targets
target_link_libraries(${PROJECT_NAME} CONAN_PKG::range-v3)
```
Create `conanfile.txt` in your source dir:
```
[requires]
range-v3/0.12.0
[generators]
cmake
```
Install and run `conan`, then build your project as always:
```
pip install conan
mkdir build
cd build
conan install ../ --build=missing
cmake ../
cmake --build .
```
Building range-v3 - Using `build2`
----------------------------------
You can use [`build2`](https://build2.org), a dependency manager and a build-system combined, to use `range-v3` (or work on it):
Currently this package is available in these package repositories:
- **https://cppget.org/range-v3/** for released and published versions.
- [**The git repository with the sources of the `build2` package of `range-v3`**](https://github.com/build2-packaging/range-v3.git) for unreleased or custom revisions of `range-v3`, or for working on it with `build2`.
### Usage:
- `build2` package name: `range-v3`
- Library target name : `lib{range-v3}`
- [Detailed use cases and instructions in this document](https://github.com/build2-packaging/range-v3/NOTES-build2.md).
For example, to make your `build2` project depend on `range-v3`:
- Add one of the repositories to your configurations, or in your `repositories.manifest`, if not already there; for example:
```
:
role: prerequisite
location: https://pkg.cppget.org/1/alpha # v0.11.0 is there.
```
- Add this package as a dependency to your `manifest` file (example for `v0.11.x`):
```
depends: range-v3 ~0.11.0
```
- Import the target and use it as a prerequisite to your own target using `range-v3` in the appropriate `buildfile`:
```
import range_v3 = range-v3%lib{range-v3}
lib{mylib} : cxx{**} ... $range_v3
```
Then just build your project as usual (with `b` or `bdep update`), `build2` will figure out the rest.
For `build2` newcomers or to get more details and use cases, you can read [this document](https://github.com/build2-packaging/range-v3/NOTES-build2.md) and the [`build2` toolchain introduction](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml).
Say Thanks!
-----------
I do this work because I love it and because I love C++ and want it to be as excellent as I know it can be. If you like my work and are looking for a way to say thank you, you can leave a supportive comment on [my blog](http://ericniebler.com). Or you could leave me some kudos on my Open Hub range-v3 contribution page. Just click the **Give Kudos** button [here](https://www.openhub.net/p/range-v3/contributors/3053743222308608).

View File

@ -0,0 +1,66 @@
/// \file
// CPP, the Concepts PreProcessor library
//
// Copyright Eric Niebler 2018-present
// Copyright (c) 2020-present, Google LLC.
//
// 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)
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef CPP_COMPARE_HPP
#define CPP_COMPARE_HPP
#if __cplusplus > 201703L && __has_include(<compare>) && \
defined(__cpp_concepts) && defined(__cpp_impl_three_way_comparison)
#include <compare>
#include <concepts/concepts.hpp>
#include <range/v3/compare.hpp>
// clang-format off
namespace concepts
{
// Note: concepts in this file can use C++20 concepts, since operator<=> isn't available in
// compilers that don't support core concepts.
namespace detail
{
template<typename T, typename Cat>
concept compares_as = same_as<ranges::common_comparison_category_t<T, Cat>, Cat>;
} // namespace detail
inline namespace defs
{
template<typename T, typename Cat = std::partial_ordering>
concept three_way_comparable =
detail::weakly_equality_comparable_with_<T, T> &&
detail::partially_ordered_with_<T ,T> &&
requires(detail::as_cref_t<T>& a, detail::as_cref_t<T>& b) {
{ a <=> b } -> detail::compares_as<Cat>;
};
template<typename T, typename U, typename Cat = std::partial_ordering>
concept three_way_comparable_with =
three_way_comparable<T, Cat> &&
three_way_comparable<U, Cat> &&
common_reference_with<detail::as_cref_t<T>&, detail::as_cref_t<U>&> &&
three_way_comparable<common_reference_t<detail::as_cref_t<T>&, detail::as_cref_t<U>&>> &&
detail::partially_ordered_with_<T, U> &&
requires(detail::as_cref_t<T>& t, detail::as_cref_t<U>& u) {
{ t <=> u } -> detail::compares_as<Cat>;
{ u <=> t } -> detail::compares_as<Cat>;
};
} // inline namespace defs
} // namespace concepts
// clang-format on
#endif // __cplusplus
#endif // CPP_COMPARE_HPP

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,340 @@
/// \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__)
#if _MSC_VER < 1926
#define CPP_WORKAROUND_MSVC_895622 // Error when phase 1 name binding finds only deleted function
#endif // _MSC_VER < 1926
#endif // MSVC
#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_PUSH __pragma(warning(push))
#define CPP_DIAGNOSTIC_POP __pragma(warning(pop))
#define CPP_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME
#define CPP_DIAGNOSTIC_IGNORE_FLOAT_EQUAL
#define CPP_DIAGNOSTIC_IGNORE_CPP2A_COMPAT
#else // ^^^ defined(_MSC_VER) ^^^ / vvv !defined(_MSC_VER) vvv
#if defined(__GNUC__) || defined(__clang__)
#define CPP_PRAGMA(X) _Pragma(#X)
#define CPP_DIAGNOSTIC_PUSH CPP_PRAGMA(GCC diagnostic push)
#define CPP_DIAGNOSTIC_POP CPP_PRAGMA(GCC diagnostic pop)
#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")
#define CPP_DIAGNOSTIC_IGNORE_FLOAT_EQUAL CPP_DIAGNOSTIC_IGNORE("-Wfloat-equal")
#define CPP_DIAGNOSTIC_IGNORE_CPP2A_COMPAT CPP_DIAGNOSTIC_IGNORE("-Wc++2a-compat")
#else
#define CPP_DIAGNOSTIC_PUSH
#define CPP_DIAGNOSTIC_POP
#define CPP_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME
#define CPP_DIAGNOSTIC_IGNORE_FLOAT_EQUAL
#define CPP_DIAGNOSTIC_IGNORE_CPP2A_COMPAT
#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

View File

@ -0,0 +1,379 @@
/// \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_3
{};
template<typename T, typename U>
struct _builtin_common_3<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_2
: _builtin_common_3<T, U>
{};
template<typename T, typename U>
struct _builtin_common_2<T, U, meta::void_<_cond_res<T, U>>>
: std::decay<_cond_res<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_3
{};
template<typename T, typename U>
struct _builtin_common_3<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_2
: _builtin_common_3<T, U>
{};
template<typename T, typename U>
struct _builtin_common_2<T, U, meta::void_<_cond_res<T, U>>>
: std::decay<_cond_res<T, U>>
{};
template<typename T, typename U, typename /* = void */>
struct _builtin_common
: _builtin_common_2<T, U>
{};
template<typename T, typename U, typename = void>
struct _builtin_common_rr
: _builtin_common_2<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_2<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

3973
thirdparty/range-v3/include/meta/meta.hpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,360 @@
/// \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) || defined(META_DOXYGEN_INVOKED)
#if !META_CXX_VARIABLE_TEMPLATES
#error Concepts, but no variable templates?
#endif
#if __cpp_concepts <= 201507L && !defined(META_DOXYGEN_INVOKED)
#define META_CONCEPT concept bool
// TS concepts subsumption barrier for atomic expressions
#define META_CONCEPT_BARRIER(...) ::meta::detail::barrier<__VA_ARGS__>
#define META_TYPE_CONSTRAINT(...) typename
#else
#define META_CONCEPT concept
#define META_CONCEPT_BARRIER(...) __VA_ARGS__
#define META_TYPE_CONSTRAINT(...) __VA_ARGS__
#endif
#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

View File

@ -0,0 +1,61 @@
/// \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"
}

View File

@ -0,0 +1,42 @@
/// \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

View File

@ -0,0 +1,247 @@
/// \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/compose.hpp>
#include <range/v3/functional/concepts.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/functional/reference_wrapper.hpp>
#include <range/v3/functional/pipeable.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/utility/move.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
struct make_action_closure_fn
{
template<typename Fun>
constexpr actions::action_closure<Fun> operator()(Fun fun) const
{
return actions::action_closure<Fun>{static_cast<Fun &&>(fun)};
}
};
/// \sa make_action_closure_fn
RANGES_INLINE_VARIABLE(make_action_closure_fn, make_action_closure)
/// \cond
namespace detail
{
struct action_closure_base_
{};
}
/// \endcond
/// \concept invocable_action_closure_
/// \brief The \c invocable_action_closure_ concept
template(typename ActionFn, typename Rng)(
concept (invocable_action_closure_)(ActionFn, Rng),
!derived_from<invoke_result_t<ActionFn, Rng>, detail::action_closure_base_>
);
/// \concept invocable_action_closure
/// \brief The \c invocable_action_closure concept
template<typename ActionFn, typename Rng>
CPP_concept invocable_action_closure =
invocable<ActionFn, Rng> &&
CPP_concept_ref(ranges::invocable_action_closure_, ActionFn, Rng);
namespace actions
{
struct RANGES_STRUCT_WITH_ADL_BARRIER(action_closure_base)
: detail::action_closure_base_
{
// clang-format off
// Piping requires things are passed by value.
template(typename Rng, typename ActionFn)(
requires (!std::is_lvalue_reference<Rng>::value) AND
range<Rng> AND invocable_action_closure<ActionFn, Rng &>)
friend constexpr auto
operator|(Rng && rng, action_closure<ActionFn> act)
{
return aux::move(static_cast<ActionFn &&>(act)(rng));
}
#ifndef RANGES_WORKAROUND_CLANG_43400
template<typename Rng, typename ActionFn> // ******************************
friend constexpr auto // ******************************
operator|(Rng &, // ********* READ THIS **********
action_closure<ActionFn> const &) // ****** IF YOUR COMPILE *******
-> CPP_broken_friend_ret(Rng)( // ******** BREAKS HERE *********
requires range<Rng>) = delete; // ******************************
// **************************************************************************
// * When piping a range into an action, the range must be moved in. *
// **************************************************************************
#endif // RANGES_WORKAROUND_CLANG_43400
template<typename ActionFn, typename Pipeable>
friend constexpr auto operator|(action_closure<ActionFn> act, Pipeable pipe)
-> CPP_broken_friend_ret(action_closure<composed<Pipeable, ActionFn>>)(
requires (is_pipeable_v<Pipeable>))
{
return make_action_closure(compose(static_cast<Pipeable &&>(pipe),
static_cast<ActionFn &&>(act)));
}
template<typename Rng, typename ActionFn>
friend constexpr auto operator|=(Rng & rng, action_closure<ActionFn> act) //
-> CPP_broken_friend_ret(Rng &)(
requires range<Rng> && invocable<ActionFn, Rng &>)
{
static_cast<ActionFn &&>(act)(rng);
return rng;
}
// clang-format on
};
#ifdef RANGES_WORKAROUND_CLANG_43400
// clang-format off
namespace RANGES_ADL_BARRIER_FOR(action_closure_base)
{
template(typename Rng, typename ActionFn)( // *******************************
requires range<Rng>) // *******************************
constexpr Rng // ********** READ THIS **********
operator|(Rng &, // ******* IF YOUR COMPILE *******
action_closure<ActionFn> const &) // ********* BREAKS HERE *********
= delete; // *******************************
// ***************************************************************************
// * When piping a range into an action, the range must be moved in. *
// ***************************************************************************
} // namespace RANGES_ADL_BARRIER_FOR(action_closure_base)
// clang-format on
#endif // RANGES_WORKAROUND_CLANG_43400
template<typename ActionFn>
struct RANGES_EMPTY_BASES action_closure
: action_closure_base
, ActionFn
{
action_closure() = default;
constexpr explicit action_closure(ActionFn fn)
: ActionFn(static_cast<ActionFn &&>(fn))
{}
};
/// \cond
/// DEPRECATED STUFF
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
};
};
using action_access RANGES_DEPRECATED(
"action_access and actions::action<> are deprecated. Please "
"replace action<> with action_closure<> and discontinue use of "
"action_access.") = action_access_;
template<typename>
struct old_action_;
struct make_action_fn_
{
template<typename Fun>
constexpr old_action_<Fun> operator()(Fun fun) const
{
return old_action_<Fun>{static_cast<Fun &&>(fun)};
}
};
using make_action_fn RANGES_DEPRECATED(
"make_action_fn is deprecated. Please use "
"make_action_closure instead.") = make_action_fn_;
namespace
{
RANGES_DEPRECATED(
"make_action and actions::action<> has been deprecated. Please switch to "
"make_action_closure and action::action_closure.")
RANGES_INLINE_VAR constexpr auto & make_action =
static_const<make_action_fn_>::value;
} // namespace
template<typename Action>
struct old_action_ : pipeable_base
{
private:
Action act_;
friend pipeable_access;
public:
old_action_() = default;
constexpr explicit old_action_(Action a) noexcept(
std::is_nothrow_move_constructible<Action>::value)
: act_(detail::move(a))
{}
// Calling directly requires things are passed by reference.
template(typename Rng, typename... Rest)(
requires range<Rng> AND invocable<Action const &, Rng &, Rest...>)
invoke_result_t<Action const &, Rng &, Rest...> //
operator()(Rng & rng, Rest &&... rest) const
{
return invoke(act_, rng, static_cast<Rest &&>(rest)...);
}
// Currying overload.
// clang-format off
template(typename... Rest, typename A = Action)(
requires (sizeof...(Rest) != 0))
auto CPP_auto_fun(operator())(Rest &&... rest)(const)
(
return make_action_fn_{}(
action_access_::impl<A>::bind(act_,
static_cast<Rest &&>(rest)...))
)
// clang-format on
};
template<typename Action>
using action RANGES_DEPRECATED(
"The actions::action<> template is deprecated. Please switch to "
"action_closure") = old_action_<Action>;
/// \endcond
} // namespace actions
template<typename ActionFn>
RANGES_INLINE_VAR constexpr bool is_pipeable_v<actions::action_closure<ActionFn>> =
true;
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,68 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct adjacent_remove_if_fn
{
template(typename Pred, typename Proj = identity)(
requires (!range<Pred>))
constexpr auto operator()(Pred pred, Proj proj = {}) const
{
return make_action_closure(
bind_back(adjacent_remove_if_fn{}, std::move(pred), std::move(proj)));
}
template(typename Rng, typename Pred, typename Proj = identity)(
requires forward_range<Rng> AND
erasable_range<Rng, iterator_t<Rng>, sentinel_t<Rng>> AND
indirect_relation<Pred, projected<iterator_t<Rng>, Proj>> AND
permutable<iterator_t<Rng>>)
Rng operator()(Rng && rng, Pred pred, Proj proj = {}) const
{
auto i = adjacent_remove_if(rng, std::move(pred), std::move(proj));
erase(rng, std::move(i), end(rng));
return static_cast<Rng &&>(rng);
}
};
/// \relates actions::adjacent_remove_if_fn
RANGES_INLINE_VARIABLE(adjacent_remove_if_fn, adjacent_remove_if)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif // RANGES_V3_ACTION_ADJACENT_REMOVE_IF_HPP

View File

@ -0,0 +1,185 @@
/// \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>
#include <range/v3/detail/prologue.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
/// @{
// clang-format off
/// \concept semi_container
/// \brief The \c semi_container concept
/// \c std::array is a \c semi_container, native arrays are not.
template<typename T>
CPP_concept semi_container =
forward_range<T> && default_constructible<uncvref_t<T>> &&
movable<uncvref_t<T>> &&
!view_<T>;
/// \concept container_
/// \brief The \c container_ concept
/// \c std::vector is a container, \c std::array is not
template(typename T)(
concept (container_)(T),
constructible_from<
uncvref_t<T>,
detail::movable_input_iterator<range_value_t<T>>,
detail::movable_input_iterator<range_value_t<T>>>
);
/// \concept container
/// \brief The \c container concept
template<typename T>
CPP_concept container =
semi_container<T> &&
CPP_concept_ref(ranges::container_, T);
/// \concept reservable_
/// \brief The \c reservable_ concept
template<typename C>
CPP_requires(reservable_,
requires(C & c, C const & cc) //
(
c.reserve(ranges::size(c)),
cc.capacity(),
cc.max_size(),
concepts::requires_<same_as<decltype(cc.capacity()),
decltype(ranges::size(c))>>,
concepts::requires_<same_as<decltype(cc.max_size()),
decltype(ranges::size(c))>>
));
/// \concept reservable
/// \brief The \c reservable concept
template<typename C>
CPP_concept reservable =
container<C> && sized_range<C> && CPP_requires_ref(ranges::reservable_, C);
/// \concept reservable_with_assign_
/// \brief The \c reservable_with_assign_ concept
template<typename C, typename I>
CPP_requires(reservable_with_assign_,
requires(C & c, I i) //
(
c.assign(i, i)
));
/// \concept reservable_with_assign
/// \brief The \c reservable_with_assign concept
template<typename C, typename I>
CPP_concept reservable_with_assign =
reservable<C> && //
input_iterator<I> && //
CPP_requires_ref(ranges::reservable_with_assign_, C, I);
/// \concept random_access_reservable
/// \brief The \c random_access_reservable concept
template<typename C>
CPP_concept random_access_reservable =
reservable<C> && random_access_range<C>;
// clang-format on
/// \cond
namespace detail
{
template(typename T)(
requires container<T>)
std::true_type is_lvalue_container_like(T &) noexcept
{
return {};
}
template(typename T)(
requires container<T>)
meta::not_<std::is_rvalue_reference<T>> //
is_lvalue_container_like(reference_wrapper<T>) noexcept
{
return {};
}
template(typename T)(
requires container<T>)
std::true_type is_lvalue_container_like(std::reference_wrapper<T>) noexcept
{
return {};
}
template(typename T)(
requires container<T>)
std::true_type is_lvalue_container_like(ref_view<T>) noexcept
{
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
/// \concept lvalue_container_like_
/// \brief The \c lvalue_container_like_ concept
template(typename T)(
concept (lvalue_container_like_)(T),
implicitly_convertible_to<detail::is_lvalue_container_like_t<T>, std::true_type>
);
/// \concept lvalue_container_like
/// \brief The \c lvalue_container_like concept
template<typename T>
CPP_concept lvalue_container_like =
forward_range<T> &&
CPP_concept_ref(ranges::lvalue_container_like_, T);
// clang-format on
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,65 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct drop_fn
{
template(typename Int)(
requires detail::integer_like_<Int>)
constexpr auto operator()(Int n) const
{
RANGES_EXPECT(n >= Int(0));
return make_action_closure(bind_back(drop_fn{}, n));
}
template(typename Rng)(
requires forward_range<Rng> AND
erasable_range<Rng &, iterator_t<Rng>, iterator_t<Rng>>)
Rng operator()(Rng && rng, range_difference_t<Rng> n) const
{
RANGES_EXPECT(n >= 0);
ranges::actions::erase(
rng, begin(rng), ranges::next(begin(rng), n, end(rng)));
return static_cast<Rng &&>(rng);
}
};
/// \relates actions::drop_fn
RANGES_INLINE_VARIABLE(drop_fn, drop)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,64 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct drop_while_fn
{
template(typename Fun)(
requires (!range<Fun>))
constexpr auto operator()(Fun fun) const
{
return make_action_closure(bind_back(drop_while_fn{}, std::move(fun)));
}
template(typename Rng, typename Fun)(
requires forward_range<Rng> AND
indirect_unary_predicate<Fun, iterator_t<Rng>> AND
erasable_range<Rng &, iterator_t<Rng>, iterator_t<Rng>>)
Rng operator()(Rng && rng, Fun fun) const
{
ranges::actions::erase(
rng, begin(rng), find_if_not(begin(rng), end(rng), std::move(fun)));
return static_cast<Rng &&>(rng);
}
};
/// \relates actions::drop_while_fn
RANGES_INLINE_VARIABLE(drop_while_fn, drop_while)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,84 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \cond
namespace adl_erase_detail
{
template(typename Cont, typename I, typename S)(
requires lvalue_container_like<Cont> AND forward_iterator<I> AND
sentinel_for<S, I>)
auto erase(Cont && cont, I first, S last) //
-> decltype(unwrap_reference(cont).erase(first, last))
{
return unwrap_reference(cont).erase(first, last);
}
struct erase_fn
{
template(typename Rng, typename I, typename S)(
requires range<Rng> AND forward_iterator<I> AND sentinel_for<S, I>)
auto operator()(Rng && rng, I first, S last) const
-> decltype(erase((Rng &&) rng, first, last))
{
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
/// \concept erasable_range_
/// \brief The \c erasable_range_ concept
template<typename Rng, typename I, typename S>
CPP_requires(erasable_range_,
requires(Rng && rng, I first, S last)
(
ranges::erase((Rng &&) rng, first, last)
)
);
/// \concept erasable_range
/// \brief The \c erasable_range concept
template<typename Rng, typename I, typename S>
CPP_concept erasable_range =
range<Rng> && CPP_requires_ref(ranges::erasable_range_, Rng, I, S);
// clang-format on
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,299 @@
/// \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>
#include <range/v3/detail/prologue.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)(
requires lvalue_container_like<Cont> AND
(!range<T> && constructible_from<range_value_t<Cont>, T>)) //
insert_result_t<Cont &, T> insert(Cont && cont, T && t)
{
return unwrap_reference(cont).insert(static_cast<T &&>(t));
}
template(typename Cont, typename I, typename S)(
requires lvalue_container_like<Cont> AND sentinel_for<S, I> AND (!range<S>))
insert_result_t<Cont &, detail::cpp17_iterator_t<I, S>,
detail::cpp17_iterator_t<I, S>>
insert(Cont && cont, I i, S j)
{
return unwrap_reference(cont).insert(detail::cpp17_iterator_t<I, S>{i},
detail::cpp17_iterator_t<I, S>{j});
}
template(typename Cont, typename Rng)(
requires lvalue_container_like<Cont> AND range<Rng>)
insert_result_t<Cont &, detail::range_cpp17_iterator_t<Rng>,
detail::range_cpp17_iterator_t<Rng>>
insert(Cont && cont, Rng && 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)(
requires lvalue_container_like<Cont> AND input_iterator<I> AND
(!range<T> && constructible_from<range_value_t<Cont>, T>)) //
insert_result_t<Cont &, I, T> insert(Cont && cont, I p, T && t)
{
return unwrap_reference(cont).insert(p, static_cast<T &&>(t));
}
template(typename Cont, typename I, typename N, typename T)(
requires lvalue_container_like<Cont> AND input_iterator<I> AND
integral<N> AND constructible_from<range_value_t<Cont>, T>)
insert_result_t<Cont &, I, N, T> insert(Cont && cont, I p, N n, T && 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)(
requires container<Cont> AND input_iterator<P> AND
random_access_reservable<Cont>)
iterator_t<Cont> insert_reserve_helper(
Cont & cont, P const p, range_size_t<Cont> const delta)
{
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)(
requires sentinel_for<S, I> AND (!range<S>)) //
auto insert_impl(Cont && cont, P p, I i, S j, std::false_type)
-> decltype(unwrap_reference(cont).insert(
p, cpp17_iterator_t<I, S>{i}, cpp17_iterator_t<I, S>{j}))
{
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)(
requires sized_sentinel_for<S, I> AND random_access_reservable<Cont> AND
(!range<S>)) //
auto insert_impl(Cont && cont_, P p, I i, S j, std::true_type)
-> decltype(unwrap_reference(cont_).insert(
ranges::begin(unwrap_reference(cont_)), cpp17_iterator_t<I, S>{i},
cpp17_iterator_t<I, S>{j}))
{
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)(
requires range<Rng>)
auto insert_impl(Cont && cont, I p, Rng && rng, std::false_type)
-> decltype(unwrap_reference(cont).insert(
p, range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
range_cpp17_iterator_t<Rng>{ranges::end(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)(
requires random_access_reservable<Cont> AND sized_range<Rng>)
auto insert_impl(Cont && cont_, I p, Rng && rng, std::true_type)
-> 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)}))
{
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)(
requires lvalue_container_like<Cont> AND input_iterator<P> AND
sentinel_for<S, I> AND
(!range<S>)) //
auto insert(Cont && cont, P p, I i, S j) //
-> decltype(detail::insert_impl(
static_cast<Cont &&>(cont),
static_cast<P &&>(p),
static_cast<I &&>(i),
static_cast<S &&>(j),
meta::bool_<random_access_reservable<Cont> && //
sized_sentinel_for<S, I>>{}))
{
return detail::insert_impl(static_cast<Cont &&>(cont),
static_cast<P &&>(p),
static_cast<I &&>(i),
static_cast<S &&>(j),
meta::bool_<random_access_reservable<Cont> &&
sized_sentinel_for<S, I>>{});
}
template(typename Cont, typename I, typename Rng)(
requires lvalue_container_like<Cont> AND input_iterator<I> AND range<Rng>)
auto insert(Cont && cont, I p, Rng && rng)
-> decltype(detail::insert_impl(
static_cast<Cont &&>(cont), std::move(p), static_cast<Rng &&>(rng),
meta::bool_<random_access_reservable<Cont> && sized_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)(
requires range<Rng> AND
(!range<T>) AND constructible_from<range_value_t<Rng>, T>)
insert_result_t<Rng, T> operator()(Rng && rng, T && t) const
{
return insert(static_cast<Rng &&>(rng), static_cast<T &&>(t));
}
template(typename Rng, typename Rng2)(
requires range<Rng> AND range<Rng2>)
insert_result_t<Rng, Rng2> operator()(Rng && rng, Rng2 && rng2) const
{
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)(
requires range<Rng>)
insert_result_t<Rng, std::initializer_list<T> &> //
operator()(Rng && rng, std::initializer_list<T> rng2) const
{
return insert(static_cast<Rng &&>(rng), rng2);
}
template(typename Rng, typename I, typename S)(
requires range<Rng> AND sentinel_for<S, I> AND (!range<S>)) //
insert_result_t<Rng, I, S> operator()(Rng && rng, I i, S j) const
{
return insert(static_cast<Rng &&>(rng), std::move(i), std::move(j));
}
template(typename Rng, typename I, typename T)(
requires range<Rng> AND input_iterator<I> AND
(!range<T>) AND constructible_from<range_value_t<Rng>, T>)
insert_result_t<Rng, I, T> operator()(Rng && rng, I p, T && t) const
{
return insert(
static_cast<Rng &&>(rng), std::move(p), static_cast<T &&>(t));
}
template(typename Rng, typename I, typename Rng2)(
requires range<Rng> AND input_iterator<I> AND range<Rng2>)
insert_result_t<Rng, I, Rng2> operator()(Rng && rng, I p, Rng2 && rng2) const
{
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)(
requires range<Rng> AND input_iterator<I>)
insert_result_t<Rng, I, std::initializer_list<T> &> //
operator()(Rng && rng, I p, std::initializer_list<T> rng2) const
{
return insert(static_cast<Rng &&>(rng), std::move(p), rng2);
}
template(typename Rng, typename I, typename N, typename T)(
requires range<Rng> AND input_iterator<I> AND integral<N> AND
(!range<T>) AND constructible_from<range_value_t<Rng>, T>)
insert_result_t<Rng, I, N, T> operator()(Rng && rng, I p, N n, T && t) const
{
return insert(
static_cast<Rng &&>(rng), std::move(p), n, static_cast<T &&>(t));
}
template(typename Rng, typename P, typename I, typename S)(
requires range<Rng> AND input_iterator<P> AND sentinel_for<S, I> AND
(!range<S>)) //
insert_result_t<Rng, P, I, S> operator()(Rng && rng, P p, I i, S j) const
{
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
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,68 @@
/// \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>
#include <range/v3/detail/prologue.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
{
template(typename Rng)(
requires input_range<Rng> AND input_range<range_value_t<Rng>> AND
semiregular<join_action_value_t_<Rng>>)
join_action_value_t_<Rng> operator()(Rng && rng) const
{
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;
}
};
/// \relates actions::join_fn
/// \sa action_closure
RANGES_INLINE_VARIABLE(action_closure<join_fn>, join)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,149 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
/// \cond
namespace adl_push_back_detail
{
/// \endcond
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)(
requires lvalue_container_like<Cont> AND
(!range<T>) AND constructible_from<range_value_t<Cont>, T>)
push_back_t<Cont, T> push_back(Cont && cont, T && t)
{
unwrap_reference(cont).push_back(static_cast<T &&>(t));
}
template(typename Cont, typename Rng)(
requires lvalue_container_like<Cont> AND range<Rng>)
insert_t<Cont, Rng> push_back(Cont && cont, Rng && rng)
{
ranges::insert(cont, end(cont), static_cast<Rng &&>(rng));
}
/// \cond
// clang-format off
/// \concept can_push_back_frag_
/// \brief The \c can_push_back_frag_ concept
template<typename Rng, typename T>
CPP_requires(can_push_back_frag_,
requires(Rng && rng, T && t) //
(
push_back(rng, (T &&) t)
));
/// \concept can_push_back_
/// \brief The \c can_push_back_ concept
template<typename Rng, typename T>
CPP_concept can_push_back_ =
CPP_requires_ref(adl_push_back_detail::can_push_back_frag_, Rng, T);
// clang-format on
/// \endcond
struct push_back_fn
{
template<typename T>
constexpr auto operator()(T && val) const
{
return make_action_closure(
bind_back(push_back_fn{}, static_cast<T &&>(val)));
}
template(typename T)(
requires range<T &>)
constexpr auto operator()(T & t) const
{
return make_action_closure(
bind_back(push_back_fn{}, detail::reference_wrapper_<T>(t)));
}
template<typename T>
constexpr auto operator()(std::initializer_list<T> val) const
{
return make_action_closure(bind_back(push_back_fn{}, val));
}
template(typename Rng, typename T)(
requires input_range<Rng> AND can_push_back_<Rng, T> AND
(range<T> || constructible_from<range_value_t<Rng>, T>)) //
Rng operator()(Rng && rng, T && t) const //
{
push_back(rng, static_cast<T &&>(t));
return static_cast<Rng &&>(rng);
}
template(typename Rng, typename T)(
requires input_range<Rng> AND
can_push_back_<Rng, std::initializer_list<T>> AND
constructible_from<range_value_t<Rng>, T const &>)
Rng operator()(Rng && rng, std::initializer_list<T> t) const //
{
push_back(rng, t);
return static_cast<Rng &&>(rng);
}
/// \cond
template<typename Rng, typename T>
invoke_result_t<push_back_fn, Rng, T &> //
operator()(Rng && rng, detail::reference_wrapper_<T> r) const
{
return (*this)(static_cast<Rng &&>(rng), r.get());
}
/// \endcond
};
/// \cond
} // namespace adl_push_back_detail
/// \endcond
namespace actions
{
RANGES_INLINE_VARIABLE(adl_push_back_detail::push_back_fn, push_back)
} // namespace actions
using actions::push_back;
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,149 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
/// \cond
namespace adl_push_front_detail
{
/// \endcond
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)(
requires lvalue_container_like<Cont> AND
(!range<T>) AND constructible_from<range_value_t<Cont>, T>)
push_front_t<Cont, T> push_front(Cont && cont, T && t)
{
unwrap_reference(cont).push_front(static_cast<T &&>(t));
}
template(typename Cont, typename Rng)(
requires lvalue_container_like<Cont> AND range<Rng>)
insert_t<Cont, Rng> push_front(Cont && cont, Rng && rng)
{
ranges::insert(cont, begin(cont), static_cast<Rng &&>(rng));
}
/// \cond
// clang-format off
/// \concept can_push_front_frag_
/// \brief The \c can_push_front_frag_ concept
template<typename Rng, typename T>
CPP_requires(can_push_front_frag_,
requires(Rng && rng, T && t) //
(
push_front(rng, (T &&) t)
));
/// \concept can_push_front_
/// \brief The \c can_push_front_ concept
template<typename Rng, typename T>
CPP_concept can_push_front_ =
CPP_requires_ref(adl_push_front_detail::can_push_front_frag_, Rng, T);
// clang-format on
/// \endcond
struct push_front_fn
{
template<typename T>
constexpr auto operator()(T && val) const
{
return make_action_closure(
bind_back(push_front_fn{}, static_cast<T &&>(val)));
}
template<typename T>
constexpr auto operator()(std::initializer_list<T> val) const
{
return make_action_closure(bind_back(push_front_fn{}, val));
}
template(typename T)(
requires range<T &>)
constexpr auto operator()(T & t) const
{
return make_action_closure(
bind_back(push_front_fn{}, detail::reference_wrapper_<T>(t)));
}
template(typename Rng, typename T)(
requires input_range<Rng> AND can_push_front_<Rng, T> AND
(range<T> || constructible_from<range_value_t<Rng>, T>)) //
Rng operator()(Rng && rng, T && t) const //
{
push_front(rng, static_cast<T &&>(t));
return static_cast<Rng &&>(rng);
}
template(typename Rng, typename T)(
requires input_range<Rng> AND
can_push_front_<Rng, std::initializer_list<T>> AND
constructible_from<range_value_t<Rng>, T const &>)
Rng operator()(Rng && rng, std::initializer_list<T> t) const //
{
push_front(rng, t);
return static_cast<Rng &&>(rng);
}
/// \cond
template<typename Rng, typename T>
invoke_result_t<push_front_fn, Rng, T &> //
operator()(Rng && rng, detail::reference_wrapper_<T> r) const
{
return (*this)(static_cast<Rng &&>(rng), r.get());
}
/// \endcond
};
/// \cond
} // namespace adl_push_front_detail
/// \endcond
namespace actions
{
RANGES_INLINE_VARIABLE(adl_push_front_detail::push_front_fn, push_front)
} // namespace actions
using actions::push_front;
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,74 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct remove_fn
{
template(typename V, typename P)(
requires (!range<V>))
constexpr auto operator()(V && value, P proj) const
{
return make_action_closure(
bind_back(remove_fn{}, static_cast<V &&>(value), std::move(proj)));
}
template<typename V>
constexpr auto operator()(V && value) const
{
return make_action_closure(
bind_back(remove_fn{}, static_cast<V &&>(value), identity{}));
}
template(typename Rng, typename V, typename P = identity)(
requires forward_range<Rng> AND permutable<iterator_t<Rng>> AND
erasable_range<Rng, iterator_t<Rng>, sentinel_t<Rng>> AND
indirect_relation<equal_to, projected<iterator_t<Rng>, P>,
V const *>)
Rng operator()(Rng && rng, V const & value, P proj = {}) const
{
auto it = ranges::remove(rng, value, std::move(proj));
ranges::erase(rng, it, ranges::end(rng));
return static_cast<Rng &&>(rng);
}
};
/// \relates actions::remove_fn
RANGES_INLINE_VARIABLE(remove_fn, remove)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,70 @@
/// \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>
#include <range/v3/detail/prologue.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
{
template(typename C, typename P = identity)(
requires (!range<C>))
constexpr auto operator()(C pred, P proj = P{}) const
{
return make_action_closure(
bind_back(remove_if_fn{}, std::move(pred), std::move(proj)));
}
template(typename Rng, typename C, typename P = identity)(
requires forward_range<Rng> AND
erasable_range<Rng &, iterator_t<Rng>, iterator_t<Rng>> AND
permutable<iterator_t<Rng>> AND
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>)
Rng operator()(Rng && rng, C pred, P proj = P{}) const
{
auto it = ranges::remove_if(rng, std::move(pred), std::move(proj));
ranges::erase(rng, it, ranges::end(rng));
return static_cast<Rng &&>(rng);
}
};
/// \relates actions::remove_if_fn
RANGES_INLINE_VARIABLE(remove_if_fn, remove_if)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,55 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
/// Reversed the source range in-place.
struct reverse_fn
{
template(typename Rng)(
requires bidirectional_range<Rng> AND permutable<iterator_t<Rng>>)
Rng operator()(Rng && rng) const
{
ranges::reverse(rng);
return static_cast<Rng &&>(rng);
}
};
/// \relates actions::reverse_fn
/// \sa action_closure
RANGES_INLINE_VARIABLE(action_closure<reverse_fn>, reverse)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,83 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct shuffle_fn
{
template(typename Gen)(
requires uniform_random_bit_generator<Gen>)
constexpr auto operator()(Gen & gen) const
{
return make_action_closure(
bind_back(shuffle_fn{}, detail::reference_wrapper_<Gen>(gen)));
}
template(typename Gen)(
requires uniform_random_bit_generator<Gen>)
constexpr auto operator()(Gen && gen) const
{
return make_action_closure(
bind_back(shuffle_fn{}, static_cast<Gen &&>(gen)));
}
template(typename Rng, typename Gen)(
requires random_access_range<Rng> AND permutable<iterator_t<Rng>> AND
uniform_random_bit_generator<std::remove_reference_t<Gen>> AND
convertible_to<invoke_result_t<Gen &>, range_difference_t<Rng>>)
Rng operator()(Rng && rng, Gen && gen) const
{
ranges::shuffle(rng, static_cast<Gen &&>(gen));
return static_cast<Rng &&>(rng);
}
/// \cond
template<typename Rng, typename T>
invoke_result_t<shuffle_fn, Rng, T &> //
operator()(Rng && rng, detail::reference_wrapper_<T> r) const
{
return (*this)(static_cast<Rng &&>(rng), r.get());
}
/// \endcond
};
/// \relates actions::shuffle_fn
/// \sa `action_closure`
RANGES_INLINE_VARIABLE(shuffle_fn, shuffle)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,154 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct slice_fn
{
private:
template<typename D>
using diff_t = range_difference_t<D>;
public:
// Overloads for the pipe syntax: rng | actions::slice(from, to)
template(typename D)(
requires integral<D>)
constexpr auto operator()(D from, D to) const
{
return make_action_closure(bind_back(slice_fn{}, from, to));
}
template(typename D)(
requires integral<D>)
constexpr auto operator()(D from, detail::from_end_<D> to) const
{
return make_action_closure(bind_back(slice_fn{}, from, to));
}
template(typename D)(
requires integral<D>)
constexpr auto operator()(detail::from_end_<D> from, detail::from_end_<D> to)
const
{
return make_action_closure(bind_back(slice_fn{}, from, to));
}
template(typename D)(
requires integral<D>)
constexpr auto operator()(D from, end_fn const & to) const
{
return make_action_closure(bind_back(slice_fn{}, from, to));
}
template(typename D)(
requires integral<D>)
constexpr auto operator()(detail::from_end_<D> from, end_fn const & to) const
{
return make_action_closure(bind_back(slice_fn{}, from, to));
}
template(typename Rng, typename I = iterator_t<Rng>)(
requires forward_range<Rng> AND erasable_range<Rng &, I, I>)
Rng operator()(Rng && rng, diff_t<Rng> from, diff_t<Rng> to) const
{
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>)(
requires bidirectional_range<Rng> AND erasable_range<Rng &, I, I>)
Rng operator()(Rng && rng,
diff_t<Rng> from,
detail::from_end_<diff_t<Rng>> to) const
{
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>)(
requires bidirectional_range<Rng> AND erasable_range<Rng &, I, I>)
Rng operator()(Rng && rng,
detail::from_end_<diff_t<Rng>> from,
detail::from_end_<diff_t<Rng>> to) const
{
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>)(
requires forward_range<Rng> AND erasable_range<Rng &, I, I>)
Rng operator()(Rng && rng, diff_t<Rng> from, end_fn const &) const
{
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>)(
requires bidirectional_range<Rng> AND erasable_range<Rng &, I, I>)
Rng operator()(Rng && rng,
detail::from_end_<diff_t<Rng>> from,
end_fn const &) const
{
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);
}
};
/// \relates actions::slice_fn
RANGES_INLINE_VARIABLE(slice_fn, slice)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,64 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct sort_fn
{
template(typename C, typename P = identity)(
requires (!range<C>))
constexpr auto operator()(C pred, P proj = {}) const
{
return make_action_closure(
bind_back(sort_fn{}, std::move(pred), std::move(proj)));
}
template(typename Rng, typename C = less, typename P = identity)(
requires forward_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
Rng operator()(Rng && rng, C pred = {}, P proj = {}) const
{
ranges::sort(rng, std::move(pred), std::move(proj));
return static_cast<Rng &&>(rng);
}
};
/// \relates actions::sort_fn
/// \sa action_closure
RANGES_INLINE_VARIABLE(action_closure<sort_fn>, sort)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,106 @@
/// \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/functional/bind_back.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/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct split_fn
{
template<typename Rng>
using split_value_t =
meta::if_c<(bool)ranges::container<Rng>, //
uncvref_t<Rng>, std::vector<range_value_t<Rng>>>;
template(typename T)(
requires range<T &>)
constexpr auto operator()(T & t) const
{
return make_action_closure(
bind_back(split_fn{}, detail::reference_wrapper_<T>(t)));
}
template<typename T>
constexpr auto operator()(T && t) const
{
return make_action_closure(bind_back(split_fn{}, static_cast<T &&>(t)));
}
// 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)(
requires input_range<Rng> AND indirectly_comparable<
iterator_t<Rng>, range_value_t<Rng> const *, ranges::equal_to>)
std::vector<split_value_t<Rng>> //
operator()(Rng && rng, range_value_t<Rng> val) const
{
return views::split(rng, std::move(val)) |
to<std::vector<split_value_t<Rng>>>();
}
template(typename Rng, typename Pattern)(
requires input_range<Rng> AND viewable_range<Pattern> AND
forward_range<Pattern> AND
indirectly_comparable<
iterator_t<Rng>,
iterator_t<Pattern>,
ranges::equal_to> AND
(forward_range<Rng> || detail::tiny_range<Pattern>)) //
std::vector<split_value_t<Rng>> operator()(Rng && rng, Pattern && pattern)
const
{
return views::split(rng, static_cast<Pattern &&>(pattern)) |
to<std::vector<split_value_t<Rng>>>();
}
/// \cond
template<typename Rng, typename T>
invoke_result_t<split_fn, Rng, T &> //
operator()(Rng && rng, detail::reference_wrapper_<T> r) const
{
return (*this)(static_cast<Rng &&>(rng), r.get());
}
/// \endcond
};
/// \relates actions::split_fn
RANGES_INLINE_VARIABLE(split_fn, split)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,90 @@
/// \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/bind_back.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/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct split_when_fn
{
template<typename Rng>
using split_value_t =
meta::if_c<(bool)ranges::container<Rng>, //
uncvref_t<Rng>, std::vector<range_value_t<Rng>>>;
template<typename Fun>
constexpr auto operator()(Fun fun) const
{
return make_action_closure(
bind_back(split_when_fn{}, static_cast<Fun &&>(fun)));
}
// 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)(
requires forward_range<Rng> AND
invocable<Fun &, iterator_t<Rng>, sentinel_t<Rng>> AND
invocable<Fun &, iterator_t<Rng>, iterator_t<Rng>> AND
copy_constructible<Fun> AND
convertible_to<invoke_result_t<Fun &, iterator_t<Rng>,
sentinel_t<Rng>>,
std::pair<bool, iterator_t<Rng>>>)
std::vector<split_value_t<Rng>> operator()(Rng && rng, Fun fun) const
{
return views::split_when(rng, std::move(fun)) |
to<std::vector<split_value_t<Rng>>>();
}
template(typename Rng, typename Fun)(
requires forward_range<Rng> AND
predicate<Fun const &, range_reference_t<Rng>> AND
copy_constructible<Fun>)
std::vector<split_value_t<Rng>> operator()(Rng && rng, Fun fun) const
{
return views::split_when(rng, std::move(fun)) |
to<std::vector<split_value_t<Rng>>>();
}
};
/// \relates actions::split_when_fn
RANGES_INLINE_VARIABLE(split_when_fn, split_when)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,64 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct stable_sort_fn
{
template(typename C, typename P = identity)(
requires (!range<C>))
constexpr auto operator()(C pred, P proj = P{}) const
{
return make_action_closure(
bind_back(stable_sort_fn{}, std::move(pred), std::move(proj)));
}
template(typename Rng, typename C = less, typename P = identity)(
requires forward_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
Rng operator()(Rng && rng, C pred = C{}, P proj = P{}) const
{
ranges::stable_sort(rng, std::move(pred), std::move(proj));
return static_cast<Rng &&>(rng);
}
};
/// \relates actions::stable_sort_fn
/// \sa action_closure
RANGES_INLINE_VARIABLE(action_closure<stable_sort_fn>, stable_sort)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,79 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct stride_fn
{
template(typename D)(
requires detail::integer_like_<D>)
constexpr auto operator()(D step) const
{
return make_action_closure(bind_back(stride_fn{}, step));
}
template(typename Rng, typename D = range_difference_t<Rng>)(
requires forward_range<Rng> AND
erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>> AND
permutable<iterator_t<Rng>>)
Rng operator()(Rng && rng, range_difference_t<Rng> const step) const
{
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);
}
};
/// \relates actions::stride_fn
RANGES_INLINE_VARIABLE(stride_fn, stride)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,64 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct take_fn
{
template(typename Int)(
requires detail::integer_like_<Int>)
constexpr auto operator()(Int n) const
{
return make_action_closure(bind_back(take_fn{}, n));
}
template(typename Rng)(
requires forward_range<Rng> AND
erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>>)
Rng operator()(Rng && rng, range_difference_t<Rng> n) const
{
RANGES_EXPECT(n >= 0);
ranges::actions::erase(
rng, ranges::next(begin(rng), n, end(rng)), end(rng));
return static_cast<Rng &&>(rng);
}
};
/// \relates actions::take_fn
RANGES_INLINE_VARIABLE(take_fn, take)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,64 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct take_while_fn
{
template(typename Fun)(
requires (!range<Fun>))
constexpr auto operator()(Fun fun) const
{
return make_action_closure(bind_back(take_while_fn{}, std::move(fun)));
}
template(typename Rng, typename Fun)(
requires forward_range<Rng> AND
erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>> AND
indirect_unary_predicate<Fun, iterator_t<Rng>>)
Rng operator()(Rng && rng, Fun fun) const
{
ranges::actions::erase(
rng, find_if_not(begin(rng), end(rng), std::move(fun)), end(rng));
return static_cast<Rng &&>(rng);
}
};
/// \relates actions::take_while_fn
RANGES_INLINE_VARIABLE(take_while_fn, take_while)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,65 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct transform_fn
{
template(typename F, typename P = identity)(
requires (!range<F>))
constexpr auto operator()(F fun, P proj = P{}) const
{
return make_action_closure(
bind_back(transform_fn{}, std::move(fun), std::move(proj)));
}
template(typename Rng, typename F, typename P = identity)(
requires input_range<Rng> AND copy_constructible<F> AND
indirectly_writable<
iterator_t<Rng>,
indirect_result_t<F &, projected<iterator_t<Rng>, P>>>)
Rng operator()(Rng && rng, F fun, P proj = P{}) const
{
ranges::transform(rng, begin(rng), std::move(fun), std::move(proj));
return static_cast<Rng &&>(rng);
}
};
/// \relates actions::transform_fn
RANGES_INLINE_VARIABLE(transform_fn, transform)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,68 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct unique_fn
{
template(typename C, typename P = identity)(
requires (!range<C>))
constexpr auto operator()(C pred, P proj = P{}) const
{
return make_action_closure(
bind_back(unique_fn{}, std::move(pred), std::move(proj)));
}
template(typename Rng, typename C = equal_to, typename P = identity)(
requires forward_range<Rng> AND
erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>> AND
sortable<iterator_t<Rng>, C, P>)
Rng operator()(Rng && rng, C pred = C{}, P proj = P{}) const
{
auto it = ranges::unique(rng, std::move(pred), std::move(proj));
ranges::erase(rng, it, end(rng));
return static_cast<Rng &&>(rng);
}
};
/// \relates detail::unique_fn
/// \sa action_closure
RANGES_INLINE_VARIABLE(action_closure<unique_fn>, unique)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,73 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct unstable_remove_if_fn
{
template(typename C, typename P = identity)(
requires (!range<C>))
constexpr auto operator()(C pred, P proj = P{}) const
{
return make_action_closure(
bind_back(unstable_remove_if_fn{}, std::move(pred), std::move(proj)));
}
template(typename Rng, typename C, typename P = identity)(
requires bidirectional_range<Rng> AND common_range<Rng> AND
permutable<iterator_t<Rng>> AND
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>> AND
erasable_range<Rng, iterator_t<Rng>, iterator_t<Rng>>)
Rng operator()(Rng && rng, C pred, P proj = P{}) const
{
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);
}
};
/// \sa `actions::unstable_remove_if_fn`
RANGES_INLINE_VARIABLE(unstable_remove_if_fn, unstable_remove_if)
} // namespace actions
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif // RANGES_V3_ACTION_UNSTABLE_REMOVE_IF_HPP

View File

@ -0,0 +1,106 @@
/// \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/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/contains.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/fold.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>
#include <range/v3/detail/config.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>
#endif

View File

@ -0,0 +1,75 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(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)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_relation<C, projected<I, P>>)
constexpr I RANGES_FUNC(adjacent_find)(I first, S last, C pred = C{}, P proj = 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)(
requires forward_range<Rng> AND
indirect_relation<C, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(adjacent_find)(Rng && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(adjacent_find)
namespace cpp20
{
using ranges::adjacent_find;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif // RANGE_ALGORITHM_ADJACENT_FIND_HPP

View File

@ -0,0 +1,92 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(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)(
requires permutable<I> AND sentinel_for<S, I> AND
indirect_relation<Pred, projected<I, Proj>>)
constexpr I RANGES_FUNC(adjacent_remove_if)(I first, S last, Pred pred = {}, Proj proj = {})
{
first = adjacent_find(std::move(first), last, ranges::ref(pred), ranges::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)(
requires forward_range<Rng> AND
indirect_relation<Pred, projected<iterator_t<Rng>, Proj>> AND
permutable<iterator_t<Rng>>)
constexpr borrowed_iterator_t<Rng>
RANGES_FUNC(adjacent_remove_if)(Rng && rng, Pred pred, Proj proj = {}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(adjacent_remove_if)
namespace cpp20
{
using ranges::adjacent_remove_if;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif // RANGES_V3_ALGORITHM_ADJACENT_REMOVE_IF_HPP

View File

@ -0,0 +1,69 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(all_of)
/// \brief function template \c all_of
template(typename I, typename S, typename F, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<F, projected<I, P>>)
constexpr bool RANGES_FUNC(all_of)(I first, S last, F pred, P proj = P{}) //
{
for(; first != last; ++first)
if(!invoke(pred, invoke(proj, *first)))
break;
return first == last;
}
/// \overload
template(typename Rng, typename F, typename P = identity)(
requires input_range<Rng> AND
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>)
constexpr bool RANGES_FUNC(all_of)(Rng && rng, F pred, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(all_of)
namespace cpp20
{
using ranges::all_of;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,70 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(any_of)
/// \brief function template \c any_of
template(typename I, typename S, typename F, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<F, projected<I, P>>)
constexpr bool RANGES_FUNC(any_of)(I first, S last, F pred, P proj = P{}) //
{
for(; first != last; ++first)
if(invoke(pred, invoke(proj, *first)))
return true;
return false;
}
/// \overload
template(typename Rng, typename F, typename P = identity)(
requires input_range<Rng> AND
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>)
constexpr bool RANGES_FUNC(any_of)(Rng && rng, F pred, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(any_of)
namespace cpp20
{
using ranges::any_of;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,92 @@
/// \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/functional/reference_wrapper.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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
namespace aux
{
struct equal_range_n_fn
{
template(typename I, typename V, typename R = less, typename P = identity)(
requires forward_iterator<I> AND
indirect_strict_weak_order<R, V const *, projected<I, P>>)
constexpr subrange<I> operator()(I first,
iter_difference_t<I> dist,
V const & val,
R pred = R{},
P proj = P{}) const
{
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,
ranges::ref(pred),
ranges::ref(proj)),
upper_bound_n(ranges::next(middle),
dist - (half + 1),
val,
ranges::ref(pred),
ranges::ref(proj))};
}
} while(0 != dist);
}
return {first, first};
}
};
RANGES_INLINE_VARIABLE(equal_range_n_fn, equal_range_n)
} // namespace aux
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,82 @@
/// \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>
#include <range/v3/detail/prologue.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>
constexpr bool operator()(T && t) const
{
return invoke(pred_, static_cast<T &&>(t), val_);
}
};
template<typename Pred, typename Val>
constexpr 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)(
requires forward_iterator<I> AND
indirect_strict_weak_order<C, V const *, projected<I, P>>)
constexpr I operator()(I first,
iter_difference_t<I> d,
V const & val,
C pred = C{},
P proj = P{}) const
{
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
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,115 @@
/// \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>
#include <range/v3/detail/prologue.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)(
requires mergeable<I0, I1, O, C, P0, P1>)
merge_n_result<I0, I1, O> 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
{
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
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,74 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
namespace aux
{
struct merge_n_with_buffer_fn
{
template(typename I, typename B, typename C = less, typename P = identity)(
requires same_as<iter_common_reference_t<I>,
iter_common_reference_t<B>> AND
indirectly_copyable<I, B> AND mergeable<B, I, I, C, P, P>)
I operator()(I begin0,
iter_difference_t<I> n0,
I begin1,
iter_difference_t<I> n1,
B buff,
C r = C{},
P p = P{}) const
{
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
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,65 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
namespace aux
{
struct partition_point_n_fn
{
template(typename I, typename C, typename P = identity)(
requires forward_iterator<I> AND
indirect_unary_predicate<C, projected<I, P>>)
constexpr I operator()(I first,
iter_difference_t<I> d,
C pred,
P proj = P{}) const //
{
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
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,73 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
namespace aux
{
struct sort_n_with_buffer_fn
{
template(typename I, typename B, typename C = less, typename P = identity)(
requires same_as<iter_common_reference_t<I>,
iter_common_reference_t<B>> AND
indirectly_copyable<I, B> AND mergeable<B, I, I, C, P, P>)
I operator()(I first, iter_difference_t<I> n, B buff, C r = C{}, P p = P{})
const
{
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
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,87 @@
/// \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>
#include <range/v3/detail/prologue.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>
constexpr bool operator()(T && t) const
{
return !invoke(pred_, val_, static_cast<T &&>(t));
}
};
template<typename Pred, typename Val>
constexpr 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)(
requires forward_iterator<I> AND
indirect_strict_weak_order<C, V const *, projected<I, P>>)
constexpr I operator()(I first,
iter_difference_t<I> d,
V const & val,
C pred = C{},
P proj = P{}) const
{
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
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,81 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(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)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, V const *, projected<I, P>>)
constexpr bool RANGES_FUNC(binary_search)(
I first, S last, V const & val, C pred = C{}, P proj = P{})
{
first =
lower_bound(std::move(first), last, val, ranges::ref(pred), ranges::ref(proj));
return first != last && !invoke(pred, val, invoke(proj, *first));
}
/// \overload
template(typename Rng, typename V, typename C = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<C, V const *, projected<iterator_t<Rng>, P>>)
constexpr bool RANGES_FUNC(binary_search)(
Rng && rng, V const & val, C pred = C{}, P proj = 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_FUNC_END(binary_search)
namespace cpp20
{
using ranges::binary_search;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,60 @@
/// \file
// Range v3 library
//
// Copyright Johel Guerrero 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_ALGORITHM_CONTAINS_HPP
#define RANGES_V3_ALGORITHM_CONTAINS_HPP
#include <utility>
#include <concepts/concepts.hpp>
#include <range/v3/algorithm/find.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/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(contains)
/// \brief function template \c contains
template(typename I, typename S, typename T, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_relation<equal_to, projected<I, P>, const T *>)
constexpr bool RANGES_FUNC(contains)(I first, S last, const T & val, P proj = {})
{
return find(std::move(first), last, val, std::move(proj)) != last;
}
/// \overload
template(typename Rng, typename T, typename P = identity)(
requires input_range<Rng> AND
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, const T *>)
constexpr bool RANGES_FUNC(contains)(Rng && rng, const T & val, P proj = {})
{
return (*this)(begin(rng), end(rng), val, std::move(proj));
}
RANGES_FUNC_END(contains)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif // RANGES_V3_ALGORITHM_CONTAINS_HPP

View File

@ -0,0 +1,89 @@
/// \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>
#include <range/v3/detail/prologue.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_FUNC_BEGIN(copy)
/// \brief function template \c copy
template(typename I, typename S, typename O)(
requires input_iterator<I> AND sentinel_for<S, I> AND
weakly_incrementable<O> AND indirectly_copyable<I, O>)
constexpr copy_result<I, O> RANGES_FUNC(copy)(I first, S last, O out) //
{
for(; first != last; ++first, ++out)
*out = *first;
return {first, out};
}
/// \overload
template(typename Rng, typename O)(
requires input_range<Rng> AND weakly_incrementable<O> AND
indirectly_copyable<iterator_t<Rng>, O>)
constexpr copy_result<borrowed_iterator_t<Rng>, O> //
RANGES_FUNC(copy)(Rng && rng, O out) //
{
return (*this)(begin(rng), end(rng), std::move(out));
}
RANGES_FUNC_END(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
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,74 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using copy_backward_result = detail::in_out_result<I, O>;
RANGES_FUNC_BEGIN(copy_backward)
/// \brief function template \c copy_backward
template(typename I, typename S, typename O)(
requires bidirectional_iterator<I> AND sentinel_for<S, I> AND
bidirectional_iterator<O> AND indirectly_copyable<I, O>)
constexpr copy_backward_result<I, O> RANGES_FUNC(copy_backward)(I first, S end_, O out)
{
I i = ranges::next(first, end_), last = i;
while(first != i)
*--out = *--i;
return {last, out};
}
/// \overload
template(typename Rng, typename O)(
requires bidirectional_range<Rng> AND bidirectional_iterator<O> AND
indirectly_copyable<iterator_t<Rng>, O>)
copy_backward_result<borrowed_iterator_t<Rng>, O> //
constexpr RANGES_FUNC(copy_backward)(Rng && rng, O out)
{
return (*this)(begin(rng), end(rng), std::move(out));
}
RANGES_FUNC_END(copy_backward)
namespace cpp20
{
using ranges::copy_backward;
using ranges::copy_backward_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,88 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using copy_if_result = detail::in_out_result<I, O>;
RANGES_FUNC_BEGIN(copy_if)
/// \brief function template \c copy_if
template(typename I, typename S, typename O, typename F, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
weakly_incrementable<O> AND
indirect_unary_predicate<F, projected<I, P>> AND
indirectly_copyable<I, O>)
constexpr copy_if_result<I, O> //
RANGES_FUNC(copy_if)(I first, S last, O out, F pred, P proj = P{}) //
{
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)(
requires input_range<Rng> AND weakly_incrementable<O> AND
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>> AND
indirectly_copyable<iterator_t<Rng>, O>)
constexpr copy_if_result<borrowed_iterator_t<Rng>, O> //
RANGES_FUNC(copy_if)(Rng && rng, O out, F pred, P proj = P{})
{
return (*this)(
begin(rng), end(rng), std::move(out), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(copy_if)
namespace cpp20
{
using ranges::copy_if;
using ranges::copy_if_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,69 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using copy_n_result = detail::in_out_result<I, O>;
RANGES_FUNC_BEGIN(copy_n)
/// \brief function template \c copy_n
template(typename I, typename O, typename P = identity)(
requires input_iterator<I> AND weakly_incrementable<O> AND
indirectly_copyable<I, O>)
constexpr copy_n_result<I, O> RANGES_FUNC(copy_n)(I first, iter_difference_t<I> n, O out)
{
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_FUNC_END(copy_n)
namespace cpp20
{
using ranges::copy_n;
using ranges::copy_n_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,72 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(count)
/// \brief function template \c count
template(typename I, typename S, typename V, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_relation<equal_to, projected<I, P>, V const *>)
constexpr iter_difference_t<I> //
RANGES_FUNC(count)(I first, S last, V const & val, P proj = P{})
{
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)(
requires input_range<Rng> AND
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, V const *>)
constexpr iter_difference_t<iterator_t<Rng>> //
RANGES_FUNC(count)(Rng && rng, V const & val, P proj = P{})
{
return (*this)(begin(rng), end(rng), val, std::move(proj));
}
RANGES_FUNC_END(count)
namespace cpp20
{
using ranges::count;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,71 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(count_if)
/// \brief function template \c count_if
template(typename I, typename S, typename R, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<R, projected<I, P>>)
constexpr iter_difference_t<I> RANGES_FUNC(count_if)(I first, S last, R pred, P proj = 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)(
requires input_range<Rng> AND
indirect_unary_predicate<R, projected<iterator_t<Rng>, P>>)
constexpr iter_difference_t<iterator_t<Rng>> //
RANGES_FUNC(count_if)(Rng && rng, R pred, P proj = P{})
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(count_if)
namespace cpp20
{
using ranges::count_if;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,100 @@
/// \file
// Range v3 library
//
// Copyright Johel Guerrero 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_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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(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)(
requires ((forward_iterator<I0> && sentinel_for<S0, I0>) ||
(input_iterator<I0> && sized_sentinel_for<S0, I0>)) AND
((forward_iterator<I1> && sentinel_for<S1, I1>) ||
(input_iterator<I1> && sized_sentinel_for<S1, I1>)) AND
indirectly_comparable<I0, I1, C, P0, P1>)
constexpr bool RANGES_FUNC(ends_with)(I0 begin0,
S0 end0,
I1 begin1,
S1 end1,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = 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)(
requires (forward_range<Rng0> || (input_range<Rng0> && sized_range<Rng0>)) AND
(forward_range<Rng1> || (input_range<Rng1> && sized_range<Rng1>)) AND
indirectly_comparable<iterator_t<Rng0>, iterator_t<Rng1>, C, P0, P1>)
constexpr bool RANGES_FUNC(ends_with)(
Rng0 && rng0, Rng1 && rng1, C pred = C{}, P0 proj0 = P0{}, P1 proj1 = 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_FUNC_END(ends_with)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,175 @@
/// \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_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>
#include <range/v3/detail/prologue.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_FUNC_BEGIN(equal)
/// \brief function template \c equal
template(typename I0,
typename S0,
typename I1,
typename C = equal_to,
typename P0 = identity,
typename P1 = identity)(
requires input_iterator<I0> AND sentinel_for<S0, I0> AND
input_iterator<I1> AND indirectly_comparable<I0, I1, C, P0, P1>)
RANGES_DEPRECATED(
"Use the variant of ranges::equal that takes an upper bound for "
"both sequences")
constexpr bool RANGES_FUNC(equal)(I0 begin0,
S0 end0,
I1 begin1,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = 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)(
requires input_iterator<I0> AND sentinel_for<S0, I0> AND
input_iterator<I1> AND sentinel_for<S1, I1> AND
indirectly_comparable<I0, I1, C, P0, P1>)
constexpr bool RANGES_FUNC(equal)(I0 begin0,
S0 end0,
I1 begin1,
S1 end1,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = 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)(
requires input_range<Rng0> AND input_iterator<uncvref_t<I1Ref>> AND
indirectly_comparable<iterator_t<Rng0>, uncvref_t<I1Ref>, C, P0, P1>)
RANGES_DEPRECATED(
"Use the variant of ranges::equal that takes an upper bound for "
"both sequences")
constexpr bool RANGES_FUNC(equal)(Rng0 && rng0,
I1Ref && begin1,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = 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)(
requires input_range<Rng0> AND input_range<Rng1> AND
indirectly_comparable<iterator_t<Rng0>, iterator_t<Rng1>, C, P0, P1>)
constexpr bool RANGES_FUNC(equal)(
Rng0 && rng0, Rng1 && rng1, C pred = C{}, P0 proj0 = P0{}, P1 proj1 = 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_FUNC_END(equal)
namespace cpp20
{
using ranges::equal;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,130 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(equal_range)
/// \brief function template \c equal_range
template(typename I,
typename S,
typename V,
typename C = less,
typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, V const *, projected<I, P>>)
constexpr subrange<I> RANGES_FUNC(equal_range)(
I first, S last, V const & val, C pred = C{}, P proj = 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, ranges::ref(pred), ranges::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, ranges::ref(pred), ranges::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, ranges::ref(pred), ranges::ref(proj)),
upper_bound(std::move(mid),
std::move(last),
val,
ranges::ref(pred),
ranges::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)(
requires forward_range<Rng> AND
indirect_strict_weak_order<C, V const *, projected<iterator_t<Rng>, P>>)
constexpr borrowed_subrange_t<Rng> //
RANGES_FUNC(equal_range)(Rng && rng, V const & val, C pred = C{}, P proj = 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_FUNC_END(equal_range)
namespace cpp20
{
using ranges::equal_range;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,62 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(fill)
/// \brief function template \c fill
template(typename O, typename S, typename V)(
requires output_iterator<O, V const &> AND sentinel_for<S, O>)
constexpr O RANGES_FUNC(fill)(O first, S last, V const & val) //
{
for(; first != last; ++first)
*first = val;
return first;
}
/// \overload
template(typename Rng, typename V)(
requires output_range<Rng, V const &>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(fill)(Rng && rng, V const & val)
{
return (*this)(begin(rng), end(rng), val);
}
RANGES_FUNC_END(fill)
namespace cpp20
{
using ranges::fill;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,59 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(fill_n)
/// \brief function template \c equal
template(typename O, typename V)(
requires output_iterator<O, V const &>)
constexpr O RANGES_FUNC(fill_n)(O first, iter_difference_t<O> n, V const & val)
{
RANGES_EXPECT(n >= 0);
auto norig = n;
auto b = uncounted(first);
for(; n != 0; ++b, --n)
*b = val;
return recounted(first, b, norig);
}
RANGES_FUNC_END(fill_n)
namespace cpp20
{
using ranges::fill_n;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,78 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(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)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_relation<equal_to, projected<I, P>, V const *>)
constexpr I RANGES_FUNC(find)(I first, S last, V const & val, P proj = P{})
{
for(; first != last; ++first)
if(invoke(proj, *first) == val)
break;
return first;
}
/// \overload
template(typename Rng, typename V, typename P = identity)(
requires input_range<Rng> AND
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, V const *>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(find)(Rng && rng, V const & val, P proj = P{})
{
return (*this)(begin(rng), end(rng), val, std::move(proj));
}
RANGES_FUNC_END(find)
namespace cpp20
{
using ranges::find;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,237 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \cond
namespace detail
{
template(typename I, typename S)(
requires input_iterator<I> AND sentinel_for<S, I>)
constexpr I next_to_if(I i, S s, std::true_type)
{
return ranges::next(i, s);
}
template(typename I, typename S)(
requires input_iterator<I> AND sentinel_for<S, I>)
constexpr S next_to_if(I, S s, std::false_type)
{
return s;
}
template(bool B, typename I, typename S)(
requires input_iterator<I> AND sentinel_for<S, I>)
constexpr meta::if_c<B, I, S> next_to_if(I i, S s)
{
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>
constexpr subrange<I1> find_end_impl(I1 begin1, S1 end1, I2 begin2, S2 end2, R pred, P proj,
std::forward_iterator_tag, std::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>
constexpr subrange<I1> find_end_impl(I1 begin1, I1 end1, I2 begin2, I2 end2, R pred, P proj,
std::bidirectional_iterator_tag,
std::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>
constexpr subrange<I1> find_end_impl(I1 begin1, I1 end1, I2 begin2, I2 end2, R pred, P proj,
std::random_access_iterator_tag,
std::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_FUNC_BEGIN(find_end)
/// \brief function template \c find_end
template(typename I1,
typename S1,
typename I2,
typename S2,
typename R = equal_to,
typename P = identity)(
requires forward_iterator<I1> AND sentinel_for<S1, I1> AND
forward_iterator<I2> AND sentinel_for<S2, I2> AND
indirect_relation<R, projected<I1, P>, I2>)
constexpr subrange<I1> RANGES_FUNC(find_end)(
I1 begin1, S1 end1, I2 begin2, S2 end2, R pred = R{}, P proj = P{}) //
{
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)(
requires forward_range<Rng1> AND forward_range<Rng2> AND
indirect_relation<R, projected<iterator_t<Rng1>, P>, iterator_t<Rng2>>)
constexpr borrowed_subrange_t<Rng1> RANGES_FUNC(find_end)(
Rng1 && rng1, Rng2 && rng2, R pred = R{}, P proj = P{}) //
{
return (*this)(begin(rng1),
end(rng1),
begin(rng2),
end(rng2),
std::move(pred),
std::move(proj));
}
RANGES_FUNC_END(find_end)
namespace cpp20
{
using ranges::find_end;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,103 @@
/// \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_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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(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)(
requires input_iterator<I0> AND sentinel_for<S0, I0> AND
forward_iterator<I1> AND sentinel_for<S1, I1> AND
indirect_relation<R, projected<I0, P0>, projected<I1, P1>>)
constexpr I0 RANGES_FUNC(find_first_of)(I0 begin0,
S0 end0,
I1 begin1,
S1 end1,
R pred = R{},
P0 proj0 = P0{},
P1 proj1 = 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)(
requires input_range<Rng0> AND forward_range<Rng1> AND
indirect_relation<R,
projected<iterator_t<Rng0>, P0>,
projected<iterator_t<Rng1>, P1>>)
constexpr borrowed_iterator_t<Rng0> RANGES_FUNC(find_first_of)(
Rng0 && rng0, Rng1 && rng1, R pred = R{}, P0 proj0 = P0{}, P1 proj1 = P1{}) //
{
return (*this)(begin(rng0),
end(rng0),
begin(rng1),
end(rng1),
std::move(pred),
std::move(proj0),
std::move(proj1));
}
RANGES_FUNC_END(find_first_of)
namespace cpp20
{
using ranges::find_first_of;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,79 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(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)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<F, projected<I, P>>)
constexpr I RANGES_FUNC(find_if)(I first, S last, F pred, P proj = P{})
{
for(; first != last; ++first)
if(invoke(pred, invoke(proj, *first)))
break;
return first;
}
/// \overload
template(typename Rng, typename F, typename P = identity)(
requires input_range<Rng> AND
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(find_if)(Rng && rng, F pred, P proj = P{})
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(find_if)
namespace cpp20
{
using ranges::find_if;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,80 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(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)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<F, projected<I, P>>)
constexpr I RANGES_FUNC(find_if_not)(I first, S last, F pred, P proj = P{})
{
for(; first != last; ++first)
if(!invoke(pred, invoke(proj, *first)))
break;
return first;
}
/// \overload
template(typename Rng, typename F, typename P = identity)(
requires input_range<Rng> AND
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(find_if_not)(Rng && rng, F pred, P proj = P{})
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(find_if_not)
namespace cpp20
{
using ranges::find_if_not;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,19 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2021-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_FOLD_HPP
#define RANGES_V3_ALGORITHM_FOLD_HPP
#include <range/v3/algorithm/fold_left.hpp>
#include <range/v3/algorithm/fold_right.hpp>
#endif

View File

@ -0,0 +1,125 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2021-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_FOLD_LEFT_HPP
#define RANGES_V3_ALGORITHM_FOLD_LEFT_HPP
#include <meta/meta.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/utility/optional.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
// clang-format off
/// \concept indirectly_binary_left_foldable_impl
/// \brief The \c indirectly_binary_left_foldable_impl concept
template<class F, class T, class I, class U>
CPP_concept indirectly_binary_left_foldable_impl =
movable<T> &&
movable<U> &&
convertible_to<T, U> &&
invocable<F&, U, iter_reference_t<I>> &&
assignable_from<U&, invoke_result_t<F&, U, iter_reference_t<I>>>;
/// \concept indirectly_binary_left_foldable
/// \brief The \c indirectly_binary_left_foldable concept
template<class F, class T, class I>
CPP_concept indirectly_binary_left_foldable =
copy_constructible<F> &&
indirectly_readable<I> &&
invocable<F&, T, iter_reference_t<I>> &&
convertible_to<invoke_result_t<F&, T, iter_reference_t<I>>,
std::decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>> &&
indirectly_binary_left_foldable_impl<F, T, I, std::decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>>;
// clang-format on
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(fold_left)
template(typename I, typename S, typename T, typename Op)(
requires sentinel_for<S, I> AND input_iterator<I> AND
indirectly_binary_left_foldable<Op, T, I>) //
constexpr auto
RANGES_FUNC(fold_left)(I first, S last, T init, Op op)
{
using U = std::decay_t<invoke_result_t<Op &, T, iter_reference_t<I>>>;
if(first == last)
{
return U(std::move(init));
}
U accum = invoke(op, std::move(init), *first);
for(++first; first != last; ++first)
{
accum = invoke(op, std::move(accum), *first);
}
return accum;
}
template(typename Rng, typename T, typename Op)(
requires input_range<Rng> AND
indirectly_binary_left_foldable<Op, T, iterator_t<Rng>>) //
constexpr auto
RANGES_FUNC(fold_left)(Rng && rng, T init, Op op)
{
return (*this)(begin(rng), end(rng), std::move(init), std::move(op));
}
RANGES_FUNC_END(fold_left)
RANGES_FUNC_BEGIN(fold_left_first)
template(typename I, typename S, typename Op)(
requires sentinel_for<S, I> AND input_iterator<I> AND
indirectly_binary_left_foldable<Op, iter_value_t<I>, I>
AND constructible_from<iter_value_t<I>, iter_reference_t<I>>) //
constexpr auto
RANGES_FUNC(fold_left_first)(I first, S last, Op op)
{
using U = invoke_result_t<fold_left_fn, I, S, iter_value_t<I>, Op>;
if(first == last)
{
return optional<U>();
}
iter_value_t<I> init = *first;
++first;
return optional<U>(
in_place,
fold_left_fn{}(std::move(first), std::move(last), std::move(init), op));
}
template(typename R, typename Op)(
requires input_range<R> AND
indirectly_binary_left_foldable<Op, range_value_t<R>, iterator_t<R>>
AND constructible_from<range_value_t<R>, range_reference_t<R>>) //
constexpr auto
RANGES_FUNC(fold_left_first)(R && rng, Op op)
{
return (*this)(begin(rng), end(rng), std::move(op));
}
RANGES_FUNC_END(fold_left_first)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,126 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2021-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_FOLD_RIGHT_HPP
#define RANGES_V3_ALGORITHM_FOLD_RIGHT_HPP
#include <meta/meta.hpp>
#include <range/v3/algorithm/fold_left.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/utility/optional.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
namespace detail
{
template<typename F>
struct flipped
{
F f;
template(class T, class U)(requires invocable<F &, U, T>) //
invoke_result_t<F &, U, T>
operator()(T &&, U &&);
};
} // namespace detail
// clang-format off
/// \concept indirectly_binary_right_foldable
/// \brief The \c indirectly_binary_right_foldable concept
template<class F, class T, class I>
CPP_concept indirectly_binary_right_foldable =
indirectly_binary_left_foldable<detail::flipped<F>, T, I>;
// clang-format on
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(fold_right)
template(typename I, typename S, typename T, typename Op)(
requires sentinel_for<S, I> AND bidirectional_iterator<I> AND
indirectly_binary_right_foldable<Op, T, I>) //
constexpr auto
RANGES_FUNC(fold_right)(I first, S last, T init, Op op)
{
using U = std::decay_t<invoke_result_t<Op &, iter_reference_t<I>, T>>;
if(first == last)
{
return U(std::move(init));
}
I tail = next(first, last);
U accum = invoke(op, *--tail, std::move(init));
while(first != tail)
{
accum = invoke(op, *--tail, std::move(accum));
}
return accum;
}
template(typename Rng, typename T, typename Op)(
requires bidirectional_range<Rng> AND
indirectly_binary_right_foldable<Op, T, iterator_t<Rng>>) //
constexpr auto
RANGES_FUNC(fold_right)(Rng && rng, T init, Op op)
{
return (*this)(begin(rng), end(rng), std::move(init), std::move(op));
}
RANGES_FUNC_END(fold_right)
RANGES_FUNC_BEGIN(fold_right_last)
template(typename I, typename S, typename Op)(
requires sentinel_for<S, I> AND bidirectional_iterator<I> AND
indirectly_binary_right_foldable<Op, iter_value_t<I>, I>
AND constructible_from<iter_value_t<I>, iter_reference_t<I>>) //
constexpr auto
RANGES_FUNC(fold_right_last)(I first, S last, Op op)
{
using U = invoke_result_t<fold_right_fn, I, S, iter_value_t<I>, Op>;
if(first == last)
{
return optional<U>();
}
I tail = prev(next(first, std::move(last)));
return optional<U>(
in_place,
fold_right_fn{}(
std::move(first), tail, iter_value_t<I>(*tail), std::move(op)));
}
template(typename R, typename Op)(
requires bidirectional_range<R> AND
indirectly_binary_right_foldable<Op, range_value_t<R>, iterator_t<R>>
AND constructible_from<range_value_t<R>, range_reference_t<R>>) //
constexpr auto
RANGES_FUNC(fold_right_last)(R && rng, Op op)
{
return (*this)(begin(rng), end(rng), std::move(op));
}
RANGES_FUNC_END(fold_right_last)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,78 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename F>
using for_each_result = detail::in_fun_result<I, F>;
RANGES_FUNC_BEGIN(for_each)
/// \brief function template \c for_each
template(typename I, typename S, typename F, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirectly_unary_invocable<F, projected<I, P>>)
constexpr for_each_result<I, F> RANGES_FUNC(for_each)(I first, S last, F fun, P proj = 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)(
requires input_range<Rng> AND
indirectly_unary_invocable<F, projected<iterator_t<Rng>, P>>)
constexpr for_each_result<borrowed_iterator_t<Rng>, F> //
RANGES_FUNC(for_each)(Rng && rng, F fun, P proj = P{})
{
return {(*this)(begin(rng), end(rng), ref(fun), detail::move(proj)).in,
detail::move(fun)};
}
RANGES_FUNC_END(for_each)
namespace cpp20
{
using ranges::for_each;
using ranges::for_each_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,77 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(for_each_n)
/// \brief function template \c for_each_n
template(typename I, typename F, typename P = identity)(
requires input_iterator<I> AND
indirectly_unary_invocable<F, projected<I, P>>)
constexpr I RANGES_FUNC(for_each_n)(I first, iter_difference_t<I> n, F fun, P proj = 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)(
requires input_range<Rng> AND
indirectly_unary_invocable<F, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(for_each_n)(
Rng && rng, range_difference_t<Rng> n, F fun, P proj = P{})
{
if(sized_range<Rng>)
RANGES_EXPECT(n <= distance(rng));
return (*this)(begin(rng), n, detail::move(fun), detail::move(proj));
}
RANGES_FUNC_END(for_each_n)
namespace cpp20
{
using ranges::for_each_n;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,73 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename O, typename F>
using generate_result = detail::out_fun_result<O, F>;
RANGES_FUNC_BEGIN(generate)
/// \brief function template \c generate_n
template(typename O, typename S, typename F)(
requires invocable<F &> AND output_iterator<O, invoke_result_t<F &>> AND
sentinel_for<S, O>)
constexpr generate_result<O, F> RANGES_FUNC(generate)(O first, S last, F fun) //
{
for(; first != last; ++first)
*first = invoke(fun);
return {detail::move(first), detail::move(fun)};
}
/// \overload
template(typename Rng, typename F)(
requires invocable<F &> AND output_range<Rng, invoke_result_t<F &>>)
constexpr generate_result<borrowed_iterator_t<Rng>, F> //
RANGES_FUNC(generate)(Rng && rng, F fun)
{
return {(*this)(begin(rng), end(rng), ref(fun)).out, detail::move(fun)};
}
RANGES_FUNC_END(generate)
namespace cpp20
{
using ranges::generate;
using ranges::generate_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,67 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename O, typename F>
using generate_n_result = detail::out_fun_result<O, F>;
RANGES_FUNC_BEGIN(generate_n)
/// \brief function template \c generate_n
template(typename O, typename F)(
requires invocable<F &> AND output_iterator<O, invoke_result_t<F &>>)
constexpr generate_n_result<O, F> //
RANGES_FUNC(generate_n)(O first, iter_difference_t<O> n, F fun)
{
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_FUNC_END(generate_n)
namespace cpp20
{
using ranges::generate_n;
using ranges::generate_n_result;
} // namespace cpp20
// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,436 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \cond
namespace detail
{
struct is_heap_until_n_fn
{
template(typename I, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND
indirect_strict_weak_order<C, projected<I, P>>)
constexpr I operator()(I const begin_,
iter_difference_t<I> const n_,
C pred = C{},
P proj = P{}) const
{
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)(
requires random_access_iterator<I> AND
indirect_strict_weak_order<C, projected<I, P>>)
constexpr bool operator()(I first,
iter_difference_t<I> n,
C pred = C{},
P proj = P{}) const
{
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_FUNC_BEGIN(is_heap_until)
/// \brief function template \c is_heap_until
template(typename I, typename S, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, projected<I, P>>)
constexpr I RANGES_FUNC(is_heap_until)(I first, S last, C pred = C{}, P proj = 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)(
requires random_access_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(is_heap_until)(Rng && rng, C pred = C{}, P proj = P{})
{
return detail::is_heap_until_n(
begin(rng), distance(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(is_heap_until)
namespace cpp20
{
using ranges::is_heap_until;
}
RANGES_FUNC_BEGIN(is_heap)
/// \brief function template \c is_heap
template(typename I, typename S, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, projected<I, P>>)
constexpr bool RANGES_FUNC(is_heap)(I first, S last, C pred = C{}, P proj = 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)(
requires random_access_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>)
constexpr bool RANGES_FUNC(is_heap)(Rng && rng, C pred = C{}, P proj = P{}) //
{
return detail::is_heap_n(
begin(rng), distance(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(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>
constexpr 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>
constexpr 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_FUNC_BEGIN(push_heap)
/// \brief function template \c push_heap
template(typename I, typename S, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sentinel_for<S, I> AND
sortable<I, C, P>)
constexpr I RANGES_FUNC(push_heap)(I first, S last, C pred = C{}, P proj = 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)(
requires random_access_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(push_heap)(Rng && rng, C pred = C{}, P proj = 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_FUNC_END(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)(
requires random_access_iterator<I> AND sortable<I, C, P>)
constexpr void operator()(I first,
iter_difference_t<I> len,
C pred = C{},
P proj = P{}) const
{
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_FUNC_BEGIN(pop_heap)
/// \brief function template \c pop_heap
template(typename I, typename S, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sentinel_for<S, I> AND
sortable<I, C, P>)
constexpr I RANGES_FUNC(pop_heap)(I first, S last, C pred = C{}, P proj = 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)(
requires random_access_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(pop_heap)(Rng && rng, C pred = C{}, P proj = 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_FUNC_END(pop_heap)
namespace cpp20
{
using ranges::pop_heap;
}
RANGES_FUNC_BEGIN(make_heap)
/// \brief function template \c make_heap
template(typename I, typename S, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sentinel_for<S, I> AND
sortable<I, C, P>)
constexpr I RANGES_FUNC(make_heap)(I first, S last, C pred = C{}, P proj = 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, ranges::ref(pred), ranges::ref(proj));
return first + n;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires random_access_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(make_heap)(Rng && rng, C pred = C{}, P proj = 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, ranges::ref(pred), ranges::ref(proj));
return first + n;
}
RANGES_FUNC_END(make_heap)
namespace cpp20
{
using ranges::make_heap;
}
RANGES_FUNC_BEGIN(sort_heap)
template(typename I, typename S, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sentinel_for<S, I> AND
sortable<I, C, P>)
constexpr I RANGES_FUNC(sort_heap)(I first, S last, C pred = C{}, P proj = P{})
{
iter_difference_t<I> const n = distance(first, last);
for(auto i = n; i > 1; --i)
detail::pop_heap_n(first, i, ranges::ref(pred), ranges::ref(proj));
return first + n;
}
template(typename Rng, typename C = less, typename P = identity)(
requires random_access_range<Rng &> AND sortable<iterator_t<Rng>, C, P>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(sort_heap)(Rng && rng, C pred = C{}, P proj = 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, ranges::ref(pred), ranges::ref(proj));
return first + n;
}
RANGES_FUNC_END(sort_heap)
namespace cpp20
{
using ranges::sort_heap;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,303 @@
/// \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>
#include <range/v3/detail/prologue.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)(
requires bidirectional_iterator<I> AND sortable<I, C, P>)
void 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
{
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)(
requires bidirectional_iterator<I> AND sortable<I, C, P>)
void operator()(I first, I middle, I last, iter_difference_t<I> len1,
iter_difference_t<I> len2, C pred = C{}, P proj = P{}) const
{
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_FUNC_BEGIN(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)(
requires bidirectional_iterator<I> AND sortable<I, C, P>)
I RANGES_FUNC(inplace_merge)(
I first, I middle, S last, C pred = C{}, P proj = 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_v<value_type> && 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)(
requires bidirectional_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
borrowed_iterator_t<Rng> RANGES_FUNC(inplace_merge)(
Rng && rng, iterator_t<Rng> middle, C pred = C{}, P proj = P{})
{
return (*this)(begin(rng),
std::move(middle),
end(rng),
std::move(pred),
std::move(proj));
}
RANGES_FUNC_END(inplace_merge)
namespace cpp20
{
using ranges::inplace_merge;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,80 @@
/// \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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(is_partitioned)
/// \brief function template \c is_partitioned
template(typename I, typename S, typename C, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<C, projected<I, P>>)
constexpr bool RANGES_FUNC(is_partitioned)(I first, S last, C pred, P proj = 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)(
requires input_range<Rng> AND
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>)
constexpr bool RANGES_FUNC(is_partitioned)(Rng && rng, C pred, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(is_partitioned)
namespace cpp20
{
using ranges::is_partitioned;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,77 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
// 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
//
// Implementation based on the code in libc++
// http://http://libcxx.llvm.org/
#ifndef RANGES_V3_ALGORITHM_IS_SORTED_HPP
#define RANGES_V3_ALGORITHM_IS_SORTED_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/is_sorted_until.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(is_sorted)
/// \brief template function \c is_sorted
///
/// range-based version of the \c is_sorted std algorithm
///
/// Works on forward_ranges
///
/// \pre `Rng` is a model of the `forward_range` concept
/// \pre `I` is a model of the `forward_iterator` concept
/// \pre `S` and `I` model the `sentinel_for<S, I>` concept
/// \pre `R` and `projected<I, P>` model the `indirect_strict_weak_order<R,
/// projected<I, P>>` concept
///
template(typename I, typename S, typename R = less, typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<R, projected<I, P>>)
constexpr bool RANGES_FUNC(is_sorted)(I first, S last, R rel = R{}, P proj = P{})
{
return is_sorted_until(
std::move(first), last, std::move(rel), std::move(proj)) == last;
}
/// \overload
template(typename Rng, typename R = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<R, projected<iterator_t<Rng>, P>>)
constexpr bool RANGES_FUNC(is_sorted)(Rng && rng, R rel = R{}, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(rel), std::move(proj));
}
RANGES_FUNC_END(is_sorted)
namespace cpp20
{
using ranges::is_sorted;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,89 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
// 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
//
// Implementation based on the code in libc++
// http://http://libcxx.llvm.org/
#ifndef RANGES_V3_ALGORITHM_IS_SORTED_UNTIL_HPP
#define RANGES_V3_ALGORITHM_IS_SORTED_UNTIL_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/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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(is_sorted_until)
/// \brief template function \c is_sorted_until
///
/// range-based version of the \c is_sorted_until std algorithm
///
/// Works on forward_ranges
///
/// \pre `Rng` is a model of the `forward_range` concept
/// \pre `I` is a model of the `forward_iterator` concept
/// \pre `S` and `I` model the `sentinel_for<S, I>` concept
/// \pre `R` and `projected<I, P>` model the `indirect_strict_weak_order<R,
/// projected<I, P>>` concept
///
template(typename I, typename S, typename R = less, typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<R, projected<I, P>>)
constexpr I RANGES_FUNC(is_sorted_until)(I first, S last, R pred = R{}, P proj = P{})
{
auto i = first;
if(first != last)
{
while(++i != last)
{
if(invoke(pred, invoke(proj, *i), invoke(proj, *first)))
return i;
first = i;
}
}
return i;
}
/// \overload
template(typename Rng, typename R = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<R, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(is_sorted_until)(Rng && rng, R pred = R{}, P proj = P{})
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(is_sorted_until)
namespace cpp20
{
using ranges::is_sorted_until;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,102 @@
/// \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_LEXICOGRAPHICAL_COMPARE_HPP
#define RANGES_V3_ALGORITHM_LEXICOGRAPHICAL_COMPARE_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/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/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(lexicographical_compare)
/// \brief function template \c lexicographical_compare
template(typename I0,
typename S0,
typename I1,
typename S1,
typename C = less,
typename P0 = identity,
typename P1 = identity)(
requires input_iterator<I0> AND sentinel_for<S0, I0> AND
input_iterator<I1> AND sentinel_for<S1, I1> AND
indirect_strict_weak_order<C, projected<I0, P0>, projected<I1, P1>>)
constexpr bool RANGES_FUNC(lexicographical_compare)(I0 begin0,
S0 end0,
I1 begin1,
S1 end1,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = P1{})
{
for(; begin1 != end1; ++begin0, ++begin1)
{
if(begin0 == end0 ||
invoke(pred, invoke(proj0, *begin0), invoke(proj1, *begin1)))
return true;
if(invoke(pred, invoke(proj1, *begin1), invoke(proj0, *begin0)))
return false;
}
return false;
}
/// \overload
template(typename Rng0,
typename Rng1,
typename C = less,
typename P0 = identity,
typename P1 = identity)(
requires input_range<Rng0> AND input_range<Rng1> AND
indirect_strict_weak_order<C,
projected<iterator_t<Rng0>, P0>,
projected<iterator_t<Rng1>, P1>>)
constexpr bool RANGES_FUNC(lexicographical_compare)(Rng0 && rng0,
Rng1 && rng1,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = P1{}) //
{
return (*this)(begin(rng0),
end(rng0),
begin(rng1),
end(rng1),
std::move(pred),
std::move(proj0),
std::move(proj1));
}
RANGES_FUNC_END(lexicographical_compare)
namespace cpp20
{
using ranges::lexicographical_compare;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,81 @@
/// \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_LOWER_BOUND_HPP
#define RANGES_V3_ALGORITHM_LOWER_BOUND_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/aux_/lower_bound_n.hpp>
#include <range/v3/algorithm/partition_point.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(lower_bound)
/// \brief function template \c lower_bound
template(typename I,
typename S,
typename V,
typename C = less,
typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, V const *, projected<I, P>>)
constexpr I RANGES_FUNC(lower_bound)(I first,
S last,
V const & val,
C pred = C{},
P proj = P{})
{
return partition_point(std::move(first),
std::move(last),
detail::make_lower_bound_predicate(pred, val),
std::move(proj));
}
/// \overload
template(typename Rng, typename V, typename C = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<C, V const *, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(lower_bound)(Rng && rng, V const & val, C pred = C{}, P proj = P{})
{
return partition_point(
rng, detail::make_lower_bound_predicate(pred, val), std::move(proj));
}
RANGES_FUNC_END(lower_bound)
namespace cpp20
{
using ranges::lower_bound;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,90 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Casey Carter 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_ALGORITHM_MAX_HPP
#define RANGES_V3_ALGORITHM_MAX_HPP
#include <initializer_list>
#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/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(max)
/// \brief function template \c max
template(typename T, typename C = less, typename P = identity)(
requires indirect_strict_weak_order<C, projected<T const *, P>>)
constexpr T const & RANGES_FUNC(max)(
T const & a, T const & b, C pred = C{}, P proj = P{}) //
{
return invoke(pred, invoke(proj, b), invoke(proj, a)) ? a : b;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires input_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>> AND
indirectly_copyable_storable<iterator_t<Rng>, range_value_t<Rng> *>)
constexpr range_value_t<Rng> //
RANGES_FUNC(max)(Rng && rng, C pred = C{}, P proj = P{}) //
{
auto first = ranges::begin(rng);
auto last = ranges::end(rng);
RANGES_EXPECT(first != last);
range_value_t<Rng> result = *first;
while(++first != last)
{
auto && tmp = *first;
if(invoke(pred, invoke(proj, result), invoke(proj, tmp)))
result = (decltype(tmp) &&)tmp;
}
return result;
}
/// \overload
template(typename T, typename C = less, typename P = identity)(
requires copyable<T> AND
indirect_strict_weak_order<C, projected<T const *, P>>)
constexpr T RANGES_FUNC(max)(
std::initializer_list<T> const && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(rng, std::move(pred), std::move(proj));
}
RANGES_FUNC_END(max)
namespace cpp20
{
using ranges::max;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,72 @@
/// \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_MAX_ELEMENT_HPP
#define RANGES_V3_ALGORITHM_MAX_ELEMENT_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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(max_element)
/// \brief function template \c max_element
template(typename I, typename S, typename C = less, typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, projected<I, P>>)
constexpr I RANGES_FUNC(max_element)(I first, S last, C pred = C{}, P proj = P{})
{
if(first != last)
for(auto tmp = next(first); tmp != last; ++tmp)
if(invoke(pred, invoke(proj, *first), invoke(proj, *tmp)))
first = tmp;
return first;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(max_element)(Rng && rng, C pred = C{}, P proj = P{})
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(max_element)
namespace cpp20
{
using ranges::max_element;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,136 @@
/// \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_MERGE_HPP
#define RANGES_V3_ALGORITHM_MERGE_HPP
#include <tuple>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/copy.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/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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I0, typename I1, typename O>
using merge_result = detail::in1_in2_out_result<I0, I1, O>;
RANGES_FUNC_BEGIN(merge)
/// \brief function template \c merge
template(typename I0,
typename S0,
typename I1,
typename S1,
typename O,
typename C = less,
typename P0 = identity,
typename P1 = identity)(
requires sentinel_for<S0, I0> AND sentinel_for<S1, I1> AND
mergeable<I0, I1, O, C, P0, P1>)
constexpr merge_result<I0, I1, O> RANGES_FUNC(merge)(I0 begin0,
S0 end0,
I1 begin1,
S1 end1,
O out,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = P1{}) //
{
for(; begin0 != end0 && begin1 != end1; ++out)
{
if(invoke(pred, invoke(proj1, *begin1), invoke(proj0, *begin0)))
{
*out = *begin1;
++begin1;
}
else
{
*out = *begin0;
++begin0;
}
}
auto t0 = ranges::copy(begin0, end0, out);
auto t1 = ranges::copy(begin1, end1, t0.out);
return {t0.in, t1.in, t1.out};
}
/// \overload
template(typename Rng0,
typename Rng1,
typename O,
typename C = less,
typename P0 = identity,
typename P1 = identity)(
requires range<Rng0> AND range<Rng1> AND
mergeable<iterator_t<Rng0>, iterator_t<Rng1>, O, C, P0, P1>)
constexpr merge_result<borrowed_iterator_t<Rng0>, borrowed_iterator_t<Rng1>, O>
RANGES_FUNC(merge)(Rng0 && rng0,
Rng1 && rng1,
O out,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = P1{})
{
return (*this)(begin(rng0),
end(rng0),
begin(rng1),
end(rng1),
std::move(out),
std::move(pred),
std::move(proj0),
std::move(proj1));
}
RANGES_FUNC_END(merge)
namespace cpp20
{
using ranges::merge;
using ranges::merge_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,90 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Casey Carter 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_ALGORITHM_MIN_HPP
#define RANGES_V3_ALGORITHM_MIN_HPP
#include <initializer_list>
#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/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(min)
/// \brief function template \c min
template(typename T, typename C = less, typename P = identity)(
requires indirect_strict_weak_order<C, projected<T const *, P>>)
constexpr T const & RANGES_FUNC(min)(
T const & a, T const & b, C pred = C{}, P proj = P{}) //
{
return invoke(pred, invoke(proj, b), invoke(proj, a)) ? b : a;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires input_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>> AND
indirectly_copyable_storable<iterator_t<Rng>, range_value_t<Rng> *>)
constexpr range_value_t<Rng> //
RANGES_FUNC(min)(Rng && rng, C pred = C{}, P proj = P{}) //
{
auto first = ranges::begin(rng);
auto last = ranges::end(rng);
RANGES_EXPECT(first != last);
range_value_t<Rng> result = *first;
while(++first != last)
{
auto && tmp = *first;
if(invoke(pred, invoke(proj, tmp), invoke(proj, result)))
result = (decltype(tmp) &&)tmp;
}
return result;
}
/// \overload
template(typename T, typename C = less, typename P = identity)(
requires copyable<T> AND
indirect_strict_weak_order<C, projected<T const *, P>>)
constexpr T RANGES_FUNC(min)(
std::initializer_list<T> const && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(rng, std::move(pred), std::move(proj));
}
RANGES_FUNC_END(min)
namespace cpp20
{
using ranges::min;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,72 @@
/// \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_MIN_ELEMENT_HPP
#define RANGES_V3_ALGORITHM_MIN_ELEMENT_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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(min_element)
/// \brief function template \c min_element
template(typename I, typename S, typename C = less, typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, projected<I, P>>)
constexpr I RANGES_FUNC(min_element)(I first, S last, C pred = C{}, P proj = P{})
{
if(first != last)
for(auto tmp = next(first); tmp != last; ++tmp)
if(invoke(pred, invoke(proj, *tmp), invoke(proj, *first)))
first = tmp;
return first;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(min_element)(Rng && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(min_element)
namespace cpp20
{
using ranges::min_element;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,130 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Casey Carter 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_ALGORITHM_MINMAX_HPP
#define RANGES_V3_ALGORITHM_MINMAX_HPP
#include <initializer_list>
#include <range/v3/range_fwd.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/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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename T>
using minmax_result = detail::min_max_result<T, T>;
RANGES_FUNC_BEGIN(minmax)
/// \brief function template \c minmax
template(typename T, typename C = less, typename P = identity)(
requires indirect_strict_weak_order<C, projected<T const *, P>>)
constexpr minmax_result<T const &> RANGES_FUNC(minmax)(
T const & a, T const & b, C pred = C{}, P proj = P{}) //
{
using R = minmax_result<T const &>;
return invoke(pred, invoke(proj, b), invoke(proj, a)) ? R{b, a} : R{a, b};
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires input_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>> AND
indirectly_copyable_storable<iterator_t<Rng>, range_value_t<Rng> *>)
constexpr minmax_result<range_value_t<Rng>> //
RANGES_FUNC(minmax)(Rng && rng, C pred = C{}, P proj = P{}) //
{
using R = minmax_result<range_value_t<Rng>>;
auto first = ranges::begin(rng);
auto last = ranges::end(rng);
RANGES_EXPECT(first != last);
auto result = R{*first, *first};
if(++first != last)
{
{
auto && tmp = *first;
if(invoke(pred, invoke(proj, tmp), invoke(proj, result.min)))
result.min = (decltype(tmp) &&)tmp;
else
result.max = (decltype(tmp) &&)tmp;
}
while(++first != last)
{
range_value_t<Rng> tmp1 = *first;
if(++first == last)
{
if(invoke(pred, invoke(proj, tmp1), invoke(proj, result.min)))
result.min = std::move(tmp1);
else if(!invoke(
pred, invoke(proj, tmp1), invoke(proj, result.max)))
result.max = std::move(tmp1);
break;
}
auto && tmp2 = *first;
if(invoke(pred, invoke(proj, tmp2), invoke(proj, tmp1)))
{
if(invoke(pred, invoke(proj, tmp2), invoke(proj, result.min)))
result.min = (decltype(tmp2) &&)tmp2;
if(!invoke(pred, invoke(proj, tmp1), invoke(proj, result.max)))
result.max = std::move(tmp1);
}
else
{
if(invoke(pred, invoke(proj, tmp1), invoke(proj, result.min)))
result.min = std::move(tmp1);
if(!invoke(pred, invoke(proj, tmp2), invoke(proj, result.max)))
result.max = (decltype(tmp2) &&)tmp2;
}
}
}
return result;
}
/// \overload
template(typename T, typename C = less, typename P = identity)(
requires copyable<T> AND
indirect_strict_weak_order<C, projected<T const *, P>>)
constexpr minmax_result<T> RANGES_FUNC(minmax)(
std::initializer_list<T> const && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(rng, std::move(pred), std::move(proj));
}
RANGES_FUNC_END(minmax)
namespace cpp20
{
using ranges::minmax;
using ranges::minmax_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,112 @@
/// \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
//
// Implementation based on the code in libc++
// http://http://libcxx.llvm.org/
#ifndef RANGES_V3_ALGORITHM_MINMAX_ELEMENT_HPP
#define RANGES_V3_ALGORITHM_MINMAX_ELEMENT_HPP
#include <range/v3/range_fwd.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/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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I>
using minmax_element_result = detail::min_max_result<I, I>;
RANGES_FUNC_BEGIN(minmax_element)
/// \brief function template \c minmax_element
template(typename I, typename S, typename C = less, typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, projected<I, P>>)
constexpr minmax_element_result<I> //
RANGES_FUNC(minmax_element)(I first, S last, C pred = C{}, P proj = P{}) //
{
minmax_element_result<I> result{first, first};
if(first == last || ++first == last)
return result;
if(invoke(pred, invoke(proj, *first), invoke(proj, *result.min)))
result.min = first;
else
result.max = first;
while(++first != last)
{
I tmp = first;
if(++first == last)
{
if(invoke(pred, invoke(proj, *tmp), invoke(proj, *result.min)))
result.min = tmp;
else if(!invoke(pred, invoke(proj, *tmp), invoke(proj, *result.max)))
result.max = tmp;
break;
}
else
{
if(invoke(pred, invoke(proj, *first), invoke(proj, *tmp)))
{
if(invoke(pred, invoke(proj, *first), invoke(proj, *result.min)))
result.min = first;
if(!invoke(pred, invoke(proj, *tmp), invoke(proj, *result.max)))
result.max = tmp;
}
else
{
if(invoke(pred, invoke(proj, *tmp), invoke(proj, *result.min)))
result.min = tmp;
if(!invoke(pred, invoke(proj, *first), invoke(proj, *result.max)))
result.max = first;
}
}
}
return result;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>)
constexpr minmax_element_result<borrowed_iterator_t<Rng>> //
RANGES_FUNC(minmax_element)(Rng && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(minmax_element)
namespace cpp20
{
using ranges::minmax_element;
using ranges::minmax_element_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,175 @@
/// \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_MISMATCH_HPP
#define RANGES_V3_ALGORITHM_MISMATCH_HPP
#include <utility>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.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/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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I1, typename I2>
using mismatch_result = detail::in1_in2_result<I1, I2>;
RANGES_FUNC_BEGIN(mismatch)
/// \brief function template \c mismatch
template(typename I1,
typename S1,
typename I2,
typename C = equal_to,
typename P1 = identity,
typename P2 = identity)(
requires input_iterator<I1> AND sentinel_for<S1, I1> AND
input_iterator<I2> AND
indirect_relation<C, projected<I1, P1>, projected<I2, P2>>)
RANGES_DEPRECATED(
"Use the variant of ranges::mismatch that takes an upper bound for "
"both sequences")
mismatch_result<I1, I2> RANGES_FUNC(mismatch)(I1 begin1,
S1 end1,
I2 begin2,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
for(; begin1 != end1; ++begin1, ++begin2)
if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
break;
return {begin1, begin2};
}
/// \overload
template(typename I1,
typename S1,
typename I2,
typename S2,
typename C = equal_to,
typename P1 = identity,
typename P2 = identity)(
requires input_iterator<I1> AND sentinel_for<S1, I1> AND
input_iterator<I2> AND sentinel_for<S2, I2> AND
indirect_relation<C, projected<I1, P1>, projected<I2, P2>>)
constexpr mismatch_result<I1, I2> RANGES_FUNC(mismatch)(I1 begin1,
S1 end1,
I2 begin2,
S2 end2,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
for(; begin1 != end1 && begin2 != end2; ++begin1, ++begin2)
if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
break;
return {begin1, begin2};
}
/// \overload
template(typename Rng1,
typename I2Ref,
typename C = equal_to,
typename P1 = identity,
typename P2 = identity)( //s
requires input_range<Rng1> AND input_iterator<uncvref_t<I2Ref>> AND
indirect_relation<C,
projected<iterator_t<Rng1>, P1>,
projected<uncvref_t<I2Ref>, P2>>)
RANGES_DEPRECATED(
"Use the variant of ranges::mismatch that takes an upper bound for "
"both sequences")
mismatch_result<borrowed_iterator_t<Rng1>, uncvref_t<I2Ref>>
RANGES_FUNC(mismatch)(Rng1 && rng1,
I2Ref && begin2,
C pred = C{}, // see below [*]
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
RANGES_DIAGNOSTIC_PUSH
RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
return (*this)(begin(rng1),
end(rng1),
static_cast<uncvref_t<I2Ref> &&>(begin2),
std::move(pred),
std::move(proj1),
std::move(proj2));
RANGES_DIAGNOSTIC_POP
}
/// \overload
template(typename Rng1,
typename Rng2,
typename C = equal_to,
typename P1 = identity,
typename P2 = identity)(
requires input_range<Rng1> AND input_range<Rng2> AND
indirect_relation<C,
projected<iterator_t<Rng1>, P1>,
projected<iterator_t<Rng2>, P2>>)
constexpr mismatch_result<borrowed_iterator_t<Rng1>, borrowed_iterator_t<Rng2>> //
RANGES_FUNC(mismatch)(Rng1 && rng1,
Rng2 && rng2,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
return (*this)(begin(rng1),
end(rng1),
begin(rng2),
end(rng2),
std::move(pred),
std::move(proj1),
std::move(proj2));
}
RANGES_FUNC_END(mismatch)
namespace cpp20
{
using ranges::mismatch;
using ranges::mismatch_result;
} // namespace cpp20
// [*] In this case, the 'begin2' iterator is taken by universal reference. Why? So
// that we can properly distinguish this case:
// int x[] = {1,2,3,4};
// int y[] = {1,2,3,4};
// mismatch(x, y);
// Had 'begin2' been taken by value as is customary, this call could match as either
// two ranges, or a range and an iterator, where the iterator is the array, decayed
// to a pointer. Yuk!
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,88 @@
/// \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_MOVE_HPP
#define RANGES_V3_ALGORITHM_MOVE_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/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/move.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using move_result = detail::in_out_result<I, O>;
RANGES_HIDDEN_DETAIL(namespace _move CPP_PP_LBRACE())
RANGES_FUNC_BEGIN(move)
/// \brief function template \c move
template(typename I, typename S, typename O)(
requires input_iterator<I> AND sentinel_for<S, I> AND
weakly_incrementable<O> AND indirectly_movable<I, O>)
constexpr move_result<I, O> RANGES_FUNC(move)(I first, S last, O out) //
{
for(; first != last; ++first, ++out)
*out = iter_move(first);
return {first, out};
}
/// \overload
template(typename Rng, typename O)(
requires input_range<Rng> AND weakly_incrementable<O> AND
indirectly_movable<iterator_t<Rng>, O>)
constexpr move_result<borrowed_iterator_t<Rng>, O> //
RANGES_FUNC(move)(Rng && rng, O out) //
{
return (*this)(begin(rng), end(rng), std::move(out));
}
RANGES_FUNC_END(move)
RANGES_HIDDEN_DETAIL(CPP_PP_RBRACE())
#ifndef RANGES_DOXYGEN_INVOKED
struct RANGES_EMPTY_BASES move_fn
: aux::move_fn
, _move::move_fn
{
using aux::move_fn::operator();
using _move::move_fn::operator();
};
RANGES_INLINE_VARIABLE(move_fn, move)
#endif
namespace cpp20
{
using ranges::move_result;
using ranges::RANGES_HIDDEN_DETAIL(_move::) move;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,75 @@
/// \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_MOVE_BACKWARD_HPP
#define RANGES_V3_ALGORITHM_MOVE_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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using move_backward_result = detail::in_out_result<I, O>;
RANGES_FUNC_BEGIN(move_backward)
/// \brief function template \c move_backward
template(typename I, typename S, typename O)(
requires bidirectional_iterator<I> AND sentinel_for<S, I> AND
bidirectional_iterator<O> AND indirectly_movable<I, O>)
constexpr move_backward_result<I, O> RANGES_FUNC(move_backward)(I first, S end_, O out) //
{
I i = ranges::next(first, end_), last = i;
while(first != i)
*--out = iter_move(--i);
return {last, out};
}
/// \overload
template(typename Rng, typename O)(
requires bidirectional_range<Rng> AND bidirectional_iterator<O> AND
indirectly_movable<iterator_t<Rng>, O>)
constexpr move_backward_result<borrowed_iterator_t<Rng>, O> //
RANGES_FUNC(move_backward)(Rng && rng, O out) //
{
return (*this)(begin(rng), end(rng), std::move(out));
}
RANGES_FUNC_END(move_backward)
namespace cpp20
{
using ranges::move_backward;
using ranges::move_backward_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,70 @@
/// \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_NONE_OF_HPP
#define RANGES_V3_ALGORITHM_NONE_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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(none_of)
/// \brief function template \c none_of
template(typename I, typename S, typename F, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<F, projected<I, P>>)
constexpr bool RANGES_FUNC(none_of)(I first, S last, F pred, P proj = P{}) //
{
for(; first != last; ++first)
if(invoke(pred, invoke(proj, *first)))
return false;
return true;
}
/// \overload
template(typename Rng, typename F, typename P = identity)(
requires input_range<Rng> AND
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>)
constexpr bool RANGES_FUNC(none_of)(Rng && rng, F pred, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(none_of)
namespace cpp20
{
using ranges::none_of;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,337 @@
/// \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_NTH_ELEMENT_HPP
#define RANGES_V3_ALGORITHM_NTH_ELEMENT_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/min_element.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/optional.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/utility/swap.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \cond
namespace detail
{
// stable, 2-3 compares, 0-2 swaps
template(typename I, typename C, typename P)(
requires forward_iterator<I> AND indirect_relation<C, projected<I, P>>)
unsigned sort3(I x, I y, I z, C & pred, P & proj)
{
unsigned r = 0;
if(!invoke(pred, invoke(proj, *y), invoke(proj, *x))) // if x <= y
{
if(!invoke(pred, invoke(proj, *z), invoke(proj, *y))) // if y <= z
return r; // x <= y && y <= z
// x <= y && y > z
ranges::iter_swap(y, z); // x <= z && y < z
r = 1;
if(invoke(pred, invoke(proj, *y), invoke(proj, *x))) // if x > y
{
ranges::iter_swap(x, y); // x < y && y <= z
r = 2;
}
return r; // x <= y && y < z
}
if(invoke(pred, invoke(proj, *z), invoke(proj, *y))) // x > y, if y > z
{
ranges::iter_swap(x, z); // x < y && y < z
r = 1;
return r;
}
ranges::iter_swap(x, y); // x > y && y <= z
r = 1; // x < y && x <= z
if(invoke(pred, invoke(proj, *z), invoke(proj, *y))) // if y > z
{
ranges::iter_swap(y, z); // x <= y && y < z
r = 2;
}
return r;
} // x <= y && y <= z
template(typename I, typename C, typename P)(
requires bidirectional_iterator<I> AND indirect_relation<C, projected<I, P>>)
void selection_sort(I first, I last, C & pred, P & proj)
{
RANGES_EXPECT(first != last);
for(I lm1 = ranges::prev(last); first != lm1; ++first)
{
I i = ranges::min_element(first, last, std::ref(pred), std::ref(proj));
if(i != first)
ranges::iter_swap(first, i);
}
}
} // namespace detail
/// \endcond
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(nth_element)
/// \brief function template \c nth_element
template(typename I, typename S, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sortable<I, C, P>)
constexpr I RANGES_FUNC(nth_element)(
I first, I nth, S end_, C pred = C{}, P proj = P{}) //
{
I last = ranges::next(nth, end_), end_orig = last;
// C is known to be a reference type
using difference_type = iter_difference_t<I>;
difference_type const limit = 7;
while(true)
{
if(nth == last)
return end_orig;
difference_type len = last - first;
switch(len)
{
case 0:
case 1:
return end_orig;
case 2:
if(invoke(pred, invoke(proj, *--last), invoke(proj, *first)))
ranges::iter_swap(first, last);
return end_orig;
case 3:
{
I m = first;
detail::sort3(first, ++m, --last, pred, proj);
return end_orig;
}
}
if(len <= limit)
{
detail::selection_sort(first, last, pred, proj);
return end_orig;
}
// len > limit >= 3
I m = first + len / 2;
I lm1 = last;
unsigned n_swaps = detail::sort3(first, m, --lm1, pred, proj);
// *m is median
// partition [first, m) < *m and *m <= [m, last)
//(this inhibits tossing elements equivalent to m around unnecessarily)
I i = first;
I j = lm1;
// j points beyond range to be tested, *lm1 is known to be <= *m
// The search going up is known to be guarded but the search coming down
// isn't. Prime the downward search with a guard.
if(!invoke(pred, invoke(proj, *i), invoke(proj, *m))) // if *first == *m
{
// *first == *m, *first doesn't go in first part
// manually guard downward moving j against i
while(true)
{
if(i == --j)
{
// *first == *m, *m <= all other elements
// Parition instead into [first, i) == *first and *first < [i,
// last)
++i; // first + 1
j = last;
if(!invoke(
pred,
invoke(proj, *first),
invoke(
proj,
*--j))) // we need a guard if *first == *(last-1)
{
while(true)
{
if(i == j)
return end_orig; // [first, last) all equivalent
// elements
if(invoke(
pred, invoke(proj, *first), invoke(proj, *i)))
{
ranges::iter_swap(i, j);
++n_swaps;
++i;
break;
}
++i;
}
}
// [first, i) == *first and *first < [j, last) and j == last -
// 1
if(i == j)
return end_orig;
while(true)
{
while(
!invoke(pred, invoke(proj, *first), invoke(proj, *i)))
++i;
while(invoke(
pred, invoke(proj, *first), invoke(proj, *--j)))
;
if(i >= j)
break;
ranges::iter_swap(i, j);
++n_swaps;
++i;
}
// [first, i) == *first and *first < [i, last)
// The first part is sorted,
if(nth < i)
return end_orig;
// nth_element the second part
// nth_element<C>(i, nth, last, pred);
first = i;
continue;
}
if(invoke(pred, invoke(proj, *j), invoke(proj, *m)))
{
ranges::iter_swap(i, j);
++n_swaps;
break; // found guard for downward moving j, now use unguarded
// partition
}
}
}
++i;
// j points beyond range to be tested, *lm1 is known to be <= *m
// if not yet partitioned...
if(i < j)
{
// known that *(i - 1) < *m
while(true)
{
// m still guards upward moving i
while(invoke(pred, invoke(proj, *i), invoke(proj, *m)))
++i;
// It is now known that a guard exists for downward moving j
while(!invoke(pred, invoke(proj, *--j), invoke(proj, *m)))
;
if(i >= j)
break;
ranges::iter_swap(i, j);
++n_swaps;
// It is known that m != j
// If m just moved, follow it
if(m == i)
m = j;
++i;
}
}
// [first, i) < *m and *m <= [i, last)
if(i != m && invoke(pred, invoke(proj, *m), invoke(proj, *i)))
{
ranges::iter_swap(i, m);
++n_swaps;
}
// [first, i) < *i and *i <= [i+1, last)
if(nth == i)
return end_orig;
const auto optional_return = [&]() -> ranges::optional<I> {
if(n_swaps == 0)
{
// We were given a perfectly partitioned sequence. Coincidence?
if(nth < i)
{
// Check for [first, i) already sorted
j = m = first;
while(++j != i)
{
if(invoke(pred, invoke(proj, *j), invoke(proj, *m)))
// not yet sorted, so sort
return ranges::nullopt;
m = j;
}
// [first, i) sorted
return end_orig;
}
else
{
// Check for [i, last) already sorted
j = m = i;
while(++j != last)
{
if(invoke(pred, invoke(proj, *j), invoke(proj, *m)))
// not yet sorted, so sort
return ranges::nullopt;
m = j;
}
// [i, last) sorted
return end_orig;
}
}
return ranges::nullopt;
}();
if(optional_return)
{
return *optional_return;
}
// nth_element on range containing nth
if(nth < i)
{
// nth_element<C>(first, nth, i, pred);
last = i;
}
else
{
// nth_element<C>(i+1, nth, last, pred);
first = ++i;
}
}
return end_orig;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires random_access_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(nth_element)(
Rng && rng, iterator_t<Rng> nth, C pred = C{}, P proj = P{}) //
{
return (*this)(
begin(rng), std::move(nth), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(nth_element)
namespace cpp20
{
using ranges::nth_element;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,87 @@
/// \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_PARTIAL_SORT_HPP
#define RANGES_V3_ALGORITHM_PARTIAL_SORT_HPP
#include <functional>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/heap_algorithm.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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(partial_sort)
/// \brief function template \c partial_sort
template(typename I, typename S, typename C = less, typename P = identity)(
requires sortable<I, C, P> AND random_access_iterator<I> AND
sentinel_for<S, I>)
constexpr I RANGES_FUNC(partial_sort)(
I first, I middle, S last, C pred = C{}, P proj = P{}) //
{
make_heap(first, middle, ranges::ref(pred), ranges::ref(proj));
auto const len = middle - first;
I i = middle;
for(; i != last; ++i)
{
if(invoke(pred, invoke(proj, *i), invoke(proj, *first)))
{
iter_swap(i, first);
detail::sift_down_n(
first, len, first, ranges::ref(pred), ranges::ref(proj));
}
}
sort_heap(first, middle, ranges::ref(pred), ranges::ref(proj));
return i;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires sortable<iterator_t<Rng>, C, P> AND random_access_range<Rng>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(partial_sort)(
Rng && rng, iterator_t<Rng> middle, C pred = C{}, P proj = P{}) //
{
return (*this)(begin(rng),
std::move(middle),
end(rng),
std::move(pred),
std::move(proj));
}
RANGES_FUNC_END(partial_sort)
namespace cpp20
{
using ranges::partial_sort;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,123 @@
/// \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_PARTIAL_SORT_COPY_HPP
#define RANGES_V3_ALGORITHM_PARTIAL_SORT_COPY_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/heap_algorithm.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>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(partial_sort_copy)
/// \brief function template \c partial_sort_copy
template(typename I,
typename SI,
typename O,
typename SO,
typename C = less,
typename PI = identity,
typename PO = identity)(
requires input_iterator<I> AND sentinel_for<SI, I> AND
random_access_iterator<O> AND sentinel_for<SO, O> AND
indirectly_copyable<I, O> AND sortable<O, C, PO> AND
indirect_strict_weak_order<C, projected<I, PI>, projected<O, PO>>)
constexpr O RANGES_FUNC(partial_sort_copy)(I first,
SI last,
O out_begin,
SO out_end,
C pred = C{},
PI in_proj = PI{},
PO out_proj = PO{}) //
{
O r = out_begin;
if(r != out_end)
{
for(; first != last && r != out_end; ++first, ++r)
*r = *first;
make_heap(out_begin, r, ranges::ref(pred), ranges::ref(out_proj));
auto len = r - out_begin;
for(; first != last; ++first)
{
auto && x = *first;
if(invoke(pred, invoke(in_proj, x), invoke(out_proj, *out_begin)))
{
*out_begin = (decltype(x) &&)x;
detail::sift_down_n(out_begin,
len,
out_begin,
ranges::ref(pred),
ranges::ref(out_proj));
}
}
sort_heap(out_begin, r, ranges::ref(pred), ranges::ref(out_proj));
}
return r;
}
/// \overload
template(typename InRng,
typename OutRng,
typename C = less,
typename PI = identity,
typename PO = identity)(
requires input_range<InRng> AND random_access_range<OutRng> AND
indirectly_copyable<iterator_t<InRng>, iterator_t<OutRng>> AND
sortable<iterator_t<OutRng>, C, PO> AND
indirect_strict_weak_order<C,
projected<iterator_t<InRng>, PI>,
projected<iterator_t<OutRng>, PO>>)
constexpr borrowed_iterator_t<OutRng> RANGES_FUNC(partial_sort_copy)(InRng && in_rng,
OutRng && out_rng,
C pred = C{},
PI in_proj = PI{},
PO out_proj = PO{}) //
{
return (*this)(begin(in_rng),
end(in_rng),
begin(out_rng),
end(out_rng),
std::move(pred),
std::move(in_proj),
std::move(out_proj));
}
RANGES_FUNC_END(partial_sort_copy)
namespace cpp20
{
using ranges::partial_sort_copy;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@ -0,0 +1,137 @@
/// \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_PARTITION_HPP
#define RANGES_V3_ALGORITHM_PARTITION_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/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>
#include <range/v3/utility/swap.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
/// \cond
namespace detail
{
template<typename I, typename S, typename C, typename P>
constexpr I partition_impl(I first, S last, C pred, P proj, std::forward_iterator_tag)
{
while(true)
{
if(first == last)
return first;
if(!invoke(pred, invoke(proj, *first)))
break;
++first;
}
for(I p = first; ++p != last;)
{
if(invoke(pred, invoke(proj, *p)))
{
ranges::iter_swap(first, p);
++first;
}
}
return first;
}
template<typename I, typename S, typename C, typename P>
constexpr I partition_impl(I first, S end_, C pred, P proj, std::bidirectional_iterator_tag)
{
I last = ranges::next(first, end_);
while(true)
{
while(true)
{
if(first == last)
return first;
if(!invoke(pred, invoke(proj, *first)))
break;
++first;
}
do
{
if(first == --last)
return first;
} while(!invoke(pred, invoke(proj, *last)));
ranges::iter_swap(first, last);
++first;
}
}
} // namespace detail
/// \endcond
RANGES_FUNC_BEGIN(partition)
/// \brief function template \c partition
template(typename I, typename S, typename C, typename P = identity)(
requires permutable<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<C, projected<I, P>>)
constexpr I RANGES_FUNC(partition)(I first, S last, C pred, P proj = P{})
{
return detail::partition_impl(std::move(first),
std::move(last),
std::move(pred),
std::move(proj),
iterator_tag_of<I>());
}
/// \overload
template(typename Rng, typename C, typename P = identity)(
requires forward_range<Rng> AND permutable<iterator_t<Rng>> AND
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(partition)(Rng && rng, C pred, P proj = P{})
{
return detail::partition_impl(begin(rng),
end(rng),
std::move(pred),
std::move(proj),
iterator_tag_of<iterator_t<Rng>>());
}
RANGES_FUNC_END(partition)
namespace cpp20
{
using ranges::partition;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

Some files were not shown because too many files have changed in this diff Show More