diff --git a/core/base/axstd.h b/core/base/axstd.h index 02e793dd0e..9d0650b5bf 100644 --- a/core/base/axstd.h +++ b/core/base/axstd.h @@ -4,6 +4,36 @@ #include #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 { /* make_unique_for_overwrite since c++20, but not all platformm support */ diff --git a/core/base/ccUtils.cpp b/core/base/ccUtils.cpp index 31f0f1ece6..5615c2327f 100644 --- a/core/base/ccUtils.cpp +++ b/core/base/ccUtils.cpp @@ -57,6 +57,7 @@ THE SOFTWARE. #include "2d/CCRenderTexture.h" #include "base/base64.h" +#include "base/axstd.h" 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 * */ -#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()); }); #else ret.resize(n); @@ -828,7 +829,7 @@ AX_DLL std::string base64Decode(std::string_view s) { 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()); }); #else ret.resize(n); diff --git a/core/network/HttpCookie.cpp b/core/network/HttpCookie.cpp index 8830faca79..63a82592e3 100644 --- a/core/network/HttpCookie.cpp +++ b/core/network/HttpCookie.cpp @@ -2,15 +2,19 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. Copyright (c) 2021 Bytedance Inc. + https://axmolengine.github.io/ + 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 @@ -25,13 +29,14 @@ #include "platform/CCFileUtils.h" #include "yasio/detail/utils.hpp" #include "yasio/stl/string_view.hpp" -#include "xsbase/fast_split.hpp" #include #include #include #include #include +#include +#include "base/axstd.h" NS_AX_BEGIN @@ -53,42 +58,41 @@ void HttpCookie::readFile() std::string inString = ax::FileUtils::getInstance()->getStringFromFile(_cookieFileName); if (!inString.empty()) { - xsbase::fast_split(inString, '\n', [this](char* s, char* e) { - if (*s == '#') // skip comment - return; + for (auto line : axstd::views::split(inString, '\n')) + { + if (line.empty() || *line.begin() == '#') // skip comment + continue; int count = 0; CookieInfo cookieInfo; using namespace cxx17; - xsbase::fast_split(s, e - s, '\t', [&, this](char* ss, char* ee) { - auto ch = *ee; // store - *ee = '\0'; + for (auto subrgn : axstd::views::split(line, '\t')) { + std::string_view word{&*subrgn.begin(), static_cast(axstd::ranges::distance(subrgn))}; switch (count) { case DOMAIN_INDEX: - cookieInfo.domain.assign(ss, ee - ss); + cookieInfo.domain = word; break; case PATH_INDEX: - cookieInfo.path.assign(ss, ee - ss); + cookieInfo.path = word; break; case SECURE_INDEX: - cookieInfo.secure = cxx17::string_view{ss, (size_t)(ee - ss)} == "TRUE"_sv; + cookieInfo.secure = word == "TRUE"_sv; break; case EXPIRES_INDEX: - cookieInfo.expires = static_cast(strtoll(ss, nullptr, 10)); + std::from_chars(word.data(), word.data() + word.size(), cookieInfo.expires); break; case NAME_INDEX: - cookieInfo.name.assign(ss, ee - ss); + cookieInfo.name = word; break; case VALUE_INDEX: - cookieInfo.value.assign(ss, ee - ss); + cookieInfo.value = word; break; } - *ee = ch; // restore ++count; - }); + } if (count >= 7) _cookies.emplace_back(std::move(cookieInfo)); - }); + } } } @@ -151,25 +155,29 @@ bool HttpCookie::updateOrAddCookie(std::string_view cookie, const Uri& uri) { unsigned int count = 0; 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; - while (*start == ' ') - ++start; // skip ws + std::string_view citem{&*rgn.begin(), static_cast(axstd::ranges::distance(rgn))}; + while (*citem.data() == ' ') + citem.remove_prefix(1); // skip ws if (++count > 1) { cxx17::string_view key; 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(axstd::ranges::distance(subrgn))}; switch (++count_) { case 1: - key = cxx17::string_view(s, e - s); + key = word; break; case 2: - value = cxx17::string_view(s, e - s); + value = word; break; } - }); + } using namespace cxx17; 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)) expires_ctime.resize(expires_ctime.length() - sizeof(" GMT") + 1); if (expires_ctime.empty()) - return; + continue; size_t off = 0; auto p = expires_ctime.find_first_of(','); if (p != std::string::npos) @@ -220,19 +228,21 @@ bool HttpCookie::updateOrAddCookie(std::string_view cookie, const Uri& uri) } else { // 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(axstd::ranges::distance(rgn))}; switch (++count_) { case 1: - info.name.assign(s, e - s); + info.name = word; break; case 2: - info.value.assign(s, e - s); + info.value = word; break; } - }); + } } - }); + } if (info.path.empty()) info.path.push_back('/'); diff --git a/core/platform/CCSAXParser.cpp b/core/platform/CCSAXParser.cpp index 94f75ce174..479fb1188a 100644 --- a/core/platform/CCSAXParser.cpp +++ b/core/platform/CCSAXParser.cpp @@ -29,7 +29,7 @@ #include // because its based on windows 8 build :P #include "platform/CCFileUtils.h" -#include "xsbase/xsxml/xsxml.hpp" +#include "xsxml/xsxml.hpp" NS_AX_BEGIN diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 00f0b1dae2..bf27c8950f 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -163,6 +163,7 @@ add_library(thirdparty STATIC empty.cpp) # bellow are header only libs target_include_directories(thirdparty INTERFACE "robin-map/include" + INTERFACE "range-v3/include" ) if (ANDROID) diff --git a/thirdparty/pugixml/pugixml.hpp b/thirdparty/pugixml/pugixml.hpp index 8adbb6fcd7..c5f1ba0438 100644 --- a/thirdparty/pugixml/pugixml.hpp +++ b/thirdparty/pugixml/pugixml.hpp @@ -59,6 +59,17 @@ # define PUGI_CXX_STD 20 #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) # define PUGI_CXX_STD 11 #endif diff --git a/thirdparty/range-v3/LICENSE.txt b/thirdparty/range-v3/LICENSE.txt new file mode 100644 index 0000000000..698193e974 --- /dev/null +++ b/thirdparty/range-v3/LICENSE.txt @@ -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. +// diff --git a/thirdparty/range-v3/README.md b/thirdparty/range-v3/README.md new file mode 100644 index 0000000000..3a5f2f6774 --- /dev/null +++ b/thirdparty/range-v3/README.md @@ -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). diff --git a/thirdparty/range-v3/include/concepts/compare.hpp b/thirdparty/range-v3/include/concepts/compare.hpp new file mode 100644 index 0000000000..e7598d2280 --- /dev/null +++ b/thirdparty/range-v3/include/concepts/compare.hpp @@ -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() && \ + defined(__cpp_concepts) && defined(__cpp_impl_three_way_comparison) + +#include +#include +#include + +// 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 + concept compares_as = same_as, Cat>; + } // namespace detail + + inline namespace defs + { + template + concept three_way_comparable = + detail::weakly_equality_comparable_with_ && + detail::partially_ordered_with_ && + requires(detail::as_cref_t& a, detail::as_cref_t& b) { + { a <=> b } -> detail::compares_as; + }; + + template + concept three_way_comparable_with = + three_way_comparable && + three_way_comparable && + common_reference_with&, detail::as_cref_t&> && + three_way_comparable&, detail::as_cref_t&>> && + detail::partially_ordered_with_ && + requires(detail::as_cref_t& t, detail::as_cref_t& u) { + { t <=> u } -> detail::compares_as; + { u <=> t } -> detail::compares_as; + }; + } // inline namespace defs +} // namespace concepts + +// clang-format on + +#endif // __cplusplus +#endif // CPP_COMPARE_HPP diff --git a/thirdparty/range-v3/include/concepts/concepts.hpp b/thirdparty/range-v3/include/concepts/concepts.hpp new file mode 100644 index 0000000000..20cd1f644f --- /dev/null +++ b/thirdparty/range-v3/include/concepts/concepts.hpp @@ -0,0 +1,1233 @@ +/// \file +// CPP, the Concepts PreProcessor library +// +// Copyright Eric Niebler 2018-present +// Copyright (c) 2018-present, Facebook, Inc. +// 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_CONCEPTS_HPP +#define CPP_CONCEPTS_HPP + +// clang-format off + +#include +#include +#include +#include +#include + +// Disable buggy clang compatibility warning about "requires" and "concept" being +// C++20 keywords. +// https://bugs.llvm.org/show_bug.cgi?id=43708 +#if defined(__clang__) && __cplusplus <= 201703L +#define CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN \ + CPP_DIAGNOSTIC_PUSH \ + CPP_DIAGNOSTIC_IGNORE_CPP2A_COMPAT + +#define CPP_PP_IGNORE_CXX2A_COMPAT_END \ + CPP_DIAGNOSTIC_POP + +#else +#define CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN +#define CPP_PP_IGNORE_CXX2A_COMPAT_END +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define CPP_WORKAROUND_MSVC_779763 // FATAL_UNREACHABLE calling constexpr function via template parameter +#define CPP_WORKAROUND_MSVC_784772 // Failure to invoke *explicit* bool conversion in a constant expression +#endif + +#if !defined(CPP_CXX_CONCEPTS) +#ifdef CPP_DOXYGEN_INVOKED +#define CPP_CXX_CONCEPTS 201800L +#elif defined(__cpp_concepts) && __cpp_concepts > 0 +// gcc-6 concepts are too buggy to use +#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 7 +#define CPP_CXX_CONCEPTS __cpp_concepts +#else +#define CPP_CXX_CONCEPTS 0L +#endif +#else +#define CPP_CXX_CONCEPTS 0L +#endif +#endif + +#define CPP_PP_CAT_(X, ...) X ## __VA_ARGS__ +#define CPP_PP_CAT(X, ...) CPP_PP_CAT_(X, __VA_ARGS__) + +#define CPP_PP_EVAL_(X, ARGS) X ARGS +#define CPP_PP_EVAL(X, ...) CPP_PP_EVAL_(X, (__VA_ARGS__)) + +#define CPP_PP_EVAL2_(X, ARGS) X ARGS +#define CPP_PP_EVAL2(X, ...) CPP_PP_EVAL2_(X, (__VA_ARGS__)) + +#define CPP_PP_EXPAND(...) __VA_ARGS__ +#define CPP_PP_EAT(...) + +#define CPP_PP_FIRST(LIST) CPP_PP_FIRST_ LIST +#define CPP_PP_FIRST_(...) __VA_ARGS__ CPP_PP_EAT + +#define CPP_PP_SECOND(LIST) CPP_PP_SECOND_ LIST +#define CPP_PP_SECOND_(...) CPP_PP_EXPAND + +#define CPP_PP_CHECK(...) CPP_PP_EXPAND(CPP_PP_CHECK_N(__VA_ARGS__, 0,)) +#define CPP_PP_CHECK_N(x, n, ...) n +#define CPP_PP_PROBE(x) x, 1, +#define CPP_PP_PROBE_N(x, n) x, n, + +#define CPP_PP_IS_PAREN(x) CPP_PP_CHECK(CPP_PP_IS_PAREN_PROBE x) +#define CPP_PP_IS_PAREN_PROBE(...) CPP_PP_PROBE(~) + +// CPP_CXX_VA_OPT +#ifndef CPP_CXX_VA_OPT +#if __cplusplus > 201703L +#define CPP_CXX_VA_OPT_(...) CPP_PP_CHECK(__VA_OPT__(,) 1) +#define CPP_CXX_VA_OPT CPP_CXX_VA_OPT_(~) +#else +#define CPP_CXX_VA_OPT 0 +#endif +#endif // CPP_CXX_VA_OPT + +// The final CPP_PP_EXPAND here is to avoid +// https://stackoverflow.com/questions/5134523/msvc-doesnt-expand-va-args-correctly +#define CPP_PP_COUNT(...) \ + CPP_PP_EXPAND(CPP_PP_COUNT_(__VA_ARGS__, \ + 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,)) + +#define CPP_PP_COUNT_( \ + _01, _02, _03, _04, _05, _06, _07, _08, _09, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, N, ...) \ + N + +#define CPP_PP_IIF(BIT) CPP_PP_CAT_(CPP_PP_IIF_, BIT) +#define CPP_PP_IIF_0(TRUE, ...) __VA_ARGS__ +#define CPP_PP_IIF_1(TRUE, ...) TRUE + +#define CPP_PP_LPAREN ( +#define CPP_PP_RPAREN ) + +#define CPP_PP_NOT(BIT) CPP_PP_CAT_(CPP_PP_NOT_, BIT) +#define CPP_PP_NOT_0 1 +#define CPP_PP_NOT_1 0 + +#define CPP_PP_EMPTY() +#define CPP_PP_COMMA() , +#define CPP_PP_LBRACE() { +#define CPP_PP_RBRACE() } +#define CPP_PP_COMMA_IIF(X) \ + CPP_PP_IIF(X)(CPP_PP_EMPTY, CPP_PP_COMMA)() + +#define CPP_PP_FOR_EACH(M, ...) \ + CPP_PP_FOR_EACH_N(CPP_PP_COUNT(__VA_ARGS__), M, __VA_ARGS__) +#define CPP_PP_FOR_EACH_N(N, M, ...) \ + CPP_PP_CAT(CPP_PP_FOR_EACH_, N)(M, __VA_ARGS__) +#define CPP_PP_FOR_EACH_1(M, _1) \ + M(_1) +#define CPP_PP_FOR_EACH_2(M, _1, _2) \ + M(_1), M(_2) +#define CPP_PP_FOR_EACH_3(M, _1, _2, _3) \ + M(_1), M(_2), M(_3) +#define CPP_PP_FOR_EACH_4(M, _1, _2, _3, _4) \ + M(_1), M(_2), M(_3), M(_4) +#define CPP_PP_FOR_EACH_5(M, _1, _2, _3, _4, _5) \ + M(_1), M(_2), M(_3), M(_4), M(_5) +#define CPP_PP_FOR_EACH_6(M, _1, _2, _3, _4, _5, _6) \ + M(_1), M(_2), M(_3), M(_4), M(_5), M(_6) +#define CPP_PP_FOR_EACH_7(M, _1, _2, _3, _4, _5, _6, _7) \ + M(_1), M(_2), M(_3), M(_4), M(_5), M(_6), M(_7) +#define CPP_PP_FOR_EACH_8(M, _1, _2, _3, _4, _5, _6, _7, _8) \ + M(_1), M(_2), M(_3), M(_4), M(_5), M(_6), M(_7), M(_8) + +#define CPP_PP_PROBE_EMPTY_PROBE_CPP_PP_PROBE_EMPTY \ + CPP_PP_PROBE(~) + +#define CPP_PP_PROBE_EMPTY() +#define CPP_PP_IS_NOT_EMPTY(...) \ + CPP_PP_EVAL( \ + CPP_PP_CHECK, \ + CPP_PP_CAT( \ + CPP_PP_PROBE_EMPTY_PROBE_, \ + CPP_PP_PROBE_EMPTY __VA_ARGS__ ())) + +#if defined(_MSC_VER) && !defined(__clang__) && (__cplusplus <= 201703L) +#define CPP_BOOL(...) ::meta::bool_<__VA_ARGS__>::value +#define CPP_TRUE_FN \ + !::concepts::detail::instance_< \ + decltype(CPP_true_fn(::concepts::detail::xNil{}))> + +#define CPP_NOT(...) (!CPP_BOOL(__VA_ARGS__)) +#else +#define CPP_BOOL(...) __VA_ARGS__ +#define CPP_TRUE_FN CPP_true_fn(::concepts::detail::xNil{}) +#define CPP_NOT(...) (!(__VA_ARGS__)) +#endif + +#define CPP_assert(...) \ + static_assert(static_cast(__VA_ARGS__), \ + "Concept assertion failed : " #__VA_ARGS__) + +#define CPP_assert_msg static_assert + +#if CPP_CXX_CONCEPTS || defined(CPP_DOXYGEN_INVOKED) +#define CPP_concept META_CONCEPT +#define CPP_and && + +#else +#define CPP_concept CPP_INLINE_VAR constexpr bool +#define CPP_and CPP_and_sfinae + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// CPP_template +// Usage: +// CPP_template(typename A, typename B) +// (requires Concept1 CPP_and Concept2) +// void foo(A a, B b) +// {} +#if CPP_CXX_CONCEPTS +#if defined(CPP_DOXYGEN_INVOKED) +#define CPP_template(...) template<__VA_ARGS__> CPP_TEMPLATE_EXPAND_ +#define CPP_TEMPLATE_EXPAND_(X,Y) X Y +#else +#define CPP_template(...) template<__VA_ARGS__ CPP_TEMPLATE_AUX_ +#endif +#define CPP_template_def CPP_template +#define CPP_member +#define CPP_ctor(TYPE) TYPE CPP_CTOR_IMPL_1_ +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 10 +#define CPP_auto_member template +#else +#define CPP_auto_member +#endif + +/// INTERNAL ONLY +#define CPP_CTOR_IMPL_1_(...) (__VA_ARGS__) CPP_PP_EXPAND + +/// INTERNAL ONLY +#define CPP_TEMPLATE_AUX_(...) \ + > CPP_PP_CAT( \ + CPP_TEMPLATE_AUX_, \ + CPP_TEMPLATE_AUX_WHICH_(__VA_ARGS__,))(__VA_ARGS__) + +/// INTERNAL ONLY +#define CPP_TEMPLATE_AUX_WHICH_(FIRST, ...) \ + CPP_PP_EVAL( \ + CPP_PP_CHECK, \ + CPP_PP_CAT(CPP_TEMPLATE_PROBE_CONCEPT_, FIRST)) + +/// INTERNAL ONLY +#define CPP_TEMPLATE_PROBE_CONCEPT_concept \ + CPP_PP_PROBE(~) + +// A template with a requires clause +/// INTERNAL ONLY +#define CPP_TEMPLATE_AUX_0(...) __VA_ARGS__ + +// A concept definition +/// INTERNAL ONLY +#define CPP_TEMPLATE_AUX_1(DECL, ...) \ + CPP_concept CPP_CONCEPT_NAME_(DECL) = __VA_ARGS__ + +#if defined(CPP_DOXYGEN_INVOKED) +#define CPP_concept_ref(NAME, ...) \ + NAME<__VA_ARGS__> +#else +#define CPP_concept_ref(NAME, ...) \ + CPP_PP_CAT(NAME, concept_)<__VA_ARGS__> +#endif + +#else // ^^^^ with concepts / without concepts vvvv + +#define CPP_template CPP_template_sfinae +#define CPP_template_def CPP_template_def_sfinae +#define CPP_member CPP_member_sfinae +#define CPP_auto_member CPP_member_sfinae +#define CPP_ctor CPP_ctor_sfinae +#define CPP_concept_ref(NAME, ...) \ + (1u == sizeof(CPP_PP_CAT(NAME, concept_)( \ + (::concepts::detail::tag<__VA_ARGS__>*)nullptr))) + +/// INTERNAL ONLY +#define CPP_TEMPLATE_AUX_ CPP_TEMPLATE_SFINAE_AUX_ + +#endif + +#define CPP_template_sfinae(...) \ + CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN \ + template<__VA_ARGS__ CPP_TEMPLATE_SFINAE_AUX_ + +/// INTERNAL ONLY +#define CPP_TEMPLATE_SFINAE_PROBE_CONCEPT_concept \ + CPP_PP_PROBE(~) + +/// INTERNAL ONLY +#define CPP_TEMPLATE_SFINAE_AUX_WHICH_(FIRST, ...) \ + CPP_PP_EVAL( \ + CPP_PP_CHECK, \ + CPP_PP_CAT(CPP_TEMPLATE_SFINAE_PROBE_CONCEPT_, FIRST)) + +/// INTERNAL ONLY +#define CPP_TEMPLATE_SFINAE_AUX_(...) \ + CPP_PP_CAT( \ + CPP_TEMPLATE_SFINAE_AUX_, \ + CPP_TEMPLATE_SFINAE_AUX_WHICH_(__VA_ARGS__,))(__VA_ARGS__) + +// A template with a requires clause +/// INTERNAL ONLY +#define CPP_TEMPLATE_SFINAE_AUX_0(...) , \ + bool CPP_true = true, \ + std::enable_if_t< \ + CPP_PP_CAT(CPP_TEMPLATE_SFINAE_AUX_3_, __VA_ARGS__) && \ + CPP_BOOL(CPP_true), \ + int> = 0> \ + CPP_PP_IGNORE_CXX2A_COMPAT_END + +// A concept definition +/// INTERNAL ONLY +#define CPP_TEMPLATE_SFINAE_AUX_1(DECL, ...) , \ + bool CPP_true = true, \ + std::enable_if_t<__VA_ARGS__ && CPP_BOOL(CPP_true), int> = 0> \ + auto CPP_CONCEPT_NAME_(DECL)( \ + ::concepts::detail::tag*) \ + -> char(&)[1]; \ + auto CPP_CONCEPT_NAME_(DECL)(...) -> char(&)[2] \ + CPP_PP_IGNORE_CXX2A_COMPAT_END + +/// INTERNAL ONLY +#define CPP_CONCEPT_NAME_(DECL) \ + CPP_PP_EVAL( \ + CPP_PP_CAT, \ + CPP_PP_EVAL(CPP_PP_FIRST, CPP_EAT_CONCEPT_(DECL)), concept_) + +/// INTERNAL ONLY +#define CPP_CONCEPT_PARAMS_(DECL) \ + CPP_PP_EVAL(CPP_PP_SECOND, CPP_EAT_CONCEPT_(DECL)) + +/// INTERNAL ONLY +#define CPP_EAT_CONCEPT_(DECL) \ + CPP_PP_CAT(CPP_EAT_CONCEPT_, DECL) + +/// INTERNAL ONLY +#define CPP_EAT_CONCEPT_concept + +/// INTERNAL ONLY +#define CPP_and_sfinae \ + && CPP_BOOL(CPP_true), int> = 0, std::enable_if_t< + +/// INTERNAL ONLY +#define CPP_template_def_sfinae(...) \ + template<__VA_ARGS__ CPP_TEMPLATE_DEF_SFINAE_AUX_ + +/// INTERNAL ONLY +#define CPP_TEMPLATE_DEF_SFINAE_AUX_(...) , \ + bool CPP_true, \ + std::enable_if_t< \ + CPP_PP_CAT(CPP_TEMPLATE_SFINAE_AUX_3_, __VA_ARGS__) && \ + CPP_BOOL(CPP_true), \ + int>> + +/// INTERNAL ONLY +#define CPP_and_sfinae_def \ + && CPP_BOOL(CPP_true), int>, std::enable_if_t< + +/// INTERNAL ONLY +#define CPP_TEMPLATE_SFINAE_AUX_3_requires + +/// INTERNAL ONLY +#define CPP_member_sfinae \ + CPP_broken_friend_member + +/// INTERNAL ONLY +#define CPP_ctor_sfinae(TYPE) \ + CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN \ + TYPE CPP_CTOR_SFINAE_IMPL_1_ + +/// INTERNAL ONLY +#define CPP_CTOR_SFINAE_IMPL_1_(...) \ + (__VA_ARGS__ \ + CPP_PP_COMMA_IIF( \ + CPP_PP_NOT(CPP_PP_IS_NOT_EMPTY(__VA_ARGS__))) \ + CPP_CTOR_SFINAE_REQUIRES + +/// INTERNAL ONLY +#define CPP_CTOR_SFINAE_PROBE_NOEXCEPT_noexcept \ + CPP_PP_PROBE(~) + +/// INTERNAL ONLY +#define CPP_CTOR_SFINAE_MAKE_PROBE(FIRST,...) \ + CPP_PP_CAT(CPP_CTOR_SFINAE_PROBE_NOEXCEPT_, FIRST) + +/// INTERNAL ONLY +#define CPP_CTOR_SFINAE_REQUIRES(...) \ + CPP_PP_CAT( \ + CPP_CTOR_SFINAE_REQUIRES_, \ + CPP_PP_EVAL( \ + CPP_PP_CHECK, \ + CPP_CTOR_SFINAE_MAKE_PROBE(__VA_ARGS__,)))(__VA_ARGS__) + +// No noexcept-clause: +/// INTERNAL ONLY +#define CPP_CTOR_SFINAE_REQUIRES_0(...) \ + std::enable_if_t< \ + CPP_PP_CAT(CPP_TEMPLATE_SFINAE_AUX_3_, __VA_ARGS__) && CPP_TRUE_FN, \ + ::concepts::detail::Nil \ + > = {}) \ + CPP_PP_IGNORE_CXX2A_COMPAT_END + +// Yes noexcept-clause: +/// INTERNAL ONLY +#define CPP_CTOR_SFINAE_REQUIRES_1(...) \ + std::enable_if_t< \ + CPP_PP_EVAL(CPP_PP_CAT, \ + CPP_TEMPLATE_SFINAE_AUX_3_, \ + CPP_PP_CAT(CPP_CTOR_SFINAE_EAT_NOEXCEPT_, __VA_ARGS__)) && CPP_TRUE_FN,\ + ::concepts::detail::Nil \ + > = {}) \ + CPP_PP_EXPAND(CPP_PP_CAT(CPP_CTOR_SFINAE_SHOW_NOEXCEPT_, __VA_ARGS__))) + +/// INTERNAL ONLY +#define CPP_CTOR_SFINAE_EAT_NOEXCEPT_noexcept(...) + +/// INTERNAL ONLY +#define CPP_CTOR_SFINAE_SHOW_NOEXCEPT_noexcept(...) \ + noexcept(__VA_ARGS__) \ + CPP_PP_IGNORE_CXX2A_COMPAT_END \ + CPP_PP_EAT CPP_PP_LPAREN + +#ifdef CPP_DOXYGEN_INVOKED +/// INTERNAL ONLY +#define CPP_broken_friend_ret(...) \ + __VA_ARGS__ CPP_PP_EXPAND + +#else // ^^^ CPP_DOXYGEN_INVOKED / not CPP_DOXYGEN_INVOKED vvv +#define CPP_broken_friend_ret(...) \ + ::concepts::return_t< \ + __VA_ARGS__, \ + std::enable_if_t> + +#ifdef CPP_WORKAROUND_MSVC_779763 +/// INTERNAL ONLY +#define CPP_broken_friend_member \ + template<::concepts::detail::CPP_true_t const &CPP_true_fn = \ + ::concepts::detail::CPP_true_fn_> + +#else // ^^^ workaround / no workaround vvv +/// INTERNAL ONLY +#define CPP_broken_friend_member \ + template + +#endif // CPP_WORKAROUND_MSVC_779763 +#endif + +#if CPP_CXX_CONCEPTS +#if defined(CPP_DOXYGEN_INVOKED) +#define CPP_requires(NAME, REQS) \ + concept NAME = \ + CPP_PP_CAT(CPP_REQUIRES_, REQS) +#define CPP_requires_ref(NAME, ...) \ + NAME<__VA_ARGS__> +#else +#define CPP_requires(NAME, REQS) \ + CPP_concept CPP_PP_CAT(NAME, requires_) = \ + CPP_PP_CAT(CPP_REQUIRES_, REQS) +#define CPP_requires_ref(NAME, ...) \ + CPP_PP_CAT(NAME, requires_)<__VA_ARGS__> +#endif + +/// INTERNAL ONLY +#define CPP_REQUIRES_requires(...) \ + requires(__VA_ARGS__) CPP_REQUIRES_AUX_ + +/// INTERNAL ONLY +#define CPP_REQUIRES_AUX_(...) \ + { __VA_ARGS__; } + +#else +#define CPP_requires(NAME, REQS) \ + auto CPP_PP_CAT(NAME, requires_test_) \ + CPP_REQUIRES_AUX_(NAME, CPP_REQUIRES_ ## REQS) + +#define CPP_requires_ref(NAME, ...) \ + (1u == sizeof(CPP_PP_CAT(NAME, requires_)( \ + (::concepts::detail::tag<__VA_ARGS__>*)nullptr))) + +/// INTERNAL ONLY +#define CPP_REQUIRES_requires(...) \ + (__VA_ARGS__) -> decltype CPP_REQUIRES_RETURN_ + +/// INTERNAL ONLY +#define CPP_REQUIRES_RETURN_(...) (__VA_ARGS__, void()) {} + +/// INTERNAL ONLY +#define CPP_REQUIRES_AUX_(NAME, ...) \ + __VA_ARGS__ \ + template \ + auto CPP_PP_CAT(NAME, requires_)( \ + ::concepts::detail::tag *, \ + decltype(&CPP_PP_CAT(NAME, requires_test_)) = nullptr) \ + -> char(&)[1]; \ + auto CPP_PP_CAT(NAME, requires_)(...) -> char(&)[2] + +#endif + +#if CPP_CXX_CONCEPTS +#define CPP_ret(...) \ + __VA_ARGS__ CPP_PP_EXPAND +#else +#define CPP_ret \ + CPP_broken_friend_ret +#endif + +//////////////////////////////////////////////////////////////////////////////// +// CPP_fun +#if CPP_CXX_CONCEPTS + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_1_(...) \ + (__VA_ARGS__) \ + CPP_PP_EXPAND + +#define CPP_fun(X) X CPP_FUN_IMPL_1_ +#else +/// INTERNAL ONLY +#define CPP_FUN_IMPL_1_(...) \ + (__VA_ARGS__ \ + CPP_PP_COMMA_IIF( \ + CPP_PP_NOT(CPP_PP_IS_NOT_EMPTY(__VA_ARGS__))) \ + CPP_FUN_IMPL_REQUIRES + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_REQUIRES(...) \ + CPP_PP_EVAL2_( \ + CPP_FUN_IMPL_SELECT_CONST_, \ + (__VA_ARGS__,) \ + )(__VA_ARGS__) + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_SELECT_CONST_(MAYBE_CONST, ...) \ + CPP_PP_CAT(CPP_FUN_IMPL_SELECT_CONST_, \ + CPP_PP_EVAL(CPP_PP_CHECK, CPP_PP_CAT( \ + CPP_PP_PROBE_CONST_PROBE_, MAYBE_CONST))) + +/// INTERNAL ONLY +#define CPP_PP_PROBE_CONST_PROBE_const CPP_PP_PROBE(~) + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_SELECT_CONST_1(...) \ + CPP_PP_EVAL( \ + CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_, \ + CPP_PP_CAT(CPP_FUN_IMPL_EAT_CONST_, __VA_ARGS__),)( \ + CPP_PP_CAT(CPP_FUN_IMPL_EAT_CONST_, __VA_ARGS__)) + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_(MAYBE_NOEXCEPT, ...) \ + CPP_PP_CAT(CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_, \ + CPP_PP_EVAL2(CPP_PP_CHECK, CPP_PP_CAT( \ + CPP_PP_PROBE_NOEXCEPT_PROBE_, MAYBE_NOEXCEPT))) + +/// INTERNAL ONLY +#define CPP_PP_PROBE_NOEXCEPT_PROBE_noexcept CPP_PP_PROBE(~) + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_0(...) \ + std::enable_if_t< \ + CPP_PP_EVAL( \ + CPP_PP_CAT, \ + CPP_FUN_IMPL_EAT_REQUIRES_, \ + __VA_ARGS__) && CPP_TRUE_FN, \ + ::concepts::detail::Nil \ + > = {}) const \ + CPP_PP_IGNORE_CXX2A_COMPAT_END + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_1(...) \ + std::enable_if_t< \ + CPP_PP_EVAL( \ + CPP_PP_CAT, \ + CPP_FUN_IMPL_EAT_REQUIRES_, \ + CPP_PP_CAT(CPP_FUN_IMPL_EAT_NOEXCEPT_, __VA_ARGS__)) && CPP_TRUE_FN,\ + ::concepts::detail::Nil \ + > = {}) const \ + CPP_PP_EXPAND(CPP_PP_CAT(CPP_FUN_IMPL_SHOW_NOEXCEPT_, __VA_ARGS__))) + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_EAT_NOEXCEPT_noexcept(...) + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_SHOW_NOEXCEPT_noexcept(...) \ + noexcept(__VA_ARGS__) CPP_PP_IGNORE_CXX2A_COMPAT_END \ + CPP_PP_EAT CPP_PP_LPAREN + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_SELECT_CONST_0(...) \ + CPP_PP_EVAL_( \ + CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_, \ + (__VA_ARGS__,) \ + )(__VA_ARGS__) + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_(MAYBE_NOEXCEPT, ...) \ + CPP_PP_CAT(CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_, \ + CPP_PP_EVAL2(CPP_PP_CHECK, CPP_PP_CAT( \ + CPP_PP_PROBE_NOEXCEPT_PROBE_, MAYBE_NOEXCEPT))) + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_0(...) \ + std::enable_if_t< \ + CPP_PP_CAT(CPP_FUN_IMPL_EAT_REQUIRES_, __VA_ARGS__) && CPP_TRUE_FN, \ + ::concepts::detail::Nil \ + > = {}) \ + CPP_PP_IGNORE_CXX2A_COMPAT_END + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_1(...) \ + std::enable_if_t< \ + CPP_PP_EVAL( \ + CPP_PP_CAT, \ + CPP_FUN_IMPL_EAT_REQUIRES_, \ + CPP_PP_CAT(CPP_FUN_IMPL_EAT_NOEXCEPT_, __VA_ARGS__) \ + ) && CPP_TRUE_FN, \ + ::concepts::detail::Nil \ + > = {}) \ + CPP_PP_EXPAND(CPP_PP_CAT(CPP_FUN_IMPL_SHOW_NOEXCEPT_, __VA_ARGS__))) + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_EAT_CONST_const + +/// INTERNAL ONLY +#define CPP_FUN_IMPL_EAT_REQUIRES_requires + +//////////////////////////////////////////////////////////////////////////////// +// CPP_fun +// Usage: +// template +// void CPP_fun(foo)(A a, B b)([const]opt [noexcept(true)]opt +// requires Concept1 && Concept2) +// {} +// +// Note: This macro cannot be used when the last function argument is a +// parameter pack. +#define CPP_fun(X) CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN X CPP_FUN_IMPL_1_ +#endif + +//////////////////////////////////////////////////////////////////////////////// +// CPP_auto_fun +// Usage: +// template +// auto CPP_auto_fun(foo)(A a, B b)([const]opt [noexcept(cond)]opt)opt +// ( +// return a + b +// ) +#define CPP_auto_fun(X) X CPP_AUTO_FUN_IMPL_ + +/// INTERNAL ONLY +#define CPP_AUTO_FUN_IMPL_(...) (__VA_ARGS__) CPP_AUTO_FUN_RETURNS_ + +/// INTERNAL ONLY +#define CPP_AUTO_FUN_RETURNS_(...) \ + CPP_PP_EVAL2_( \ + CPP_AUTO_FUN_SELECT_RETURNS_, \ + (__VA_ARGS__,) \ + )(__VA_ARGS__) + +/// INTERNAL ONLY +#define CPP_AUTO_FUN_SELECT_RETURNS_(MAYBE_CONST, ...) \ + CPP_PP_CAT(CPP_AUTO_FUN_RETURNS_CONST_, \ + CPP_PP_EVAL(CPP_PP_CHECK, CPP_PP_CAT( \ + CPP_PP_PROBE_CONST_MUTABLE_PROBE_, MAYBE_CONST))) + +/// INTERNAL ONLY +#define CPP_PP_PROBE_CONST_MUTABLE_PROBE_const CPP_PP_PROBE_N(~, 1) + +/// INTERNAL ONLY +#define CPP_PP_PROBE_CONST_MUTABLE_PROBE_mutable CPP_PP_PROBE_N(~, 2) + +/// INTERNAL ONLY +#define CPP_PP_EAT_MUTABLE_mutable + +/// INTERNAL ONLY +#define CPP_AUTO_FUN_RETURNS_CONST_2(...) \ + CPP_PP_CAT(CPP_PP_EAT_MUTABLE_, __VA_ARGS__) CPP_AUTO_FUN_RETURNS_CONST_0 + +/// INTERNAL ONLY +#define CPP_AUTO_FUN_RETURNS_CONST_1(...) \ + __VA_ARGS__ CPP_AUTO_FUN_RETURNS_CONST_0 + +/// INTERNAL ONLY +#define CPP_AUTO_FUN_RETURNS_CONST_0(...) \ + CPP_PP_EVAL(CPP_AUTO_FUN_DECLTYPE_NOEXCEPT_, \ + CPP_PP_CAT(CPP_AUTO_FUN_RETURNS_, __VA_ARGS__)) + +/// INTERNAL ONLY +#define CPP_AUTO_FUN_RETURNS_return + +#ifdef __cpp_guaranteed_copy_elision +/// INTERNAL ONLY +#define CPP_AUTO_FUN_DECLTYPE_NOEXCEPT_(...) \ + noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) \ + { return (__VA_ARGS__); } + +#else +/// INTERNAL ONLY +#define CPP_AUTO_FUN_DECLTYPE_NOEXCEPT_(...) \ + noexcept(noexcept(decltype(__VA_ARGS__)(__VA_ARGS__))) -> \ + decltype(__VA_ARGS__) \ + { return (__VA_ARGS__); } + +#endif + +#if defined(CPP_DOXYGEN_INVOKED) +#define concept(NAME) concept NAME CPP_CONCEPT_EQUALS_ +#define CPP_CONCEPT_EQUALS_(...) = +#endif + +namespace concepts +{ + template + using bool_ = std::integral_constant; + +#if defined(__cpp_fold_expressions) && __cpp_fold_expressions >= 201603 + template + CPP_INLINE_VAR constexpr bool and_v = (Bs &&...); + + template + CPP_INLINE_VAR constexpr bool or_v = (Bs ||...); +#else + namespace detail + { + template + struct bools; + } // namespace detail + + template + CPP_INLINE_VAR constexpr bool and_v = + META_IS_SAME(detail::bools, detail::bools); + + template + CPP_INLINE_VAR constexpr bool or_v = + !META_IS_SAME(detail::bools, detail::bools); +#endif + + template + struct return_t_ + { + template + using invoke = T; + }; + + template + using return_t = meta::invoke, T>; + + /// \cond + namespace detail + { + struct ignore + { + template + constexpr ignore(Args&&...) noexcept {} + }; + + template + constexpr bool true_() + { + return true; + } + + template + struct tag; + + template + CPP_INLINE_VAR constexpr T instance_ = T{}; + + template + constexpr bool requires_() + { + return true; + } + + struct Nil + {}; + +#ifdef CPP_WORKAROUND_MSVC_779763 + enum class xNil {}; + + struct CPP_true_t + { + constexpr bool operator()(Nil) const noexcept + { + return true; + } + constexpr bool operator()(xNil) const noexcept + { + return true; + } + }; + + CPP_INLINE_VAR constexpr CPP_true_t CPP_true_fn_ {}; + + constexpr bool CPP_true_fn(xNil) + { + return true; + } +#else + using xNil = Nil; +#endif + + constexpr bool CPP_true_fn(Nil) + { + return true; + } + } // namespace detail + /// \endcond + +#if defined(__clang__) || defined(_MSC_VER) + template + std::enable_if_t requires_() + {} +#else + template + CPP_INLINE_VAR constexpr std::enable_if_t requires_ = 0; +#endif + + inline namespace defs + { + //////////////////////////////////////////////////////////////////////// + // Utility concepts + //////////////////////////////////////////////////////////////////////// + + /// \concept is_true + /// \brief The \c is_true concept + template + CPP_concept is_true = B; + + /// \concept type + /// \brief The \c type concept + template + CPP_concept type = true; + + /// \concept satisfies + /// \brief The \c satisfies concept + template class Trait, typename... Args> + CPP_concept satisfies = + static_cast(Trait::type::value); + + //////////////////////////////////////////////////////////////////////// + // Core language concepts + //////////////////////////////////////////////////////////////////////// + + /// \concept same_as + /// \brief The \c same_as concept + template + CPP_concept same_as = + META_IS_SAME(A, B) && META_IS_SAME(B, A); + + /// \cond + /// \concept not_same_as_ + /// \brief The \c not_same_as_ concept + template + CPP_concept not_same_as_ = + (!same_as, remove_cvref_t>); + /// \endcond + + // Workaround bug in the Standard Library: + // From cannot be an incomplete class type despite that + // is_convertible should be equivalent to is_convertible + // in such a case. + /// \concept implicitly_convertible_to + /// \brief The \c implicitly_convertible_to concept + template + CPP_concept implicitly_convertible_to = + std::is_convertible, To>::value; + + /// \concept explicitly_convertible_to_ + /// \brief The \c explicitly_convertible_to_ concept + template + CPP_requires(explicitly_convertible_to_, + requires(From(*from)()) // + ( + static_cast(from()) + )); + /// \concept explicitly_convertible_to + /// \brief The \c explicitly_convertible_to concept + template + CPP_concept explicitly_convertible_to = + CPP_requires_ref(concepts::explicitly_convertible_to_, From, To); + + /// \concept convertible_to + /// \brief The \c convertible_to concept + template + CPP_concept convertible_to = + implicitly_convertible_to && + explicitly_convertible_to; + + /// \concept derived_from_ + /// \brief The \c derived_from_ concept + CPP_template(typename T, typename U)( + concept (derived_from_)(T, U), + convertible_to + ); + /// \concept derived_from + /// \brief The \c derived_from concept + template + CPP_concept derived_from = + META_IS_BASE_OF(U, T) && + CPP_concept_ref(concepts::derived_from_, T, U); + + /// \concept common_reference_with_ + /// \brief The \c common_reference_with_ concept + CPP_template(typename T, typename U)( + concept (common_reference_with_)(T, U), + same_as, common_reference_t> CPP_and + convertible_to> CPP_and + convertible_to> + ); + /// \concept common_reference_with + /// \brief The \c common_reference_with concept + template + CPP_concept common_reference_with = + CPP_concept_ref(concepts::common_reference_with_, T, U); + + /// \concept common_with_ + /// \brief The \c common_with_ concept + CPP_template(typename T, typename U)( + concept (common_with_)(T, U), + same_as, common_type_t> CPP_and + convertible_to> CPP_and + convertible_to> CPP_and + common_reference_with< + std::add_lvalue_reference_t, + std::add_lvalue_reference_t> CPP_and + common_reference_with< + std::add_lvalue_reference_t>, + common_reference_t< + std::add_lvalue_reference_t, + std::add_lvalue_reference_t>> + ); + /// \concept common_with + /// \brief The \c common_with concept + template + CPP_concept common_with = + CPP_concept_ref(concepts::common_with_, T, U); + + /// \concept integral + /// \brief The \c integral concept + template + CPP_concept integral = + std::is_integral::value; + + /// \concept signed_integral + /// \brief The \c signed_integral concept + template + CPP_concept signed_integral = + integral && + std::is_signed::value; + + /// \concept unsigned_integral + /// \brief The \c unsigned_integral concept + template + CPP_concept unsigned_integral = + integral && + !signed_integral; + + /// \concept assignable_from_ + /// \brief The \c assignable_from_ concept + template + CPP_requires(assignable_from_, + requires(T t, U && u) // + ( + t = (U &&) u, + requires_> + )); + /// \concept assignable_from + /// \brief The \c assignable_from concept + template + CPP_concept assignable_from = + std::is_lvalue_reference::value && + common_reference_with, detail::as_cref_t> && + CPP_requires_ref(defs::assignable_from_, T, U); + + /// \concept swappable_ + /// \brief The \c swappable_ concept + template + CPP_requires(swappable_, + requires(T & t, T & u) // + ( + concepts::swap(t, u) + )); + /// \concept swappable + /// \brief The \c swappable concept + template + CPP_concept swappable = + CPP_requires_ref(defs::swappable_, T); + + /// \concept swappable_with_ + /// \brief The \c swappable_with_ concept + template + CPP_requires(swappable_with_, + requires(T && t, U && u) // + ( + concepts::swap((T &&) t, (T &&) t), + concepts::swap((U &&) u, (U &&) u), + concepts::swap((U &&) u, (T &&) t), + concepts::swap((T &&) t, (U &&) u) + )); + /// \concept swappable_with + /// \brief The \c swappable_with concept + template + CPP_concept swappable_with = + common_reference_with, detail::as_cref_t> && + CPP_requires_ref(defs::swappable_with_, T, U); + + } // inline namespace defs + + namespace detail + { + /// \concept boolean_testable_impl_ + /// \brief The \c boolean_testable_impl_ concept + template + CPP_concept boolean_testable_impl_ = convertible_to; + + /// \concept boolean_testable_frag_ + /// \brief The \c boolean_testable_frag_ concept + template + CPP_requires(boolean_testable_frag_, + requires(T && t) // + ( + !(T&&) t, + concepts::requires_> + )); + + /// \concept boolean_testable_ + /// \brief The \c boolean_testable_ concept + template + CPP_concept boolean_testable_ = + CPP_requires_ref(boolean_testable_frag_, T) && + boolean_testable_impl_; + + CPP_DIAGNOSTIC_PUSH + CPP_DIAGNOSTIC_IGNORE_FLOAT_EQUAL + + /// \concept weakly_equality_comparable_with_frag_ + /// \brief The \c weakly_equality_comparable_with_frag_ concept + template + CPP_requires(weakly_equality_comparable_with_frag_, + requires(detail::as_cref_t t, detail::as_cref_t u) // + ( + concepts::requires_>, + concepts::requires_>, + concepts::requires_>, + concepts::requires_> + )); + /// \concept weakly_equality_comparable_with_ + /// \brief The \c weakly_equality_comparable_with_ concept + template + CPP_concept weakly_equality_comparable_with_ = + CPP_requires_ref(weakly_equality_comparable_with_frag_, T, U); + + /// \concept partially_ordered_with_frag_ + /// \brief The \c partially_ordered_with_frag_ concept + template + CPP_requires(partially_ordered_with_frag_, + requires(detail::as_cref_t& t, detail::as_cref_t& u) // + ( + concepts::requires_>, + concepts::requires_ u)>>, + concepts::requires_>, + concepts::requires_= u)>>, + concepts::requires_>, + concepts::requires_ t)>>, + concepts::requires_>, + concepts::requires_= t)>> + )); + /// \concept partially_ordered_with_ + /// \brief The \c partially_ordered_with_ concept + template + CPP_concept partially_ordered_with_ = + CPP_requires_ref(partially_ordered_with_frag_, T, U); + + CPP_DIAGNOSTIC_POP + } // namespace detail + + inline namespace defs + { + //////////////////////////////////////////////////////////////////////// + // Comparison concepts + //////////////////////////////////////////////////////////////////////// + + /// \concept equality_comparable + /// \brief The \c equality_comparable concept + template + CPP_concept equality_comparable = + detail::weakly_equality_comparable_with_; + + /// \concept equality_comparable_with_ + /// \brief The \c equality_comparable_with_ concept + CPP_template(typename T, typename U)( + concept (equality_comparable_with_)(T, U), + equality_comparable< + common_reference_t, detail::as_cref_t>> + ); + /// \concept equality_comparable_with + /// \brief The \c equality_comparable_with concept + template + CPP_concept equality_comparable_with = + equality_comparable && + equality_comparable && + detail::weakly_equality_comparable_with_ && + common_reference_with, detail::as_cref_t> && + CPP_concept_ref(concepts::equality_comparable_with_, T, U); + + /// \concept totally_ordered + /// \brief The \c totally_ordered concept + template + CPP_concept totally_ordered = + equality_comparable && + detail::partially_ordered_with_; + + /// \concept totally_ordered_with_ + /// \brief The \c totally_ordered_with_ concept + CPP_template(typename T, typename U)( + concept (totally_ordered_with_)(T, U), + totally_ordered< + common_reference_t< + detail::as_cref_t, + detail::as_cref_t>> CPP_and + detail::partially_ordered_with_); + + /// \concept totally_ordered_with + /// \brief The \c totally_ordered_with concept + template + CPP_concept totally_ordered_with = + totally_ordered && + totally_ordered && + equality_comparable_with && + CPP_concept_ref(concepts::totally_ordered_with_, T, U); + + //////////////////////////////////////////////////////////////////////// + // Object concepts + //////////////////////////////////////////////////////////////////////// + + /// \concept destructible + /// \brief The \c destructible concept + template + CPP_concept destructible = + std::is_nothrow_destructible::value; + + /// \concept constructible_from + /// \brief The \c constructible_from concept + template + CPP_concept constructible_from = + destructible && + META_IS_CONSTRUCTIBLE(T, Args...); + + /// \concept default_constructible + /// \brief The \c default_constructible concept + template + CPP_concept default_constructible = + constructible_from; + + /// \concept move_constructible + /// \brief The \c move_constructible concept + template + CPP_concept move_constructible = + constructible_from && + convertible_to; + + /// \concept copy_constructible_ + /// \brief The \c copy_constructible_ concept + CPP_template(typename T)( + concept (copy_constructible_)(T), + constructible_from && + constructible_from && + constructible_from && + convertible_to && + convertible_to && + convertible_to); + /// \concept copy_constructible + /// \brief The \c copy_constructible concept + template + CPP_concept copy_constructible = + move_constructible && + CPP_concept_ref(concepts::copy_constructible_, T); + + /// \concept move_assignable_ + /// \brief The \c move_assignable_ concept + CPP_template(typename T)( + concept (move_assignable_)(T), + assignable_from + ); + /// \concept movable + /// \brief The \c movable concept + template + CPP_concept movable = + std::is_object::value && + move_constructible && + CPP_concept_ref(concepts::move_assignable_, T) && + swappable; + + /// \concept copy_assignable_ + /// \brief The \c copy_assignable_ concept + CPP_template(typename T)( + concept (copy_assignable_)(T), + assignable_from + ); + /// \concept copyable + /// \brief The \c copyable concept + template + CPP_concept copyable = + copy_constructible && + movable && + CPP_concept_ref(concepts::copy_assignable_, T); + + /// \concept semiregular + /// \brief The \c semiregular concept + template + CPP_concept semiregular = + copyable && + default_constructible; + // Axiom: copies are independent. See Fundamentals of Generic + // Programming http://www.stepanovpapers.com/DeSt98.pdf + + /// \concept regular + /// \brief The \c regular concept + template + CPP_concept regular = + semiregular && + equality_comparable; + + } // inline namespace defs +} // namespace concepts + +#endif // RANGES_V3_UTILITY_CONCEPTS_HPP diff --git a/thirdparty/range-v3/include/concepts/swap.hpp b/thirdparty/range-v3/include/concepts/swap.hpp new file mode 100644 index 0000000000..dd7086411d --- /dev/null +++ b/thirdparty/range-v3/include/concepts/swap.hpp @@ -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 +#include +#include +#include + +// 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::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::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 + CPP_INLINE_VAR constexpr bool is_movable_v = + std::is_object::value && + std::is_move_constructible::value && + std::is_move_assignable::value; + + template + struct static_const + { + static constexpr T const value {}; + }; + template + constexpr T const static_const::value; + } + /// \endcond + + template + struct is_swappable; + + template + struct is_nothrow_swappable; + + template + struct is_swappable_with; + + template + struct is_nothrow_swappable_with; + + template + CPP_CXX14_CONSTEXPR + meta::if_c< + std::is_move_constructible::value && + std::is_assignable::value, T> + exchange(T &t, U &&u) + noexcept( + std::is_nothrow_move_constructible::value && + std::is_nothrow_assignable::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 + nope swap(T &, T &) = delete; + + template + nope swap(T (&)[N], T (&)[N]) = delete; + +#ifdef CPP_WORKAROUND_MSVC_895622 + nope swap(); +#endif + + template + decltype(swap(std::declval(), std::declval())) try_adl_swap_(int); + + template + nope try_adl_swap_(long); + + template + CPP_INLINE_VAR constexpr bool is_adl_swappable_v = + !META_IS_SAME(decltype(adl_swap_detail::try_adl_swap_(42)), nope); + + struct swap_fn + { + // Dispatch to user-defined swap found via ADL: + template + CPP_CXX14_CONSTEXPR + meta::if_c> + 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 + CPP_CXX14_CONSTEXPR + meta::if_c< + !is_adl_swappable_v && + detail::is_movable_v> + 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 + CPP_CXX14_CONSTEXPR + meta::if_c< + !is_adl_swappable_v && + is_swappable_with::value> + operator()(T (&t)[N], U (&u)[N]) const + noexcept(is_nothrow_swappable_with::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 + CPP_CXX14_CONSTEXPR + meta::if_c::value && is_swappable_with::value> + operator()(std::pair &&left, std::pair &&right) const + noexcept( + is_nothrow_swappable_with::value && + is_nothrow_swappable_with::value) + { + swap_fn()(static_cast &&>(left).first, + static_cast &&>(right).first); + swap_fn()(static_cast &&>(left).second, + static_cast &&>(right).second); + } + + template + CPP_CXX14_CONSTEXPR + meta::if_c::value...>::value> + operator()(std::tuple &&left, std::tuple &&right) const + noexcept(meta::and_c::value...>::value) + { + swap_fn::impl( + static_cast &&>(left), + static_cast &&>(right), + meta::make_index_sequence{}); + } + + private: + template + static constexpr int ignore_unused(Ts &&...) + { + return 0; + } + template + CPP_CXX14_CONSTEXPR + static void impl(T &&left, U &&right, meta::index_sequence) + { + (void) swap_fn::ignore_unused( + (swap_fn()(std::get(static_cast(left)), + std::get(static_cast(right))), 42)...); + } + }; + + template + struct is_swappable_with_ + : std::false_type + {}; + + template + struct is_swappable_with_(), std::declval())), + decltype(swap_fn()(std::declval(), std::declval()))>> + : std::true_type + {}; + + template + struct is_nothrow_swappable_with_ + : meta::bool_(), std::declval())) && + noexcept(swap_fn()(std::declval(), std::declval()))> + {}; + + // 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. How do I make it model indirectly_swappable? + // A: With an overload of iter_swap. + } + /// \endcond + + /// \ingroup group-utility + template + struct is_swappable_with + : adl_swap_detail::is_swappable_with_ + {}; + + /// \ingroup group-utility + template + struct is_nothrow_swappable_with + : meta::and_< + is_swappable_with, + adl_swap_detail::is_nothrow_swappable_with_> + {}; + + /// \ingroup group-utility + template + struct is_swappable + : is_swappable_with + {}; + + /// \ingroup group-utility + template + struct is_nothrow_swappable + : is_nothrow_swappable_with + {}; + + /// \ingroup group-utility + /// \relates adl_swap_detail::swap_fn + CPP_DEFINE_CPO(adl_swap_detail::swap_fn, swap) +} + +#endif diff --git a/thirdparty/range-v3/include/concepts/type_traits.hpp b/thirdparty/range-v3/include/concepts/type_traits.hpp new file mode 100644 index 0000000000..f8ee95c9c9 --- /dev/null +++ b/thirdparty/range-v3/include/concepts/type_traits.hpp @@ -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 +#include +#include +#include + +namespace concepts +{ + template + using remove_cvref_t = + typename std::remove_cv< + typename std::remove_reference::type>::type; + + /// \cond + namespace detail + { + template + using is_convertible = std::is_convertible>, To>; + + template + struct if_else_ + { + template + using invoke = U; + }; + template<> + struct if_else_ + { + template + using invoke = T; + }; + template + using if_else_t = meta::invoke, T, U>; + + template + struct if_ + {}; + template<> + struct if_ + { + template + using invoke = T; + }; + template + using if_t = meta::invoke, T>; + + template + struct _copy_cv_ + { + using type = To; + }; + template + struct _copy_cv_ + { + using type = To const; + }; + template + struct _copy_cv_ + { + using type = To volatile; + }; + template + struct _copy_cv_ + { + using type = To const volatile; + }; + template + using _copy_cv = meta::_t<_copy_cv_>; + + //////////////////////////////////////////////////////////////////////////////////////// + template + struct _builtin_common; + + template + using _builtin_common_t = meta::_t<_builtin_common>; + + template + using _cond_res = decltype(true ? std::declval() : std::declval()); + + template> + using _rref_res = + if_else_t::value, meta::_t> &&, R>; + + template + using _lref_res = _cond_res<_copy_cv &, _copy_cv &>; + + template + struct as_cref_ + { + using type = T const &; + }; + template + struct as_cref_ + { + using type = T const &; + }; + template + struct as_cref_ + { + using type = T const &; + }; + template<> + struct as_cref_ + { + using type = void; + }; + template<> + struct as_cref_ + { + using type = void const; + }; + + template + using as_cref_t = typename as_cref_::type; + + template + using decay_t = typename std::decay::type; + + #if !defined(__GNUC__) || defined(__clang__) + template + struct _builtin_common_3 + {}; + template + struct _builtin_common_3, as_cref_t>>> + : std::decay<_cond_res, as_cref_t>> + {}; + template + struct _builtin_common_2 + : _builtin_common_3 + {}; + template + struct _builtin_common_2>> + : std::decay<_cond_res> + {}; + template + struct _builtin_common + : _builtin_common_2 + {}; + template + struct _builtin_common>::value && + is_convertible>::value>> + { + using type = _rref_res; + }; + template + struct _builtin_common + : meta::defer<_lref_res, T, U> + {}; + template + struct _builtin_common>::value>> + : _builtin_common + {}; + template + struct _builtin_common + : _builtin_common + {}; + #else + template + struct _builtin_common_3 + {}; + template + struct _builtin_common_3, as_cref_t>>> + : std::decay<_cond_res, as_cref_t>> + {}; + template + struct _builtin_common_2 + : _builtin_common_3 + {}; + template + struct _builtin_common_2>> + : std::decay<_cond_res> + {}; + template + struct _builtin_common + : _builtin_common_2 + {}; + template + struct _builtin_common_rr + : _builtin_common_2 + {}; + template + struct _builtin_common_rr>::value && + is_convertible>::value>> + { + using type = _rref_res; + }; + template + struct _builtin_common + : _builtin_common_rr + {}; + template + struct _builtin_common + : meta::defer<_lref_res, T, U> + {}; + template + struct _builtin_common_lr + : _builtin_common_2 + {}; + template + struct _builtin_common_lr>::value>> + : _builtin_common + {}; + template + struct _builtin_common + : _builtin_common_lr + {}; + template + struct _builtin_common + : _builtin_common + {}; + #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 + struct common_type + {}; + + template + struct common_type + : std::decay + {}; + + template + struct common_type + : detail::if_else_t< + (META_IS_SAME(detail::decay_t, T) && + META_IS_SAME(detail::decay_t, U) ), + meta::defer, + common_type, detail::decay_t>> + {}; + + template + using common_type_t = typename common_type::type; + + template + struct common_type + : meta::lazy::fold, T, meta::quote> + {}; + + /// @} + + /// \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 class TQual, + template class UQual> + struct basic_common_reference + {}; + + /// \cond + namespace detail + { + using _rref = + meta::quote_trait; + using _lref = + meta::quote_trait; + + template + struct _xref + { + template + using invoke = T; + }; + template + struct _xref + { + template + using invoke = + meta::_t, U>>>; + }; + template + struct _xref + { + template + using invoke = + meta::_t, U>>>; + }; + template + struct _xref + { + template + using invoke = U const; + }; + template + struct _xref + { + template + using invoke = U volatile; + }; + template + struct _xref + { + template + using invoke = U const volatile; + }; + + template + using _basic_common_reference = + basic_common_reference< + remove_cvref_t, + remove_cvref_t, + _xref::template invoke, + _xref::template invoke>; + + template + struct _common_reference2 + : if_else_t< + meta::is_trait<_basic_common_reference>::value, + _basic_common_reference, + common_type> + {}; + + template + struct _common_reference2>::value>> + : _builtin_common + {}; + } + /// \endcond + + /// Users can specialize this to hook the \c common_reference_with concept. + /// \sa `basic_common_reference` + template + struct common_reference + {}; + + template + struct common_reference + { + using type = T; + }; + + template + struct common_reference + : detail::_common_reference2 + {}; + + template + using common_reference_t = typename common_reference::type; + + template + struct common_reference + : meta::lazy::fold, T, meta::quote> + {}; + /// @} +} // namespace concepts + +#endif diff --git a/thirdparty/range-v3/include/meta/meta.hpp b/thirdparty/range-v3/include/meta/meta.hpp new file mode 100644 index 0000000000..1372703e78 --- /dev/null +++ b/thirdparty/range-v3/include/meta/meta.hpp @@ -0,0 +1,3973 @@ +/// \file meta.hpp Tiny meta-programming library. +// +// 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_HPP +#define META_HPP + +#include +#include +#include +#include +#include + +#ifdef __clang__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunknown-pragmas" +#pragma GCC diagnostic ignored "-Wpragmas" +#pragma GCC diagnostic ignored "-Wdocumentation-deprecated-sync" +#pragma GCC diagnostic ignored "-Wmissing-variable-declarations" +#endif + +/// \defgroup meta Meta +/// +/// A tiny metaprogramming library + +/// \defgroup trait Trait +/// Trait invocation/composition. +/// \ingroup meta + +/// \defgroup invocation Invocation +/// Trait invocation +/// \ingroup trait + +/// \defgroup composition Composition +/// Trait composition +/// \ingroup trait + +/// \defgroup logical Logical +/// Logical operations +/// \ingroup meta + +/// \defgroup algorithm Algorithms +/// Algorithms. +/// \ingroup meta + +/// \defgroup query Query/Search +/// Query and search algorithms +/// \ingroup algorithm + +/// \defgroup transformation Transformation +/// Transformation algorithms +/// \ingroup algorithm + +/// \defgroup runtime Runtime +/// Runtime algorithms +/// \ingroup algorithm + +/// \defgroup datatype Datatype +/// Datatypes. +/// \ingroup meta + +/// \defgroup list list_like +/// \ingroup datatype + +/// \defgroup integral Integer sequence +/// Equivalent to C++14's `std::integer_sequence` +/// \ingroup datatype + +/// \defgroup extension Extension +/// Extend meta with your own datatypes. +/// \ingroup datatype + +/// \defgroup math Math +/// Integral constant arithmetic. +/// \ingroup meta + +/// \defgroup lazy_trait lazy +/// \ingroup trait + +/// \defgroup lazy_invocation lazy +/// \ingroup invocation + +/// \defgroup lazy_composition lazy +/// \ingroup composition + +/// \defgroup lazy_logical lazy +/// \ingroup logical + +/// \defgroup lazy_query lazy +/// \ingroup query + +/// \defgroup lazy_transformation lazy +/// \ingroup transformation + +/// \defgroup lazy_list lazy +/// \ingroup list + +/// \defgroup lazy_datatype lazy +/// \ingroup datatype + +/// \defgroup lazy_math lazy +/// \ingroup math + +/// Tiny metaprogramming library +namespace meta +{ + namespace detail + { + /// Returns a \p T nullptr + template + constexpr T *_nullptr_v() + { + return nullptr; + } + +#if META_CXX_VARIABLE_TEMPLATES + template + META_INLINE_VAR constexpr T *nullptr_v = nullptr; +#endif + } // namespace detail + + /// An empty type. + /// \ingroup datatype + struct nil_ + { + }; + + /// Type alias for \p T::type. + /// \ingroup invocation + template + using _t = typename T::type; + +#if META_CXX_VARIABLE_TEMPLATES || defined(META_DOXYGEN_INVOKED) + /// Variable alias for \c T::type::value + /// \note Requires C++14 or greater. + /// \ingroup invocation + template + constexpr typename T::type::value_type _v = T::type::value; +#endif + + /// Lazy versions of meta actions + namespace lazy + { + /// \sa `meta::_t` + /// \ingroup lazy_invocation + template + using _t = defer<_t, T>; + } // namespace lazy + + /// An integral constant wrapper for \c std::size_t. + /// \ingroup integral + template + using size_t = std::integral_constant; + + /// An integral constant wrapper for \c bool. + /// \ingroup integral + template + using bool_ = std::integral_constant; + + /// An integral constant wrapper for \c int. + /// \ingroup integral + template + using int_ = std::integral_constant; + + /// An integral constant wrapper for \c char. + /// \ingroup integral + template + using char_ = std::integral_constant; + + /////////////////////////////////////////////////////////////////////////////////////////// + // Math operations + /// An integral constant wrapper around the result of incrementing the wrapped integer \c + /// T::type::value. + template + using inc = std::integral_constant; + + /// An integral constant wrapper around the result of decrementing the wrapped integer \c + /// T::type::value. + template + using dec = std::integral_constant; + + /// An integral constant wrapper around the result of adding the two wrapped integers + /// \c T::type::value and \c U::type::value. + /// \ingroup math + template + using plus = std::integral_constant; + + /// An integral constant wrapper around the result of subtracting the two wrapped integers + /// \c T::type::value and \c U::type::value. + /// \ingroup math + template + using minus = std::integral_constant; + + /// An integral constant wrapper around the result of multiplying the two wrapped integers + /// \c T::type::value and \c U::type::value. + /// \ingroup math + template + using multiplies = std::integral_constant; + + /// An integral constant wrapper around the result of dividing the two wrapped integers \c + /// T::type::value and \c U::type::value. + /// \ingroup math + template + using divides = std::integral_constant; + + /// An integral constant wrapper around the result of negating the wrapped integer + /// \c T::type::value. + /// \ingroup math + template + using negate = std::integral_constant; + + /// An integral constant wrapper around the remainder of dividing the two wrapped integers + /// \c T::type::value and \c U::type::value. + /// \ingroup math + template + using modulus = std::integral_constant; + + /// A Boolean integral constant wrapper around the result of comparing \c T::type::value and + /// \c U::type::value for equality. + /// \ingroup math + template + using equal_to = bool_; + + /// A Boolean integral constant wrapper around the result of comparing \c T::type::value and + /// \c U::type::value for inequality. + /// \ingroup math + template + using not_equal_to = bool_; + + /// A Boolean integral constant wrapper around \c true if \c T::type::value is greater than + /// \c U::type::value; \c false, otherwise. + /// \ingroup math + template + using greater = bool_<(T::type::value > U::type::value)>; + + /// A Boolean integral constant wrapper around \c true if \c T::type::value is less than \c + /// U::type::value; \c false, otherwise. + /// \ingroup math + template + using less = bool_<(T::type::value < U::type::value)>; + + /// A Boolean integral constant wrapper around \c true if \c T::type::value is greater than + /// or equal to \c U::type::value; \c false, otherwise. + /// \ingroup math + template + using greater_equal = bool_<(T::type::value >= U::type::value)>; + + /// A Boolean integral constant wrapper around \c true if \c T::type::value is less than or + /// equal to \c U::type::value; \c false, otherwise. + /// \ingroup math + template + using less_equal = bool_<(T::type::value <= U::type::value)>; + + /// An integral constant wrapper around the result of bitwise-and'ing the two wrapped + /// integers \c T::type::value and \c U::type::value. + /// \ingroup math + template + using bit_and = std::integral_constant; + + /// An integral constant wrapper around the result of bitwise-or'ing the two wrapped + /// integers \c T::type::value and \c U::type::value. + /// \ingroup math + template + using bit_or = std::integral_constant; + + /// An integral constant wrapper around the result of bitwise-exclusive-or'ing the two + /// wrapped integers \c T::type::value and \c U::type::value. + /// \ingroup math + template + using bit_xor = std::integral_constant; + + /// An integral constant wrapper around the result of bitwise-complementing the wrapped + /// integer \c T::type::value. + /// \ingroup math + template + using bit_not = std::integral_constant; + + namespace lazy + { + /// \sa 'meta::int' + /// \ingroup lazy_math + template + using inc = defer; + + /// \sa 'meta::dec' + /// \ingroup lazy_math + template + using dec = defer; + + /// \sa 'meta::plus' + /// \ingroup lazy_math + template + using plus = defer; + + /// \sa 'meta::minus' + /// \ingroup lazy_math + template + using minus = defer; + + /// \sa 'meta::multiplies' + /// \ingroup lazy_math + template + using multiplies = defer; + + /// \sa 'meta::divides' + /// \ingroup lazy_math + template + using divides = defer; + + /// \sa 'meta::negate' + /// \ingroup lazy_math + template + using negate = defer; + + /// \sa 'meta::modulus' + /// \ingroup lazy_math + template + using modulus = defer; + + /// \sa 'meta::equal_to' + /// \ingroup lazy_math + template + using equal_to = defer; + + /// \sa 'meta::not_equal_t' + /// \ingroup lazy_math + template + using not_equal_to = defer; + + /// \sa 'meta::greater' + /// \ingroup lazy_math + template + using greater = defer; + + /// \sa 'meta::less' + /// \ingroup lazy_math + template + using less = defer; + + /// \sa 'meta::greater_equal' + /// \ingroup lazy_math + template + using greater_equal = defer; + + /// \sa 'meta::less_equal' + /// \ingroup lazy_math + template + using less_equal = defer; + + /// \sa 'meta::bit_and' + /// \ingroup lazy_math + template + using bit_and = defer; + + /// \sa 'meta::bit_or' + /// \ingroup lazy_math + template + using bit_or = defer; + + /// \sa 'meta::bit_xor' + /// \ingroup lazy_math + template + using bit_xor = defer; + + /// \sa 'meta::bit_not' + /// \ingroup lazy_math + template + using bit_not = defer; + } // namespace lazy + + /// \cond + namespace detail + { + enum class indices_strategy_ + { + done, + repeat, + recurse + }; + + constexpr indices_strategy_ strategy_(std::size_t cur, std::size_t end) + { + return cur >= end ? indices_strategy_::done + : cur * 2 <= end ? indices_strategy_::repeat + : indices_strategy_::recurse; + } + + template + constexpr std::size_t range_distance_(T begin, T end) + { + return begin <= end ? static_cast(end - begin) + : throw "The start of the integer_sequence must not be " + "greater than the end"; + } + + template + struct make_indices_ + { + using type = State; + }; + + template + struct coerce_indices_ + { + }; + } // namespace detail + /// \endcond + + /////////////////////////////////////////////////////////////////////////////////////////// + // integer_sequence +#if !META_CXX_INTEGER_SEQUENCE + /// A container for a sequence of compile-time integer constants. + /// \ingroup integral + template + struct integer_sequence + { + using value_type = T; + /// \return `sizeof...(Is)` + static constexpr std::size_t size() noexcept { return sizeof...(Is); } + }; +#endif + + /////////////////////////////////////////////////////////////////////////////////////////// + // index_sequence + /// A container for a sequence of compile-time integer constants of type + /// \c std::size_t + /// \ingroup integral + template + using index_sequence = integer_sequence; + +#if META_HAS_MAKE_INTEGER_SEQ && !defined(META_DOXYGEN_INVOKED) + // Implement make_integer_sequence and make_index_sequence with the + // __make_integer_seq builtin on compilers that provide it. (Redirect + // through decltype to workaround suspected clang bug.) + /// \cond + namespace detail + { + template + __make_integer_seq make_integer_sequence_(); + } + /// \endcond + + template + using make_integer_sequence = decltype(detail::make_integer_sequence_()); + + template + using make_index_sequence = make_integer_sequence; +#else + /// Generate \c index_sequence containing integer constants [0,1,2,...,N-1]. + /// \par Complexity + /// `O(log(N))`. + /// \ingroup integral + template + using make_index_sequence = + _t, detail::strategy_(1, N)>>; + + /// Generate \c integer_sequence containing integer constants [0,1,2,...,N-1]. + /// \par Complexity + /// `O(log(N))`. + /// \ingroup integral + template + using make_integer_sequence = + _t(N)>>>; +#endif + + /////////////////////////////////////////////////////////////////////////////////////////// + // integer_range + /// Makes the integer sequence `[From, To)`. + /// \par Complexity + /// `O(log(To - From))`. + /// \ingroup integral + template + using integer_range = + _t>>; + + /// \cond + namespace detail + { + template + struct concat_indices_ + { + }; + + template + struct concat_indices_, index_sequence> + { + using type = index_sequence; + }; + + template <> + struct make_indices_<0u, index_sequence<0>, indices_strategy_::done> + { + using type = index_sequence<>; + }; + + template + struct make_indices_, indices_strategy_::repeat> + : make_indices_, + detail::strategy_(sizeof...(Values) * 2, End)> + { + }; + + template + struct make_indices_, indices_strategy_::recurse> + : concat_indices_, + make_index_sequence> + { + }; + + template + struct coerce_indices_> + { + using type = + integer_sequence(static_cast(Values) + Offset)...>; + }; + } // namespace detail + /// \endcond + + /// Evaluate the invocable \p Fn with the arguments \p Args. + /// \ingroup invocation + template + using invoke = typename Fn::template invoke; + + /// Lazy versions of meta actions + namespace lazy + { + /// \sa `meta::invoke` + /// \ingroup lazy_invocation + template + using invoke = defer; + } // namespace lazy + + /// A trait that always returns its argument \p T. It is also an invocable + /// that always returns \p T. + /// \ingroup trait + /// \ingroup invocation + template + struct id + { +#if defined(META_WORKAROUND_CWG_1558) && !defined(META_DOXYGEN_INVOKED) + // Redirect through decltype for compilers that have not + // yet implemented CWG 1558: + static id impl(void *); + + template + using invoke = _t *>(nullptr)))>; +#else + template + using invoke = T; +#endif + + using type = T; + }; + + /// An alias for type \p T. Useful in non-deduced contexts. + /// \ingroup trait + template + using id_t = _t>; + + namespace lazy + { + /// \sa `meta::id` + /// \ingroup lazy_trait + /// \ingroup lazy_invocation + template + using id = defer; + } // namespace lazy + + /// An alias for `void`. + /// \ingroup trait +#if defined(META_WORKAROUND_CWG_1558) && !defined(META_DOXYGEN_INVOKED) + // Redirect through decltype for compilers that have not + // yet implemented CWG 1558: + template + using void_ = invoke, Ts...>; +#else + template + using void_ = void; +#endif + +#if META_CXX_VARIABLE_TEMPLATES +#ifdef META_CONCEPT + /// `true` if `T::type` exists and names a type; `false` otherwise. + /// \ingroup trait + template + META_INLINE_VAR constexpr bool is_trait_v = trait; + + /// `true` if `T::invoke` exists and names a class template; `false` otherwise. + /// \ingroup trait + template + META_INLINE_VAR constexpr bool is_callable_v = invocable; +#else // ^^^ Concepts / No concepts vvv + /// \cond + namespace detail + { + template + META_INLINE_VAR constexpr bool is_trait_ = false; + + template + META_INLINE_VAR constexpr bool is_trait_> = true; + + template + META_INLINE_VAR constexpr bool is_callable_ = false; + + template + META_INLINE_VAR constexpr bool is_callable_>> = true; + } // namespace detail + /// \endcond + + /// `true` if `T::type` exists and names a type; `false` otherwise. + /// \ingroup trait + template + META_INLINE_VAR constexpr bool is_trait_v = detail::is_trait_; + + /// `true` if `T::invoke` exists and names a class template; `false` otherwise. + /// \ingroup trait + template + META_INLINE_VAR constexpr bool is_callable_v = detail::is_callable_; +#endif // Concepts vs. variable templates + + /// An alias for `std::true_type` if `T::type` exists and names a type; otherwise, it's an + /// alias for `std::false_type`. + /// \ingroup trait + template + using is_trait = bool_>; + + /// An alias for `std::true_type` if `T::invoke` exists and names a class template; + /// otherwise, it's an alias for `std::false_type`. + /// \ingroup trait + template + using is_callable = bool_>; +#else // ^^^ META_CXX_VARIABLE_TEMPLATES / !META_CXX_VARIABLE_TEMPLATES vvv + /// \cond + namespace detail + { + template + struct is_trait_ + { + using type = std::false_type; + }; + + template + struct is_trait_> + { + using type = std::true_type; + }; + + template + struct is_callable_ + { + using type = std::false_type; + }; + + template + struct is_callable_>> + { + using type = std::true_type; + }; + } // namespace detail + /// \endcond + + template + using is_trait = _t>; + + /// An alias for `std::true_type` if `T::invoke` exists and names a class + /// template or alias template; otherwise, it's an alias for + /// `std::false_type`. + /// \ingroup trait + template + using is_callable = _t>; +#endif + + /// \cond + namespace detail + { +#ifdef META_CONCEPT + template