mirror of https://github.com/axmolengine/axmol.git
Working on c++23
There are many more efficient features on future c++23 standard
This commit is contained in:
parent
ff75289a07
commit
49284f4cc2
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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('/');
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
//
|
|
@ -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).
|
|
@ -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
|
@ -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
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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"
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
Loading…
Reference in New Issue