Add range-v3 via conan and not via the vendor/ directory

This commit is contained in:
Sebastian Messmer 2019-10-31 23:50:55 -07:00
parent 8376a554cc
commit ae09ff98aa
630 changed files with 56 additions and 101037 deletions

View File

@ -20,8 +20,8 @@ init:
- echo %APPVEYOR_BUILD_WORKER_IMAGE%
- set arch=32
- if "%PLATFORM%"=="x64" ( set arch=64)
- set VisualStudioVersion=2017
- if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017 Preview" ( set VisualStudioVersion=Preview)
- set VisualStudioVersion=2019
- if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2019 Preview" ( set VisualStudioVersion=Preview)
- cmd: call "C:\Program Files (x86)\Microsoft Visual Studio\%VisualStudioVersion%\Community\VC\Auxiliary\Build\vcvars%arch%.bat"
install:

View File

@ -6,22 +6,13 @@ include(CheckCXXCompilerFlag)
# Uses: target_activate_cpp14(buildtarget)
###################################################
function(target_activate_cpp14 TARGET)
if("${CMAKE_VERSION}" VERSION_GREATER "3.1")
if(MSVC)
# Required by range-v3, see its README.md
set_property(TARGET ${TARGET} PROPERTY CXX_STANDARD 17)
else()
set_property(TARGET ${TARGET} PROPERTY CXX_STANDARD 14)
set_property(TARGET ${TARGET} PROPERTY CXX_STANDARD_REQUIRED ON)
else("${CMAKE_VERSION}" VERSION_GREATER "3.1")
check_cxx_compiler_flag("-std=c++14" COMPILER_HAS_CPP14_SUPPORT)
if (COMPILER_HAS_CPP14_SUPPORT)
target_compile_options(${TARGET} PRIVATE -std=c++14)
else(COMPILER_HAS_CPP14_SUPPORT)
check_cxx_compiler_flag("-std=c++1y" COMPILER_HAS_CPP14_PARTIAL_SUPPORT)
if (COMPILER_HAS_CPP14_PARTIAL_SUPPORT)
target_compile_options(${TARGET} PRIVATE -std=c++1y)
else()
message(FATAL_ERROR "Compiler doesn't support C++14")
endif()
endif(COMPILER_HAS_CPP14_SUPPORT)
endif("${CMAKE_VERSION}" VERSION_GREATER "3.1")
endif()
set_property(TARGET ${TARGET} PROPERTY CXX_STANDARD_REQUIRED ON)
# Ideally, we'd like to use libc++ on linux as well, but:
# - http://stackoverflow.com/questions/37096062/get-a-basic-c-program-to-compile-using-clang-on-ubuntu-16
# - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=808086

View File

@ -3,6 +3,7 @@ from conans import ConanFile, CMake
class CryFSConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
requires = [
"range-v3/0.9.1@ericniebler/stable",
]
generators = "cmake"
default_options = {

View File

@ -89,8 +89,13 @@ target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_DL_LIBS})
target_link_libraries(${PROJECT_NAME} PUBLIC spdlog cryptopp)
target_link_libraries(${PROJECT_NAME} PUBLIC spdlog cryptopp CONAN_PKG::range-v3)
target_add_boost(${PROJECT_NAME} filesystem system thread chrono)
target_enable_style_warnings(${PROJECT_NAME})
target_activate_cpp14(${PROJECT_NAME})
if(MSVC)
# Required by range-v3, see its README.md
target_compile_options(${PROJECT_NAME} PUBLIC /experimental:preprocessor /permissive- /Zc:twoPhase-)
endif()

View File

@ -128,7 +128,7 @@ TEST(BacktraceTest, ShowBacktraceOnSigIll) {
#else
TEST(BacktraceTest, ContainsBacktrace) {
string backtrace = cpputils::backtrace();
EXPECT_THAT(backtrace, HasSubstr("#1"));
EXPECT_THAT(backtrace, HasSubstr("#0"));
}
TEST(BacktraceTest, ShowBacktraceOnNullptrAccess) {
auto output = call_process_exiting_with_nullptr_violation();

View File

@ -1,4 +1,3 @@
add_subdirectory(googletest)
add_subdirectory(spdlog)
add_subdirectory(cryptopp)
add_subdirectory(range-v3)

2
vendor/README vendored
View File

@ -1,7 +1,7 @@
This directory contains external projects, taken from the following locations:
googletest: https://github.com/google/googletest/tree/release-1.10.0
- changed: https://github.com/google/googletest/pull/2514
spdlog: https://github.com/gabime/spdlog/tree/v1.4.2/include/spdlog
cryptopp: https://github.com/weidai11/cryptopp/tree/CRYPTOPP_8_2_0
- changed: added CMakeLists.txt and cryptopp-config.cmake from https://github.com/noloader/cryptopp-cmake/tree/CRYPTOPP_8_2_0
- changed: commented out line including winapifamily.h in CMakeLists.txt
range-v3: https://github.com/ericniebler/range-v3/tree/0.9.1

View File

@ -1,19 +1,6 @@
#ifndef THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_PP_H_
#define THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_PP_H_
#undef GMOCK_PP_INTERNAL_USE_MSVC
#if defined(__clang__)
#define GMOCK_PP_INTERNAL_USE_MSVC 0
#elif defined(_MSC_VER)
// TODO(iserna): Also verify tradional versus comformant preprocessor.
static_assert(
_MSC_VER >= 1900,
"MSVC version not supported. There is support for MSVC 14.0 and above.");
#define GMOCK_PP_INTERNAL_USE_MSVC 1
#else
#define GMOCK_PP_INTERNAL_USE_MSVC 0
#endif
// Expands and concatenates the arguments. Constructed macros reevaluate.
#define GMOCK_PP_CAT(_1, _2) GMOCK_PP_INTERNAL_CAT(_1, _2)
@ -29,10 +16,6 @@ static_assert(
// Returns the only argument.
#define GMOCK_PP_IDENTITY(_1) _1
// MSVC preprocessor collapses __VA_ARGS__ in a single argument, we use a
// CAT-like directive to force correct evaluation. Each macro has its own.
#if GMOCK_PP_INTERNAL_USE_MSVC
// Evaluates to the number of arguments after expansion.
//
// #define PAIR x, y
@ -43,45 +26,29 @@ static_assert(
// GMOCK_PP_NARG(PAIR) => 2
//
// Requires: the number of arguments after expansion is at most 15.
#define GMOCK_PP_NARG(...) \
GMOCK_PP_INTERNAL_NARG_CAT( \
GMOCK_PP_INTERNAL_INTERNAL_16TH(__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, \
8, 7, 6, 5, 4, 3, 2, 1), )
#define GMOCK_PP_NARG(...) \
GMOCK_PP_INTERNAL_16TH( \
(__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
// Returns 1 if the expansion of arguments has an unprotected comma. Otherwise
// returns 0. Requires no more than 15 unprotected commas.
#define GMOCK_PP_HAS_COMMA(...) \
GMOCK_PP_INTERNAL_HAS_COMMA_CAT( \
GMOCK_PP_INTERNAL_INTERNAL_16TH(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 0), )
#define GMOCK_PP_HAS_COMMA(...) \
GMOCK_PP_INTERNAL_16TH( \
(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0))
// Returns the first argument.
#define GMOCK_PP_HEAD(...) \
GMOCK_PP_INTERNAL_HEAD_CAT(GMOCK_PP_INTERNAL_HEAD(__VA_ARGS__), )
GMOCK_PP_INTERNAL_HEAD((__VA_ARGS__))
// Returns the tail. A variadic list of all arguments minus the first. Requires
// at least one argument.
#define GMOCK_PP_TAIL(...) \
GMOCK_PP_INTERNAL_TAIL_CAT(GMOCK_PP_INTERNAL_TAIL(__VA_ARGS__), )
GMOCK_PP_INTERNAL_TAIL((__VA_ARGS__))
// Calls CAT(_Macro, NARG(__VA_ARGS__))(__VA_ARGS__)
#define GMOCK_PP_VARIADIC_CALL(_Macro, ...) \
GMOCK_PP_INTERNAL_VARIADIC_CALL_CAT( \
GMOCK_PP_CAT(_Macro, GMOCK_PP_NARG(__VA_ARGS__))(__VA_ARGS__), )
#else // GMOCK_PP_INTERNAL_USE_MSVC
#define GMOCK_PP_NARG(...) \
GMOCK_PP_INTERNAL_INTERNAL_16TH(__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, \
7, 6, 5, 4, 3, 2, 1)
#define GMOCK_PP_HAS_COMMA(...) \
GMOCK_PP_INTERNAL_INTERNAL_16TH(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 0)
#define GMOCK_PP_HEAD(...) GMOCK_PP_INTERNAL_HEAD(__VA_ARGS__)
#define GMOCK_PP_TAIL(...) GMOCK_PP_INTERNAL_TAIL(__VA_ARGS__)
#define GMOCK_PP_VARIADIC_CALL(_Macro, ...) \
GMOCK_PP_CAT(_Macro, GMOCK_PP_NARG(__VA_ARGS__))(__VA_ARGS__)
#endif // GMOCK_PP_INTERNAL_USE_MSVC
GMOCK_PP_IDENTITY( \
GMOCK_PP_CAT(_Macro, GMOCK_PP_NARG(__VA_ARGS__))(__VA_ARGS__))
// If the arguments after expansion have no tokens, evaluates to `1`. Otherwise
// evaluates to `0`.
@ -140,7 +107,7 @@ static_assert(
// Expands to 1 if the first argument starts with something in parentheses,
// otherwise to 0.
#define GMOCK_PP_IS_BEGIN_PARENS(...) \
GMOCK_PP_INTERNAL_ALTERNATE_HEAD( \
GMOCK_PP_HEAD( \
GMOCK_PP_CAT(GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_R_, \
GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_C __VA_ARGS__))
@ -179,10 +146,6 @@ static_assert(
#define GMOCK_PP_INTENRAL_EMPTY_TUPLE (, , , , , , , , , , , , , , , )
#define GMOCK_PP_INTERNAL_CAT(_1, _2) _1##_2
#define GMOCK_PP_INTERNAL_STRINGIZE(...) #__VA_ARGS__
#define GMOCK_PP_INTERNAL_INTERNAL_16TH(_1, _2, _3, _4, _5, _6, _7, _8, _9, \
_10, _11, _12, _13, _14, _15, _16, \
...) \
_16
#define GMOCK_PP_INTERNAL_CAT_5(_1, _2, _3, _4, _5) _1##_2##_3##_4##_5
#define GMOCK_PP_INTERNAL_IS_EMPTY(_1, _2, _3, _4) \
GMOCK_PP_HAS_COMMA(GMOCK_PP_INTERNAL_CAT_5(GMOCK_PP_INTERNAL_IS_EMPTY_CASE_, \
@ -190,30 +153,24 @@ static_assert(
#define GMOCK_PP_INTERNAL_IS_EMPTY_CASE_0001 ,
#define GMOCK_PP_INTERNAL_IF_1(_Then, _Else) _Then
#define GMOCK_PP_INTERNAL_IF_0(_Then, _Else) _Else
#define GMOCK_PP_INTERNAL_HEAD(_1, ...) _1
#define GMOCK_PP_INTERNAL_TAIL(_1, ...) __VA_ARGS__
#if GMOCK_PP_INTERNAL_USE_MSVC
#define GMOCK_PP_INTERNAL_NARG_CAT(_1, _2) GMOCK_PP_INTERNAL_NARG_CAT_I(_1, _2)
#define GMOCK_PP_INTERNAL_HEAD_CAT(_1, _2) GMOCK_PP_INTERNAL_HEAD_CAT_I(_1, _2)
#define GMOCK_PP_INTERNAL_HAS_COMMA_CAT(_1, _2) \
GMOCK_PP_INTERNAL_HAS_COMMA_CAT_I(_1, _2)
#define GMOCK_PP_INTERNAL_TAIL_CAT(_1, _2) GMOCK_PP_INTERNAL_TAIL_CAT_I(_1, _2)
#define GMOCK_PP_INTERNAL_VARIADIC_CALL_CAT(_1, _2) \
GMOCK_PP_INTERNAL_VARIADIC_CALL_CAT_I(_1, _2)
#define GMOCK_PP_INTERNAL_NARG_CAT_I(_1, _2) _1##_2
#define GMOCK_PP_INTERNAL_HEAD_CAT_I(_1, _2) _1##_2
#define GMOCK_PP_INTERNAL_HAS_COMMA_CAT_I(_1, _2) _1##_2
#define GMOCK_PP_INTERNAL_TAIL_CAT_I(_1, _2) _1##_2
#define GMOCK_PP_INTERNAL_VARIADIC_CALL_CAT_I(_1, _2) _1##_2
#define GMOCK_PP_INTERNAL_ALTERNATE_HEAD(...) \
GMOCK_PP_INTERNAL_ALTERNATE_HEAD_CAT(GMOCK_PP_HEAD(__VA_ARGS__), )
#define GMOCK_PP_INTERNAL_ALTERNATE_HEAD_CAT(_1, _2) \
GMOCK_PP_INTERNAL_ALTERNATE_HEAD_CAT_I(_1, _2)
#define GMOCK_PP_INTERNAL_ALTERNATE_HEAD_CAT_I(_1, _2) _1##_2
#else // GMOCK_PP_INTERNAL_USE_MSVC
#define GMOCK_PP_INTERNAL_ALTERNATE_HEAD(...) GMOCK_PP_HEAD(__VA_ARGS__)
#endif // GMOCK_PP_INTERNAL_USE_MSVC
// Because of MSVC treating a token with a comma in it as a single token when passed
// to another macro, we need to force it to evaluate it as multiple tokens. We do that
// by using a "IDENTITY(MACRO PARENTHESIZED_ARGS)" macro.
// We define one per possible macro that relies on this behavior.
// Note "_Args" must be parenthesized.
#define GMOCK_PP_INTERNAL_INTERNAL_16TH(_1, _2, _3, _4, _5, _6, _7, _8, _9, \
_10, _11, _12, _13, _14, _15, _16, \
...) \
_16
#define GMOCK_PP_INTERNAL_16TH(_Args) \
GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_16TH _Args)
#define GMOCK_PP_INTERNAL_INTERNAL_HEAD(_1, ...) _1
#define GMOCK_PP_INTERNAL_HEAD(_Args) \
GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_HEAD _Args)
#define GMOCK_PP_INTERNAL_INTERNAL_TAIL(_1, ...) __VA_ARGS__
#define GMOCK_PP_INTERNAL_TAIL(_Args) \
GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_TAIL _Args)
#define GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_C(...) 1 _
#define GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_R_1 1,

View File

@ -1,5 +1,10 @@
#include "gmock/internal/gmock-pp.h"
// Used to test MSVC treating __VA_ARGS__ with a comma in it as one value
#define GMOCK_TEST_REPLACE_comma_WITH_COMMA_I_comma ,
#define GMOCK_TEST_REPLACE_comma_WITH_COMMA(x) \
GMOCK_PP_CAT(GMOCK_TEST_REPLACE_comma_WITH_COMMA_I_, x)
// Static assertions.
namespace testing {
namespace internal {
@ -17,6 +22,11 @@ static_assert(GMOCK_PP_NARG(x, y, z, w) == 4, "");
static_assert(!GMOCK_PP_HAS_COMMA(), "");
static_assert(GMOCK_PP_HAS_COMMA(b, ), "");
static_assert(!GMOCK_PP_HAS_COMMA((, )), "");
static_assert(
GMOCK_PP_HAS_COMMA(GMOCK_TEST_REPLACE_comma_WITH_COMMA(comma)), "");
static_assert(
GMOCK_PP_HAS_COMMA(GMOCK_TEST_REPLACE_comma_WITH_COMMA(comma(unrelated))),
"");
static_assert(!GMOCK_PP_IS_EMPTY(, ), "");
static_assert(!GMOCK_PP_IS_EMPTY(a), "");
static_assert(!GMOCK_PP_IS_EMPTY(()), "");

View File

@ -1,2 +0,0 @@
add_library(range-v3 INTERFACE)
target_include_directories(range-v3 SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/range-v3/include)

View File

View File

@ -1,92 +0,0 @@
{
AccessModifierOffset: -4,
AlignAfterOpenBracket: Align,
AlignEscapedNewlinesLeft: true,
AlignTrailingComments: true,
AllowAllParametersOfDeclarationOnNextLine: false,
AllowShortBlocksOnASingleLine: true,
AllowShortCaseLabelsOnASingleLine: false,
AllowShortFunctionsOnASingleLine: None,
AllowShortIfStatementsOnASingleLine: false,
AllowShortLoopsOnASingleLine: false,
AlwaysBreakBeforeMultilineStrings: true,
AlwaysBreakAfterReturnType: None,
AlwaysBreakTemplateDeclarations: true,
BinPackArguments: false,
BinPackParameters: true,
BraceWrapping: {
AfterCaseLabel: true,
AfterClass: true,
AfterControlStatement: true,
AfterEnum: true,
AfterFunction: true,
AfterNamespace: true,
AfterStruct: true,
AfterUnion: true,
AfterExternBlock: true,
BeforeCatch: true,
BeforeElse: true,
IndentBraces: false,
SplitEmptyFunction: false,
SplitEmptyRecord: false,
SplitEmptyNamespace: true,
},
BreakBeforeBinaryOperators: false,
BreakBeforeBraces: Custom,
BreakBeforeTernaryOperators: true,
BreakConstructorInitializers: BeforeComma,
BreakInheritanceList: BeforeComma,
ColumnLimit: 90,
ConstructorInitializerAllOnOneLineOrOnePerLine: false,
ConstructorInitializerIndentWidth: 2,
ContinuationIndentWidth: 4,
Cpp11BracedListStyle: true,
DerivePointerAlignment: false,
ExperimentalAutoDetectBinPacking: false,
ForEachMacros: ['RANGES_FOR',],
IncludeBlocks: Regroup,
IncludeCategories: [
{ Regex: '^<range/v3/range_fwd.hpp',
Priority: 5},
{ Regex: '^<range/v3',
Priority: 6},
{ Regex: '^<concepts/',
Priority: 4},
{ Regex: '^<meta/',
Priority: 3},
{ Regex: '^<std/.*>$',
Priority: 2},
{ Regex: '^<.*>$',
Priority: 1},
],
IndentCaseLabels: false,
IndentFunctionDeclarationAfterType: false,
IndentWidth: 4,
KeepEmptyLinesAtTheStartOfBlocks: true,
Language: Cpp,
MaxEmptyLinesToKeep: 1,
MacroBlockBegin: "^(RANGES|META)_BEGIN_(NAMESPACE_(STD|VERSION|CONTAINER)|NIEBLOID)$",
MacroBlockEnd: "^(RANGES|META)_END_(NAMESPACE_(STD|VERSION|CONTAINER)|NIEBLOID)$",
NamespaceIndentation: All,
PenaltyBreakBeforeFirstCallParameter: 10,
PenaltyReturnTypeOnItsOwnLine: 1000,
PointerAlignment: Middle,
SpaceAfterControlStatementKeyword: false,
SpaceAfterTemplateKeyword: false,
SpaceBeforeAssignmentOperators: true,
SpaceBeforeParens: Never,
SpaceInEmptyParentheses: false,
SpacesBeforeTrailingComments: 1,
SpacesInAngles: false,
SpacesInCStyleCastParentheses: false,
SpacesInParentheses: false,
Standard: Cpp11,
StatementMacros: [
'RANGES_INLINE_VARIABLE',
'RANGES_DEFINE_CPO',
'CPP_member',
'CPP_broken_friend_member',
],
TabWidth: 4,
UseTab: Never,
}

View File

@ -1,237 +0,0 @@
## Copyright (c) 2013 GitHub, Inc.
##
## 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.
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# Clion files
.idea
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
x64/
build*/
bld/
[Bb]in/
[Oo]bj/
bazel-*
cmake-build-*/
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
!packages/*/build/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
#NUNIT
*.VisualState.xml
TestResult.xml
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
*.azurePubxml
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
#packages/
## TODO: If the tool you use requires repositories.config, also uncomment the next line
#!packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Buck build artefacts
.buckd/
buck-out/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.[Pp]ublish.xml
*.pfx
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# =========================
# Windows detritus
# =========================
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Visual Studio stuff
*.VC.db
*.VC.opendb
.vscode/
.vs/
\#*#
.#*

View File

@ -1,303 +0,0 @@
# Copyright Louis Dionne 2013-2016
# Copyright Gonzalo BG 2014-2017
# Copyright Julian Becker 2015
# Copyright Manu Sánchez 2015
# Copyright Casey Carter 2015-2017
# Copyright Eric Niebler 2015-2016
# Copyright Paul Fultz II 2015-2016
# Copyright Jakub Szuppe 2016.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.txt or copy at http://boost.org/LICENSE_1_0.txt)
# Adapted from various sources, including:
# - Louis Dionne's Hana: https://github.com/ldionne/hana
# - Paul Fultz II's FIT: https://github.com/pfultz2/Fit
language: cpp
dist: xenial
script: cmake
git:
depth: 1
env:
global:
- DEPS_DIR=${TRAVIS_BUILD_DIR}/deps
- CMAKE_VERSION="3.12.0"
cache:
directories:
- ${DEPS_DIR}/cmake-${CMAKE_VERSION}
matrix:
include:
- env: BUILD_TYPE=Release CPP=1z SYSTEM_LIBCXX=On
os: osx
compiler: clang
# The ASAN build in install_libcxx.sh doesn't work for versions < 4
# clang 3.6 C++17/14 Release libc++
- env: CLANG_VERSION=3.6 BUILD_TYPE=Release CPP=14 LIBCXX=On HEADERS=On
os: linux
addons: &clang36
apt:
packages:
- clang-3.6
- libstdc++-5-dev
- valgrind
sources:
- ubuntu-toolchain-r-test
# clang 3.7 C++17/14 Release libc++
- env: CLANG_VERSION=3.7 BUILD_TYPE=Release CPP=14 LIBCXX=On HEADERS=On
os: linux
addons: &clang37
apt:
packages:
- clang-3.7
- libstdc++-5-dev
- valgrind
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-3.7
- sourceline: 'deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.7 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
# clang 3.8 C++17/14 Release libc++
- env: CLANG_VERSION=3.8 BUILD_TYPE=Release CPP=1z LIBCXX=On
os: linux
addons: &clang38
apt:
packages:
- util-linux
- clang-3.8
- libstdc++-5-dev
- valgrind
sources:
- ubuntu-toolchain-r-test
- env: CLANG_VERSION=3.8 BUILD_TYPE=Release CPP=14 LIBCXX=On HEADERS=On
os: linux
addons: *clang38
# clang 3.9 C++17/14 Release libc++
- env: CLANG_VERSION=3.9 BUILD_TYPE=Release CPP=1z LIBCXX=On
os: linux
addons: &clang39
apt:
packages:
- util-linux
- clang-3.9
- libstdc++-6-dev
- valgrind
sources:
- ubuntu-toolchain-r-test
- env: CLANG_VERSION=3.9 BUILD_TYPE=Release CPP=14 LIBCXX=On HEADERS=On
os: linux
addons: *clang39
# clang 5 C++17/14/1z Debug/Release-ASAN libc++, 17 Debug libstdc++
- env: CLANG_VERSION=5.0 BUILD_TYPE=Debug CPP=1z LIBCXX=On
os: linux
addons: &clang5
apt:
packages:
- clang-5.0
- libstdc++-6-dev
- valgrind
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-5.0
- sourceline: 'deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-5.0 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- env: CLANG_VERSION=5.0 BUILD_TYPE=Release CPP=1z ASAN=On LIBCXX=On HEADERS=On
os: linux
addons: *clang5
- env: CLANG_VERSION=5.0 BUILD_TYPE=Debug CPP=14 LIBCXX=On
os: linux
addons: *clang5
- env: CLANG_VERSION=5.0 BUILD_TYPE=Release CPP=14 ASAN=On LIBCXX=On
os: linux
addons: *clang5
- env: CLANG_VERSION=5.0 BUILD_TYPE=Release CPP=1z
os: linux
addons: *clang5
# Module build is on the floor
# - env: CLANG_VERSION=5.0 BUILD_TYPE=Release CPP=1z MSAN=On LIBCXX=On CLANG_MODULES=On
# os: linux
# addons: *clang5
# gcc-5 C++17/C++14 Release
- env: GCC_VERSION=5 BUILD_TYPE=Release CPP=1z
os: linux
addons: &gcc5
apt:
packages:
- g++-5
- valgrind
sources:
- ubuntu-toolchain-r-test
- env: GCC_VERSION=5 BUILD_TYPE=Release CPP=14 HEADERS=On
os: linux
addons: *gcc5
# gcc-6 C++17/14/1z Debug/Release
- env: GCC_VERSION=6 BUILD_TYPE=Debug CPP=1z
os: linux
addons: &gcc6
apt:
packages:
- g++-6
- valgrind
sources:
- ubuntu-toolchain-r-test
- env: GCC_VERSION=6 BUILD_TYPE=Release CPP=1z
os: linux
addons: *gcc6
- env: GCC_VERSION=6 BUILD_TYPE=Debug CPP=14 HEADERS=On
os: linux
addons: *gcc6
- env: GCC_VERSION=6 BUILD_TYPE=Release CPP=14
os: linux
addons: *gcc6
# gcc-7 C++17/14/1z Debug/Release
- env: GCC_VERSION=7 BUILD_TYPE=Debug CPP=1z
os: linux
addons: &gcc7
apt:
packages:
- g++-7
- valgrind
sources:
- ubuntu-toolchain-r-test
- env: GCC_VERSION=7 BUILD_TYPE=Release CPP=1z
os: linux
addons: *gcc7
- env: GCC_VERSION=7 BUILD_TYPE=Debug CPP=14 HEADERS=On
os: linux
addons: *gcc7
- env: GCC_VERSION=7 BUILD_TYPE=Release CPP=14
os: linux
addons: *gcc7
- env: GCC_VERSION=7 BUILD_TYPE=Release CPP=1z CONCEPTS=On
os: linux
addons: *gcc7
# gcc-8 C++17/14/1z Debug/Release
- env: GCC_VERSION=8 BUILD_TYPE=Debug CPP=1z
os: linux
addons: &gcc8
apt:
packages:
- g++-8
- valgrind
sources:
- ubuntu-toolchain-r-test
- env: GCC_VERSION=8 BUILD_TYPE=Release CPP=1z
os: linux
addons: *gcc8
- env: GCC_VERSION=8 BUILD_TYPE=Debug CPP=14 HEADERS=On
os: linux
addons: *gcc8
- env: GCC_VERSION=8 BUILD_TYPE=Release CPP=14
os: linux
addons: *gcc8
- env: GCC_VERSION=8 BUILD_TYPE=Release CPP=1z CONCEPTS=On
os: linux
addons: *gcc8
# Install dependencies
before_install:
- set -e
- |
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
brew update
brew install gnu-sed
brew install gnu-which
brew upgrade cmake
export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
elif [ "$BUILD_TYPE" == "Release" -a "$ASAN" != "On" -a "$MSAN" != "On" ]; then
USE_VALGRIND=On
fi
- |
if [ "${TRAVIS_OS_NAME}" == "linux" ]; then
if [ -f ${DEPS_DIR}/cmake-${CMAKE_VERSION}/cached ]; then
echo "Using cached cmake version ${CMAKE_VERSION}."
else
CMAKE_URL="https://cmake.org/files/v3.12/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz"
mkdir -p ${DEPS_DIR}/cmake-${CMAKE_VERSION}
travis_retry wget --no-check-certificate --quiet -O - "${CMAKE_URL}" | tar --strip-components=1 -xz -C ${DEPS_DIR}/cmake-${CMAKE_VERSION}
touch ${DEPS_DIR}/cmake-${CMAKE_VERSION}/cached
fi
export PATH="${DEPS_DIR}/cmake-${CMAKE_VERSION}/bin:${PATH}"
fi
- if [ -n "$GCC_VERSION" ]; then export CXX="g++-${GCC_VERSION}" CC="gcc-${GCC_VERSION}"; fi
- if [ -n "$CLANG_VERSION" ]; then export CXX="clang++-${CLANG_VERSION}" CC="clang-${CLANG_VERSION}"; fi
- which $CXX && $CXX --version
- which $CC
- if [ "$USE_VALGRIND" == "On" ]; then which valgrind; fi
- if [ "$ASAN" == "On" ]; then export SANITIZER="Address;Undefined"; fi
- if [ "$MSAN" == "On" ]; then export SANITIZER="MemoryWithOrigins"; fi
- if [ -n "$CLANG_VERSION" ]; then PATH="${PATH}" CXX="$CXX" CC="$CC" ./install_libcxx.sh; fi
install:
# Workaround for valgrind bug: https://bugs.kde.org/show_bug.cgi?id=326469.
# It is fixed in valgrind 3.10 so this won't be necessary if someone
# replaces the current valgrind (3.7) with valgrind-3.10
- |
if [ "$USE_VALGRIND" == "On" ]; then
sed -i 's/march=native/msse4.2/' cmake/ranges_flags.cmake
# We need to explicitly initialize std::random_device on libstdc++ to avoid using RDRAND
# since valgrind doesn't understand the instruction.
CXX_FLAGS="${CXX_FLAGS} -DRANGES_WORKAROUND_VALGRIND_RDRAND"
fi
- if [ "$GCC_VERSION" == "5" ]; then CXX_FLAGS="${CXX_FLAGS} -DRANGES_CXX_CONSTEXPR=RANGES_CXX_CONSTEXPR11"; fi
- |
if [ "$LIBCXX" == "On" ]; then
CXX_FLAGS="${CXX_FLAGS} -stdlib=libc++ -nostdinc++ -cxx-isystem ${TRAVIS_BUILD_DIR}/llvm/include/c++/v1/ -Wno-unused-command-line-argument"
CXX_LINKER_FLAGS="${CXX_LINKER_FLAGS} -L ${TRAVIS_BUILD_DIR}/llvm/lib -Wl,-rpath,${TRAVIS_BUILD_DIR}/llvm/lib -lc++abi"
if [ -n "$CLANG_VERSION" ]; then
if [ "$ASAN" == "On" ]; then
CXX_FLAGS="${CXX_FLAGS} -fsanitize=address"
elif [ "$MSAN" == "On" ]; then
CXX_FLAGS="${CXX_FLAGS} -fsanitize=memory"
fi
fi
fi
- mkdir -p build
# This cd works, but causes the shell to exit on OSX with set -e. I don't even.
- set +e; cd build; set -e; pwd
- cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CXX_FLAGS="${CXX_FLAGS}" -DCMAKE_EXE_LINKER_FLAGS="${CXX_LINKER_FLAGS}" -DRANGES_CXX_STD=$CPP -DRANGE_V3_HEADER_CHECKS=$HEADERS -DRANGES_PREFER_REAL_CONCEPTS=$CONCEPTS -DRANGES_VERBOSE_BUILD=On -DRANGES_ASAN=$ASAN -DRANGES_MSAN=$MSAN -DRANGES_DEEP_STL_INTEGRATION=On -Wdev
- cat CMakeFiles/CMakeError.log || true
- cat CMakeFiles/CMakeOutput.log || true
- if [ "$CLANG_MODULES" == "On" -a "$LIBCXX" == "On" ]; then cmake .. -DRANGES_MODULES=On -DRANGES_LIBCXX_MODULE="${TRAVIS_BUILD_DIR}/llvm/include/c++/v1/module.modulemap"; fi
- make -j2 VERBOSE=1
script:
- if [ "$USE_VALGRIND" == "On" ]; then CTEST_FLAGS="-D ExperimentalMemCheck"; fi
- ctest -j2 -VV ${CTEST_FLAGS}
notifications:
email: false

View File

@ -1,42 +0,0 @@
prebuilt_cxx_library(
name = 'concepts',
header_namespace = 'concepts',
header_only = True,
exported_headers = subdir_glob([
('include/concepts', '**/*.hpp'),
]),
licenses = [
'LICENSE.txt',
],
)
prebuilt_cxx_library(
name = 'meta',
header_namespace = 'meta',
header_only = True,
exported_headers = subdir_glob([
('include/meta', '**/*.hpp'),
]),
licenses = [
'LICENSE.txt',
],
)
prebuilt_cxx_library(
name = 'range-v3',
header_namespace = 'range/v3',
header_only = True,
exported_headers = subdir_glob([
('include/range/v3', '**/*.hpp'),
]),
licenses = [
'LICENSE.txt',
],
visibility = [
'PUBLIC'
],
deps = [
':concepts',
':meta',
],
)

View File

@ -1,42 +0,0 @@
cc_library(
name = 'concepts',
hdrs = glob([
'include/concepts/**/*.hpp',
]),
includes = [
"include",
],
)
cc_library(
name = 'meta',
hdrs = glob([
'include/meta/**/*.hpp',
]),
includes = [
"include",
],
)
cc_library(
name = 'std',
hdrs = glob([
'include/std/**/*.hpp',
]),
includes = [
"include",
],
)
cc_library(
name = 'range-v3',
hdrs = glob([
'include/range/v3/**/*.hpp',
]),
visibility = ["//visibility:public"],
deps = [
':concepts',
':meta',
':std',
],
)

View File

@ -1,171 +0,0 @@
# Copyright Eric Niebler 2014
# Copyright Gonzalo Brito Gadeschi 2014, 2017
# Copyright Louis Dionne 2015
# Copyright Casey Carter 2016
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
cmake_minimum_required(VERSION 3.6)
get_directory_property(is_subproject PARENT_DIRECTORY)
if(NOT is_subproject)
set(is_standalone YES)
else()
set(is_standalone NO)
endif()
project(Range-v3 CXX)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export compilation data-base
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
add_library(meta INTERFACE)
target_include_directories(meta INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/>)
target_include_directories(meta SYSTEM INTERFACE $<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>)
target_compile_options(meta INTERFACE $<$<CXX_COMPILER_ID:MSVC>:/permissive->)
add_library(concepts INTERFACE)
target_include_directories(concepts INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/>)
target_include_directories(concepts SYSTEM INTERFACE $<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>)
target_compile_options(concepts INTERFACE $<$<CXX_COMPILER_ID:MSVC>:/permissive- /experimental:preprocessor /wd5105>)
target_link_libraries(concepts INTERFACE meta)
add_library(range-v3 INTERFACE)
target_include_directories(range-v3 INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/>)
target_include_directories(range-v3 SYSTEM INTERFACE $<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>)
target_compile_options(range-v3 INTERFACE $<$<CXX_COMPILER_ID:MSVC>:/permissive->)
target_link_libraries(range-v3 INTERFACE concepts meta)
function(rv3_add_test TESTNAME EXENAME FIRSTSOURCE)
add_executable(${EXENAME} ${FIRSTSOURCE} ${ARGN})
target_link_libraries(${EXENAME} range-v3)
add_test(${TESTNAME} ${EXENAME})
endfunction(rv3_add_test)
include(ranges_options)
include(ranges_env)
include(ranges_flags)
if(RANGE_V3_DOCS)
add_subdirectory(doc)
endif()
if(RANGE_V3_TESTS)
include(CTest)
add_subdirectory(test)
endif()
if(RANGE_V3_EXAMPLES)
add_subdirectory(example)
endif()
if(RANGE_V3_PERF)
add_subdirectory(perf)
endif()
# Add header files as sources to fix MSVS 2017 not finding source during debugging
file(GLOB_RECURSE RANGE_V3_PUBLIC_HEADERS_ABSOLUTE
"${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
add_custom_target(headers SOURCES ${RANGE_V3_PUBLIC_HEADERS_ABSOLUTE})
set_target_properties(headers PROPERTIES FOLDER "header")
# Test all headers
if(RANGE_V3_HEADER_CHECKS)
include(TestHeaders)
file(GLOB_RECURSE RANGE_V3_PUBLIC_HEADERS
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
# This header is not meant to be included directly:
list(REMOVE_ITEM RANGE_V3_PUBLIC_HEADERS std/detail/associated_types.hpp)
# Deprecated headers
if(CMAKE_CXX_COMPILER_ID STREQUAL GNU)
foreach(header ${RANGE_V3_PUBLIC_HEADERS})
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/${header}" is_deprecated
LIMIT_COUNT 1
REGEX ".*RANGES_DEPRECATED_HEADER.*")
if(is_deprecated)
list(APPEND RANGE_V3_DEPRECATED_PUBLIC_HEADERS "${header}")
endif()
endforeach()
endif()
add_header_test(test.range.v3.headers
EXCLUDE ${RANGE_V3_DEPRECATED_PUBLIC_HEADERS}
HEADERS ${RANGE_V3_PUBLIC_HEADERS})
target_link_libraries(test.range.v3.headers PRIVATE range-v3)
endif()
# Grab the range-v3 version numbers:
include(${CMAKE_CURRENT_SOURCE_DIR}/Version.cmake)
set(RANGE_V3_VERSION ${RANGE_V3_MAJOR}.${RANGE_V3_MINOR}.${RANGE_V3_PATCHLEVEL})
# Try to build a new version.hpp
configure_file(version.hpp.in include/range/v3/version.hpp @ONLY)
file(STRINGS ${CMAKE_CURRENT_BINARY_DIR}/include/range/v3/version.hpp RANGE_V3_OLD_VERSION_HPP)
file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/include/range/v3/version.hpp RANGE_V3_NEW_VERSION_HPP)
# If the new version.hpp is materially different from the one in the source
# directory, update it, commit, and tag.
if(NOT RANGE_V3_NEW_VERSION_HPP STREQUAL RANGE_V3_OLD_VERSION_HPP)
# Check that README.md and Version.cmake are the only changed file:
execute_process(
COMMAND ${GIT_EXECUTABLE} -C "${CMAKE_CURRENT_SOURCE_DIR}" status --porcelain -uno
OUTPUT_VARIABLE RANGE_V3_GIT_STATUS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REPLACE "\n" ";" RANGE_V3_GIT_STATUS ${RANGE_V3_GIT_STATUS})
if (NOT "x${RANGE_V3_GIT_STATUS}" STREQUAL "x M Version.cmake; M doc/release_notes.md")
message(FATAL_ERROR "Cannot update version.hpp: range-v3 source directory has a dirty status")
endif()
file(
COPY ${CMAKE_CURRENT_BINARY_DIR}/include/range/v3/version.hpp
DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/include/range/v3
)
execute_process(
COMMAND ${GIT_EXECUTABLE} -C "${CMAKE_CURRENT_SOURCE_DIR}" add -u
)
execute_process(
COMMAND ${GIT_EXECUTABLE} -C "${CMAKE_CURRENT_SOURCE_DIR}" commit -m "${RANGE_V3_VERSION}"
)
execute_process(
COMMAND ${GIT_EXECUTABLE} -C "${CMAKE_CURRENT_SOURCE_DIR}" tag -f -a "${RANGE_V3_VERSION}" -m "${RANGE_V3_VERSION}"
)
find_program(CONAN_EXECUTABLE NAMES conan conan.exe)
if (NOT "x${CONAN_EXECUTABLE}" STREQUAL "xCONAN_EXECUTABLE-NOTFOUND")
message(STATUS "Exporting conanfile for new version")
execute_process(
COMMAND ${CONAN_EXECUTABLE} create . range-v3/${RANGE_V3_VERSION}@ericniebler/stable
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
endif()
message(STATUS "Version updated to ${RANGE_V3_VERSION}. Don't forget to:")
message(STATUS " git push origin <feature-branch>")
message(STATUS "and (after that is merged to master) then:")
message(STATUS " conan create ${CMAKE_CURRENT_SOURCE_DIR} range-v3/${RANGE_V3_VERSION}@ericniebler/stable")
message(STATUS " conan upload --all range-v3/${RANGE_V3_VERSION}@ericniebler/stable")
endif()
include(CMakePackageConfigHelpers)
# write_basic_package_version_file(...) gained ARCH_INDEPENDENT in CMake 3.14.
# For CMake 3.6, this workaround makes the version file ARCH_INDEPENDENT
# by making CMAKE_SIZEOF_VOID_P empty.
set(OLD_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
set(CMAKE_SIZEOF_VOID_P "")
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/range-v3-config-version.cmake
VERSION ${RANGE_V3_VERSION}
COMPATIBILITY ExactVersion
)
set(CMAKE_SIZEOF_VOID_P ${OLD_CMAKE_SIZEOF_VOID_P})
install(TARGETS concepts meta range-v3 EXPORT range-v3-targets DESTINATION lib)
install(EXPORT range-v3-targets FILE range-v3-config.cmake DESTINATION lib/cmake/range-v3)
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/range-v3-config-version.cmake
DESTINATION lib/cmake/range-v3)
install(DIRECTORY include/ DESTINATION include FILES_MATCHING PATTERN "*")
export(EXPORT range-v3-targets FILE range-v3-config.cmake)

View File

@ -1,48 +0,0 @@
Acknowledgements
----------------
In range-v3, I have integrated many ideas that come from other people. I would be remiss to not mention them. Many others helped either directly or indirectly in a variety of ways. In no particular order...
| Contributor | Contribution |
|-----------------------------|------|
| Jeremy Siek | Container algorithms (in Boost pre-history), Boost.Iterators |
| Thorston Ottoson | Boost.Range v1 |
| Neil Groves | Boost.Range v2 |
| David Abrahams, Thomas Witt | Boost.Iterators, Sentinels |
| Sean Parent | ASL, Projections, View / Range distinction, much Generic Program wisdom besides |
| Dietmar Kühl | Array Traits, Property Map |
| Andrew Sutton | C++ Concepts "Lite", Origin Libraries, Palo Alto Report |
| Doug Gregor | C++0x Concepts |
| Casey Carter | Co-author and Editor, Ranges TS; major code contributions |
| Gonzalo Brito Gadeschi | Many ideas, bug reports, and code contributions |
| Alexander Stepanov | STL, Generic Programming, Iterators, Elements of Programming, etc. |
| Bjarne Stroustrup | A tireless effort to add proper support for Generic Programming to C++, early support for my Ranges proposal |
| Herb Sutter | Early support for my Ranges proposal |
| The Standard C++ Foundation | A generous grant supporting my Ranges work |
An Abreviated History
--------------------
**Range v1**
I came to Boost in the early 2000's. By that time, Boost already had a Range library (Thorston Ottoson's). At this time, Boost.Range was little more that the `begin` and `end` free functions, and range-based overloads of the STL algorithms that dispatched to the iterator-based overloads in namespace `std`.
Boost also already had the Iterators library by David Abrahams and Jeremy Siek. This library had iterator adaptors like `filter_iterator` and `transform_iterator`.
**Range v2**
It seemed natural to me that the Range library and the adaptors from the Iterators library should be combined. I wrote the `filter` and `transform` range adaptors, commandeered the pipe operator (`|`) from bash for chaining, and put a rough library together called Range_ex in the Boost File Vault (which would later become the Boost Sandbox). I saw problems with my design and never finished it.
A few years later, Neil Groves picked up some of the ideas in my Range\_ex, polished them a great deal, published his own Range\_ex library, and submitted it to Boost. It became Boost.Range v2. At the time of writing (March, 2017), it is the version still shipping with Boost.
**Range v3**
In 2013, I published a blog post called ["Out Parameters, Move Semantics, and Stateful Algorithms"](http://ericniebler.com/2013/10/13/out-parameters-vs-move-semantics/) that turned my mind to ranges once again. Following that, it became clear to me that the Boost.Range library, designed for C++98, needed a facelift for the post-C++11 world. I began what I believed at the time would be a quick hack to bring Boost.Range into the modern world. I called it "Range v3", thinking it would become the third major version of the Boost.Range library. Subsequent posts detailed the evolution of my thinking as range-v3 took shape.
**Standardization**
Around this time, some big thinkers in the C++ community were working to resurrect the effort to add Concepts to C++. They published a paper ([N3351](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3351.pdf)) that would become known as the **"Palo Alto Report"** which detailed the necessary and sufficient language and library support for a concept-checked version of the Standard Template Library. The authors of the paper included Alexander Stepanov, Bjarne Stroustrup, Sean Parent, Andrew Sutton, and more. Andrew Sutton began working in earnest to realize the core language changes, an effort that became known as "Concepts Lite". (It is now the Concepts TS.)
I decided early on that Concepts Lite, or something like it, would become part of Standard C++. Recognizing that C++ would need a concept-ified Standard Library to go with the language feature, I began evolving range-v3 in that direction, eventually submitting ["Ranges for the Standard Library, Revision 1"](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4128.html) to the C++ Standardization Committee, together with Andrew Sutton and Sean Parent. The Committee approved the direction in late 2014, and so it goes...
Today (2017-03), we are very close to a final Ranges TS and are on target to integrate into Standard C++ in 2020, with *much* more to come. Stay tuned.

View File

@ -1,151 +0,0 @@
========================================================
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.
//

View File

@ -1,77 +0,0 @@
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 3.6.2 (or later)
- GCC 5.0.2 (or later) (C++14 "extended constexpr" support is poor before 6.1.)
- Clang/LLVM 6 (or later) on Windows (older versions may work - we haven't tested.)
- Visual Studio 2019 Preview 4 (or later) on Windows, with some caveats due to range-v3's strict conformance requirements:
- range-v3 needs `/std:c++17 /permissive-`
- range-v3 needs a fully conforming preprocessor, so `/experimental:preprocessor` is necessary. Note that the conforming preprocessor diagnoses `C5105` "macro expansion producing 'defined' has undefined behavior" in some of the Windows SDK headers, so you'll probably want to suppress that warning with `/wd5105`.
[ Note: We've "retired" support for Clang/C2 with the VS2015 toolset (i.e., the `v140_clang_c2` toolset) which Microsoft no longer supports for C++ use. We no longer have CI runs, but haven't gone out of our way to break anything, so it will likely continue to work. ]
**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 Travis-CI: [![Travis Build Status](https://travis-ci.org/ericniebler/range-v3.svg?branch=master)](https://travis-ci.org/ericniebler/range-v3)
- on AppVeyor: [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/fwl9ymc2t6ukn9qj/branch/master?svg=true)](https://ci.appveyor.com/project/ericniebler/range-v3)
Say Thanks!
-----------
I do this work because I love it and because I love C++ and want it to be as excellent as I know it can be. If you like my work and are looking for a way to say thank you, you can leave a supportive comment on [my blog](http://ericniebler.com). Or you could leave me some kudos on my Open Hub range-v3 contribution page. Just click the **Give Kudos** button [here](https://www.openhub.net/p/range-v3/contributors/3053743222308608).

View File

@ -1,26 +0,0 @@
* Add contiguous iterator utilities. How about `is_contiguous_iterator` and `as_contiguous_range`:
```
CPP_template(typename I, typename S)(
requires RandomAccessIterator<I> &&
SizedSentinel<S, I> &&
is_contiguous_iterator<I>())
subrange<std::add_pointer_t<iter_reference_t<I>>>
as_contiguous_range(I begin, S end)
{
if(begin == end)
return {nullptr, nullptr};
else
return {addressof(*begin), addressof(*begin) + (end - begin)};
}
```
* Longer-term goals:
- Make `inplace_merge` work with forward iterators
- Make the sorting algorithms work with forward iterators
* Maybe iterators are not necessarily countable. Is there a relation between
the ability to be able to subtract two iterators to find the distance, and
with the existence of a DistanceType associated type? Think of:
- counted iterators (subtractable regardless of traversal category)
- repeat_view iterators (*not* subtractable but could be random access otherwise)
- infinite ranges (only countable with an infinite precision integer which we lack)

View File

@ -1,5 +0,0 @@
# To update the range-v3 version, from a *CLEAN* working directory, update the version numbers below.
# This makefile will generate a new version.hpp, *AMEND THE MOST RECENT COMMIT*, and git-tag the commit.
set(RANGE_V3_MAJOR 0)
set(RANGE_V3_MINOR 9)
set(RANGE_V3_PATCHLEVEL 1)

View File

View File

@ -1,59 +0,0 @@
shallow_clone: true
image: Visual Studio 2019
platform:
- x64_x86
- x64
configuration:
- Debug
- Release
environment:
matrix:
- CXX: clang-cl
CPP: latest
- CXX: cl
CPP: 17
- CXX: cl
CPP: latest
cache:
- C:\ninja-1.8.2
install:
- ps: |
if (![IO.File]::Exists("C:\ninja-1.8.2\ninja.exe")) {
Start-FileDownload 'https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-win.zip'
7z x -y ninja-win.zip -oC:\ninja-1.8.2
}
$env:PATH="C:\ninja-1.8.2;$env:PATH"
- for /f "tokens=1* delims=" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath') do call "%%i\VC\Auxiliary\Build\vcvarsall.bat" %PLATFORM%
- cmake --version
- ninja --version
- clang-cl --version
- cl /Bv || exit 0
build_script:
- mkdir build && cd build
- ps: |
$env:CC=$env:CXX
$env:HEADER_CHECK=0
if ($env:PLATFORM -eq "x64") {
if ($env:CONFIGURATION -eq "Debug") {
$env:HEADER_CHECK=1
}
} elseif ($env:CXX -eq "clang-cl") {
$env:CXXFLAGS='-m32'
$env:CFLAGS='-m32'
}
- cmake .. -G Ninja -Wdev -DRANGE_V3_HEADER_CHECKS=%HEADER_CHECK% -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DRANGES_CXX_STD=%CPP%
- ninja
test_script:
- ctest -j2 --output-on-failure
deploy: off

View File

@ -1,79 +0,0 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"/Users/eniebler/llvm-install/include/c++/v1",
"/usr/local/include",
"/Users/eniebler/llvm-install/lib/clang/6.0.0/include",
"/usr/include",
"${workspaceRoot}/include",
"/usr/local/opt/boost@1.67/incluse"
],
"defines": [],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/Users/eniebler/llvm-install/include/c++/v1",
"/usr/local/include",
"/Users/eniebler/llvm-install/lib/clang/6.0.0/include",
"/usr/include",
"${workspaceRoot}/include",
"/usr/local/opt/boost@1.67/incluse"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"macFrameworkPath": [
"/System/Library/Frameworks",
"/Library/Frameworks"
],
"compilerPath": "/Users/eniebler/llvm-install/bin/clang++",
"cStandard": "c11",
"cppStandard": "c++11",
"configurationProvider": "vector-of-bool.cmake-tools"
},
{
"name": "Linux",
"includePath": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}/include"
],
"defines": [],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}/include"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"cStandard": "c11",
"cppStandard": "c++11"
},
{
"name": "Win32",
"includePath": [
"${workspaceRoot}/include"
],
"defines": [
"_DEBUG",
"UNICODE"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"${workspaceRoot}/include"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"cStandard": "c11",
"cppStandard": "c++11"
}
],
"version": 4
}

View File

@ -1,128 +0,0 @@
# Copyright Louis Dionne 2013-2017
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#
#
# This CMake module provides a function generating a unit test to make sure
# that every public header can be included on its own.
#
# When a C++ library or application has many header files, it can happen that
# a header does not include all the other headers it depends on. When this is
# the case, it can happen that including that header file on its own will
# break the compilation. This CMake module generates a dummy executable
# comprised of many .cpp files, each of which includes a header file that
# is part of the public API. In other words, the executable is comprised
# of .cpp files of the form:
#
# #include <the/public/header.hpp>
#
# and then exactly one `main` function. If this succeeds to compile, it means
# that the header can be included on its own, which is what clients expect.
# Otherwise, you have a problem. Since writing these dumb unit tests by hand
# is tedious and repetitive, you can use this CMake module to automate this
# task.
# add_header_test(<target> [EXCLUDE_FROM_ALL] [EXCLUDE excludes...] HEADERS headers...)
#
# Generates header-inclusion unit tests for all the specified headers.
#
# This function creates a target which builds a dummy executable including
# each specified header file individually. If this target builds successfully,
# it means that all the specified header files can be included individually.
#
# Parameters
# ----------
# <target>:
# The name of the target to generate.
#
# HEADERS headers:
# A list of header files to generate the inclusion tests for. All headers
# in this list must be represented as relative paths from the root of the
# include directory added to the compiler's header search path. In other
# words, it should be possible to include all headers in this list as
#
# #include <${header}>
#
# For example, for a library with the following structure:
#
# project/
# doc/
# test/
# ...
# include/
# boost/
# hana.hpp
# hana/
# transform.hpp
# tuple.hpp
# pair.hpp
# ...
#
# When building the unit tests for that library, we'll add `-I project/include'
# to the compiler's arguments. The list of public headers should therefore contain
#
# boost/hana.hpp
# boost/hana/transform.hpp
# boost/hana/tuple.hpp
# boost/hana/pair.hpp
# ...
#
# Usually, all the 'public' header files of a library should be tested for
# standalone inclusion. A header is considered 'public' if a client should
# be able to include that header on its own.
#
# [EXCLUDE excludes]:
# An optional list of headers or regexes for which no unit test should be
# generated. Basically, any header in the list specified by the `HEADERS`
# argument that matches anything in `EXCLUDE` will be skipped.
#
# [EXCLUDE_FROM_ALL]:
# If provided, the generated target is excluded from the 'all' target.
#
function(add_header_test target)
cmake_parse_arguments(ARGS "EXCLUDE_FROM_ALL" # options
"" # 1 value args
"HEADERS;EXCLUDE" # multivalued args
${ARGN})
if (NOT ARGS_HEADERS)
message(FATAL_ERROR "The `HEADERS` argument must be provided.")
endif()
if (ARGS_EXCLUDE_FROM_ALL)
set(ARGS_EXCLUDE_FROM_ALL "EXCLUDE_FROM_ALL")
else()
set(ARGS_EXCLUDE_FROM_ALL "")
endif()
foreach(header ${ARGS_HEADERS})
set(skip FALSE)
foreach(exclude ${ARGS_EXCLUDE})
if (${header} MATCHES ${exclude})
set(skip TRUE)
break()
endif()
endforeach()
if (skip)
continue()
endif()
get_filename_component(filename "${header}" NAME_WE)
get_filename_component(directory "${header}" DIRECTORY)
set(source "${CMAKE_CURRENT_BINARY_DIR}/headers/${directory}/${filename}.cpp")
if (NOT EXISTS "${source}")
file(WRITE "${source}" "#include <${header}>")
endif()
list(APPEND sources "${source}")
endforeach()
set(standalone_main "${CMAKE_CURRENT_BINARY_DIR}/headers/_standalone_main.cpp")
if (NOT EXISTS "${standalone_main}")
file(WRITE "${standalone_main}" "int main() { }")
endif()
add_executable(${target}
${ARGS_EXCLUDE_FROM_ALL}
${sources}
"${CMAKE_CURRENT_BINARY_DIR}/headers/_standalone_main.cpp"
)
endfunction()

View File

@ -1,6 +0,0 @@
#include <new>
int main() {
struct alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 4) S {};
(void) ::operator new(sizeof(S), static_cast<std::align_val_t>(alignof(S)));
}

View File

@ -1,19 +0,0 @@
template<class>
concept bool True = true;
template<class T>
constexpr bool test(T)
{
return false;
}
template<True T>
constexpr bool test(T)
{
return true;
}
int main()
{
static_assert(::test(42), "");
}

View File

@ -1,34 +0,0 @@
#include <experimental/coroutine>
struct present
{
struct promise_type
{
int result;
present get_return_object() { return {*this}; }
std::experimental::suspend_never initial_suspend() { return {}; }
std::experimental::suspend_never final_suspend() { return {}; }
void return_value(int i) { result = i; }
void unhandled_exception() {}
};
promise_type& promise;
bool await_ready() const { return true; }
void await_suspend(std::experimental::coroutine_handle<>) const {}
int await_resume() const { return promise.result; }
};
present f(int n)
{
if (n < 2)
co_return 1;
else
co_return n * co_await f(n - 1);
}
int main()
{
return f(5).promise.result != 120;
}

View File

@ -1,43 +0,0 @@
# Copyright Louis Dionne 2015
# Copyright Gonzalo Brito Gadeschi 2015
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#
# Setup compiler flags (more can be set on a per-target basis or in
# subdirectories)
# Enable all warnings:
ranges_append_flag(RANGES_HAS_WEVERYTHING -Weverything)
ranges_append_flag(RANGES_HAS_PEDANTIC -pedantic)
ranges_append_flag(RANGES_HAS_PEDANTIC_ERRORS -pedantic-errors)
# Selectively disable those warnings that are not worth it:
ranges_append_flag(RANGES_HAS_WNO_CXX98_COMPAT -Wno-c++98-compat)
ranges_append_flag(RANGES_HAS_WNO_CXX98_COMPAT_PEDANTIC -Wno-c++98-compat-pedantic)
ranges_append_flag(RANGES_HAS_WNO_WEAK_VTABLES -Wno-weak-vtables)
ranges_append_flag(RANGES_HAS_WNO_PADDED -Wno-padded)
ranges_append_flag(RANGES_HAS_WNO_MISSING_PROTOTYPES -Wno-missing-prototypes)
ranges_append_flag(RANGES_HAS_WNO_MISSING_VARIABLE_DECLARATIONS -Wno-missing-variable-declarations)
ranges_append_flag(RANGES_HAS_WNO_DOCUMENTATION -Wno-documentation)
ranges_append_flag(RANGES_HAS_WNO_DOCUMENTATION_UNKNOWN_COMMAND -Wno-documentation-unknown-command)
ranges_append_flag(RANGES_HAS_WNO_OLD_STYLE_CAST -Wno-old-style-cast)
if (RANGES_ENV_MACOSX)
ranges_append_flag(RANGES_HAS_WNO_GLOBAL_CONSTRUCTORS -Wno-global-constructors)
ranges_append_flag(RANGES_HAS_WNO_EXIT_TIME_DESTRUCTORS -Wno-exit-time-destructors)
endif()
if (RANGES_CXX_COMPILER_GCC)
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "6.0")
ranges_append_flag(RANGES_HAS_WNO_STRICT_OVERFLOW -Wno-strict-overflow)
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0")
ranges_append_flag(RANGES_HAS_WNO_MISSING_FIELD_INITIALIZERS -Wno-missing-field-initializers)
endif()
elseif ((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "7.0") OR (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "7.0"))
ranges_append_flag(RANGES_HAS_WNO_NOEXCEPT_TYPE -Wno-noexcept-type)
endif()
endif()
if (RANGES_VERBOSE_BUILD)
message(STATUS "[range-v3]: test C++ flags: ${CMAKE_CXX_FLAGS}")
endif()

View File

@ -1,94 +0,0 @@
# Copyright Gonzalo Brito Gadeschi 2015
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#
# Detects the C++ compiler, system, build-type, etc.
include(CheckCXXCompilerFlag)
if("x${CMAKE_CXX_COMPILER_ID}" MATCHES "x.*Clang")
if("x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
set (RANGES_CXX_COMPILER_CLANGCL TRUE)
if (RANGES_VERBOSE_BUILD)
message(STATUS "[range-v3]: compiler is clang-cl.")
endif()
else()
set (RANGES_CXX_COMPILER_CLANG TRUE)
if (RANGES_VERBOSE_BUILD)
message(STATUS "[range-v3]: compiler is clang.")
endif()
endif()
elseif(CMAKE_COMPILER_IS_GNUCXX)
set (RANGES_CXX_COMPILER_GCC TRUE)
if (RANGES_VERBOSE_BUILD)
message(STATUS "[range-v3]: compiler is gcc.")
endif()
elseif("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC")
set (RANGES_CXX_COMPILER_MSVC TRUE)
if (RANGES_VERBOSE_BUILD)
message(STATUS "[range-v3]: compiler is msvc.")
endif()
else()
message(WARNING "[range-v3 warning]: unknown compiler ${CMAKE_CXX_COMPILER_ID} !")
endif()
if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
set (RANGES_ENV_MACOSX TRUE)
if (RANGES_VERBOSE_BUILD)
message(STATUS "[range-v3]: system is MacOSX.")
endif()
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
set (RANGES_ENV_LINUX TRUE)
if (RANGES_VERBOSE_BUILD)
message(STATUS "[range-v3]: system is Linux.")
endif()
elseif(CMAKE_SYSTEM_NAME MATCHES "Windows")
set (RANGES_ENV_WINDOWS TRUE)
if (RANGES_VERBOSE_BUILD)
message(STATUS "[range-v3]: system is Windows.")
endif()
else()
message(WARNING "[range-v3 warning]: unknown system ${CMAKE_SYSTEM_NAME} !")
endif()
if (RANGES_CXX_COMPILER_MSVC AND RANGES_CXX_STD LESS 17)
# MSVC is currently supported only in 17+ mode
set(RANGES_CXX_STD 17)
elseif(RANGES_CXX_STD LESS 14)
set(RANGES_CXX_STD 14)
endif()
# Build type
set(RANGES_DEBUG_BUILD FALSE)
set(RANGES_RELEASE_BUILD FALSE)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(RANGES_DEBUG_BUILD TRUE)
if (RANGES_VERBOSE_BUILD)
message(STATUS "[range-v3]: build type is debug.")
endif()
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
set(RANGES_RELEASE_BUILD TRUE)
if (RANGES_VERBOSE_BUILD)
message(STATUS "[range-v3]: build type is release.")
endif()
else()
message(WARNING "[range-v3 warning]: unknown build type, defaults to release!")
set(CMAKE_BUILD_TYPE "Release")
set(RANGES_RELEASE_BUILD TRUE)
endif()
# Find Valgrind
find_program(MEMORYCHECK_COMMAND valgrind)
if(MEMORYCHECK_COMMAND)
set(MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full")
if (RANGES_VERBOSE_BUILD)
message(STATUS "[range-v3]: valgrind found at path: ${MEMORYCHECK_COMMAND}")
endif()
else()
if (RANGES_VERBOSE_BUILD)
message(WARNING "[range-v3 warning]: valgrind not found!")
endif()
endif()
find_package(Doxygen)
find_package(Git)

View File

@ -1,247 +0,0 @@
# Copyright Louis Dionne 2015
# Copyright Gonzalo Brito Gadeschi 2015
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#
# Setup compiler flags (more can be set on a per-target basis or in
# subdirectories)
# Compilation flags
include(CheckCXXCompilerFlag)
macro(ranges_append_flag testname flag)
# As -Wno-* flags do not lead to build failure when there are no other
# diagnostics, we check positive option to determine their applicability.
# Of course, we set the original flag that is requested in the parameters.
string(REGEX REPLACE "^-Wno-" "-W" alt ${flag})
check_cxx_compiler_flag(${alt} ${testname})
if (${testname})
add_compile_options(${flag})
endif()
endmacro()
# All compilation flags
# Language flag: version of the C++ standard to use
message(STATUS "[range-v3]: C++ std=${RANGES_CXX_STD}")
if (RANGES_CXX_COMPILER_CLANGCL OR RANGES_CXX_COMPILER_MSVC)
ranges_append_flag(RANGES_HAS_CXXSTDCOLON "/std:c++${RANGES_CXX_STD}")
set(RANGES_STD_FLAG "/std:c++${RANGES_CXX_STD}")
if (RANGES_CXX_COMPILER_CLANGCL)
ranges_append_flag(RANGES_HAS_FNO_MS_COMPATIBIILITY "-fno-ms-compatibility")
ranges_append_flag(RANGES_HAS_FNO_DELAYED_TEMPLATE_PARSING "-fno-delayed-template-parsing")
endif()
# Enable "normal" warnings and make them errors:
ranges_append_flag(RANGES_HAS_W3 /W3)
ranges_append_flag(RANGES_HAS_WX /WX)
else()
ranges_append_flag(RANGES_HAS_CXXSTD "-std=c++${RANGES_CXX_STD}")
set(RANGES_STD_FLAG "-std=c++${RANGES_CXX_STD}")
# Enable "normal" warnings and make them errors:
ranges_append_flag(RANGES_HAS_WALL -Wall)
ranges_append_flag(RANGES_HAS_WEXTRA -Wextra)
ranges_append_flag(RANGES_HAS_WERROR -Werror)
endif()
if (RANGES_ENV_LINUX AND RANGES_CXX_COMPILER_CLANG)
# On linux libc++ re-exports the system math headers. The ones from libstdc++
# use the GCC __extern_always_inline intrinsic which is not supported by clang
# versions 3.6, 3.7, 3.8, 3.9, 4.0, and current trunk 5.0 (as of 2017.04.13).
#
# This works around it by replacing __extern_always_inline with inline using a
# macro:
ranges_append_flag(RANGES_HAS_D__EXTERN_ALWAYS_INLINE -D__extern_always_inline=inline)
endif()
# Deep integration support
if (RANGES_DEEP_STL_INTEGRATION)
if (RANGES_CXX_COMPILER_MSVC)
add_compile_options(/I "${PROJECT_SOURCE_DIR}/include/std")
else()
add_compile_options(-isystem "${PROJECT_SOURCE_DIR}/include/std")
endif()
add_compile_options(-DRANGES_DEEP_STL_INTEGRATION=1)
endif()
# Template diagnostic flags
ranges_append_flag(RANGES_HAS_FDIAGNOSTIC_SHOW_TEMPLATE_TREE -fdiagnostics-show-template-tree)
ranges_append_flag(RANGES_HAS_FTEMPLATE_BACKTRACE_LIMIT "-ftemplate-backtrace-limit=0")
ranges_append_flag(RANGES_HAS_FMACRO_BACKTRACE_LIMIT "-fmacro-backtrace-limit=1")
# Clang modules support
if (RANGES_MODULES)
ranges_append_flag(RANGES_HAS_MODULES -fmodules)
ranges_append_flag(RANGES_HAS_MODULE_MAP_FILE "-fmodule-map-file=${PROJECT_SOURCE_DIR}/include/module.modulemap")
ranges_append_flag(RANGES_HAS_MODULE_CACHE_PATH "-fmodules-cache-path=${PROJECT_BINARY_DIR}/module.cache")
if (RANGES_LIBCXX_MODULE)
ranges_append_flag(RANGES_HAS_LIBCXX_MODULE_MAP_FILE "-fmodule-map-file=${RANGES_LIBCXX_MODULE}")
endif()
if (RANGES_ENV_MACOSX)
ranges_append_flag(RANGES_HAS_NO_IMPLICIT_MODULE_MAPS -fno-implicit-module-maps)
endif()
if (RANGES_DEBUG_BUILD)
ranges_append_flag(RANGES_HAS_GMODULES -gmodules)
endif()
endif()
# Sanitizer support: detect incompatible sanitizer combinations
if (RANGES_ASAN AND RANGES_MSAN)
message(FATAL_ERROR "[range-v3 error]: AddressSanitizer and MemorySanitizer are both enabled at the same time!")
endif()
if (RANGES_MSAN AND RANGES_ENV_MACOSX)
message(FATAL_ERROR "[range-v3 error]: MemorySanitizer is not supported on MacOSX!")
endif()
# AddressSanitizer support
if (RANGES_ASAN)
# This policy enables passing the linker flags to the linker when trying to
# test the features, which is required to successfully link ASan binaries
cmake_policy(SET CMP0056 NEW)
set (ASAN_FLAGS "")
if (RANGES_ENV_MACOSX) # LeakSanitizer not supported on MacOSX
set (ASAN_FLAGS "-fsanitize=address,signed-integer-overflow,shift,integer-divide-by-zero,implicit-signed-integer-truncation,implicit-integer-sign-change,undefined,nullability")
else()
if (RANGES_CXX_COMPILER_CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.0")
set (ASAN_FLAGS "-fsanitize=address")
else()
set (ASAN_FLAGS "-fsanitize=address,signed-integer-overflow,shift,integer-divide-by-zero,implicit-signed-integer-truncation,implicit-integer-sign-change,leak,nullability")
endif()
endif()
ranges_append_flag(RANGES_HAS_ASAN "${ASAN_FLAGS}")
if (RANGES_HAS_ASAN) #ASAN flags must be passed to the linker:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${ASAN_FLAGS}")
endif()
ranges_append_flag(RANGES_HAS_SANITIZE_NO_RECOVER "-fno-sanitize-recover=all")
ranges_append_flag(RANGES_HAS_NO_OMIT_FRAME_POINTER -fno-omit-frame-pointer)
endif()
# MemorySanitizer support
if (RANGES_MSAN)
# This policy enables passing the linker flags to the linker when trying to
# compile the examples, which is required to successfully link MSan binaries
cmake_policy(SET CMP0056 NEW)
ranges_append_flag(RANGES_HAS_MSAN "-fsanitize=memory")
ranges_append_flag(RANGES_HAS_MSAN_TRACK_ORIGINS -fsanitize-memory-track-origins)
ranges_append_flag(RANGES_HAS_SANITIZE_RECOVER_ALL "-fno-sanitize-recover=all")
ranges_append_flag(RANGES_HAS_NO_OMIT_FRAME_POINTER -fno-omit-frame-pointer)
endif()
# Build types:
if (RANGES_DEBUG_BUILD AND RANGES_RELEASE_BUILD)
message(FATAL_ERROR "[range-v3 error] Cannot simultaneously generate debug and release builds!")
endif()
if (RANGES_DEBUG_BUILD)
ranges_append_flag(RANGES_HAS_O0 -O0)
ranges_append_flag(RANGES_HAS_NO_INLINE -fno-inline)
ranges_append_flag(RANGES_HAS_STACK_PROTECTOR_ALL -fstack-protector-all)
ranges_append_flag(RANGES_HAS_G3 -g3)
# Clang can generate debug info tuned for LLDB or GDB
if (RANGES_CXX_COMPILER_CLANG)
if (RANGES_ENV_MACOSX)
ranges_append_flag(RANGES_HAS_GLLDB -glldb)
elseif(RANGES_ENV_LINUX)
ranges_append_flag(RANGES_HAS_GGDB -ggdb)
endif()
endif()
endif()
if (RANGES_RELEASE_BUILD)
if (NOT RANGES_ASSERTIONS)
ranges_append_flag(RANGES_HAS_DNDEBUG -DNDEBUG)
endif()
if (NOT RANGES_ASAN AND NOT RANGES_MSAN)
# The quality of ASan and MSan error messages suffers if we disable the
# frame pointer, so leave it enabled when compiling with either of them:
ranges_append_flag(RANGES_HAS_OMIT_FRAME_POINTER -fomit-frame-pointer)
endif()
ranges_append_flag(RANGES_HAS_OFAST -Ofast)
if (NOT RANGES_HAS_OFAST)
ranges_append_flag(RANGES_HAS_O2 -O2)
endif()
ranges_append_flag(RANGES_HAS_STRICT_ALIASING -fstrict-aliasing)
ranges_append_flag(RANGES_HAS_STRICT_VTABLE_POINTERS -fstrict-vtable-pointers)
ranges_append_flag(RANGES_HAS_FAST_MATH -ffast-math)
ranges_append_flag(RANGES_HAS_VECTORIZE -fvectorize)
if (NOT RANGES_ENV_MACOSX)
# Sized deallocation is not available in MacOSX:
ranges_append_flag(RANGES_HAS_SIZED_DEALLOCATION -fsized-deallocation)
endif()
if (RANGES_LLVM_POLLY)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mllvm -polly -mllvm -polly-vectorizer=stripmine")
endif()
if (RANGES_CXX_COMPILER_CLANG AND (NOT (RANGES_INLINE_THRESHOLD EQUAL -1)))
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mllvm -inline-threshold=${RANGES_INLINE_THRESHOLD}")
endif()
endif()
if (RANGES_NATIVE)
ranges_append_flag(RANGES_HAS_MARCH_NATIVE "-march=native")
ranges_append_flag(RANGES_HAS_MTUNE_NATIVE "-mtune=native")
endif()
include(CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_FLAGS ${RANGES_STD_FLAG})
# Probe for library and compiler support for aligned new
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/aligned_new_probe.cpp" RANGE_V3_PROBE_CODE)
check_cxx_source_compiles("${RANGE_V3_PROBE_CODE}" RANGE_V3_ALIGNED_NEW_PROBE)
unset(RANGE_V3_PROBE_CODE)
unset(CMAKE_REQUIRED_FLAGS)
if (NOT RANGE_V3_ALIGNED_NEW_PROBE)
add_compile_options("-DRANGES_CXX_ALIGNED_NEW=0")
endif()
# Probe for coroutine TS support
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/coro_test_code.cpp" RANGE_V3_PROBE_CODE)
if(RANGES_CXX_COMPILER_MSVC)
set(CMAKE_REQUIRED_FLAGS "/await")
check_cxx_source_compiles("${RANGE_V3_PROBE_CODE}" RANGES_HAS_AWAIT)
if(RANGES_HAS_AWAIT)
set(RANGE_V3_COROUTINE_FLAGS "/await")
endif()
elseif(RANGES_CXX_COMPILER_CLANG)
set(CMAKE_REQUIRED_FLAGS "-fcoroutines-ts ${RANGES_STD_FLAG}")
check_cxx_source_compiles("${RANGE_V3_PROBE_CODE}" RANGES_HAS_FCOROUTINES_TS)
if(RANGES_HAS_FCOROUTINES_TS)
set(RANGE_V3_COROUTINE_FLAGS "-fcoroutines-ts")
endif()
endif()
unset(CMAKE_REQUIRED_FLAGS)
unset(RANGE_V3_PROBE_CODE)
if (RANGE_V3_COROUTINE_FLAGS)
add_compile_options(${RANGE_V3_COROUTINE_FLAGS})
endif()
# Test for concepts support
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/concepts_test_code.cpp" RANGE_V3_PROBE_CODE)
if(RANGES_CXX_COMPILER_GCC OR RANGES_CXX_COMPILER_CLANG)
set(CMAKE_REQUIRED_FLAGS "-fconcepts ${RANGES_STD_FLAG}")
check_cxx_source_compiles("${RANGE_V3_PROBE_CODE}" RANGE_V3_HAS_FCONCEPTS)
if(RANGE_V3_HAS_FCONCEPTS)
set(RANGE_V3_CONCEPTS_FLAGS "-fconcepts")
endif()
endif()
unset(CMAKE_REQUIRED_FLAGS)
unset(RANGE_V3_PROBE_CODE)
if (RANGE_V3_CONCEPTS_FLAGS AND RANGES_PREFER_REAL_CONCEPTS)
add_compile_options(${RANGE_V3_CONCEPTS_FLAGS})
endif()
if (RANGES_VERBOSE_BUILD)
message(STATUS "[range-v3]: C++ flags: ${CMAKE_CXX_FLAGS}")
message(STATUS "[range-v3]: C++ debug flags: ${CMAKE_CXX_FLAGS_DEBUG}")
message(STATUS "[range-v3]: C++ Release Flags: ${CMAKE_CXX_FLAGS_RELEASE}")
message(STATUS "[range-v3]: C++ Compile Flags: ${CMAKE_CXX_COMPILE_FLAGS}")
message(STATUS "[range-v3]: Compile options: ${COMPILE_OPTIONS_}")
message(STATUS "[range-v3]: C Flags: ${CMAKE_C_FLAGS}")
message(STATUS "[range-v3]: C Compile Flags: ${CMAKE_C_COMPILE_FLAGS}")
message(STATUS "[range-v3]: EXE Linker flags: ${CMAKE_EXE_LINKER_FLAGS}")
message(STATUS "[range-v3]: C++ Linker flags: ${CMAKE_CXX_LINK_FLAGS}")
message(STATUS "[range-v3]: MODULE Linker flags: ${CMAKE_MODULE_LINKER_FLAGS}")
get_directory_property(CMakeCompDirDefs COMPILE_DEFINITIONS)
message(STATUS "[range-v3]: Compile Definitions: ${CmakeCompDirDefs}")
endif()

View File

@ -1,56 +0,0 @@
# Copyright Gonzalo Brito Gadeschi 2015
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#
# CMake options
include(CMakeDependentOption)
set(RANGES_CXX_STD 14 CACHE STRING "C++ standard version.")
option(RANGES_BUILD_CALENDAR_EXAMPLE "Builds the calendar example." ON)
option(RANGES_ASAN "Run the tests using AddressSanitizer." OFF)
option(RANGES_MSAN "Run the tests using MemorySanitizer." OFF)
option(RANGES_ASSERTIONS "Enable assertions." ON)
option(RANGES_DEBUG_INFO "Include debug information in the binaries." ON)
option(RANGES_MODULES "Enables use of Clang modules (experimental)." OFF)
option(RANGES_NATIVE "Enables -march/-mtune=native." ON)
option(RANGES_VERBOSE_BUILD "Enables debug output from CMake." OFF)
option(RANGES_LLVM_POLLY "Enables LLVM Polly." OFF)
option(RANGES_PREFER_REAL_CONCEPTS
"Use real concepts instead of emulation if the compiler supports it"
ON)
option(RANGES_DEEP_STL_INTEGRATION
"Hijacks the primary std::iterator_traits template to emulate the C++20 std::ranges:: behavior."
OFF)
option(RANGE_V3_HEADER_CHECKS
"Build the Range-v3 header checks and integrate with ctest"
OFF)
set(RANGES_INLINE_THRESHOLD -1 CACHE STRING "Force a specific inlining threshold.")
# Enable verbose configure when passing -Wdev to CMake
if (DEFINED CMAKE_SUPPRESS_DEVELOPER_WARNINGS AND
NOT CMAKE_SUPPRESS_DEVELOPER_WARNINGS)
set(RANGES_VERBOSE_BUILD ON)
endif()
if (RANGES_VERBOSE_BUILD)
message(STATUS "[range-v3]: verbose build enabled.")
endif()
CMAKE_DEPENDENT_OPTION(RANGE_V3_TESTS
"Build the Range-v3 tests and integrate with ctest"
ON "${is_standalone}" OFF)
CMAKE_DEPENDENT_OPTION(RANGE_V3_EXAMPLES
"Build the Range-v3 examples and integrate with ctest"
ON "${is_standalone}" OFF)
CMAKE_DEPENDENT_OPTION(RANGE_V3_PERF
"Build the Range-v3 performance benchmarks"
ON "${is_standalone}" OFF)
CMAKE_DEPENDENT_OPTION(RANGE_V3_DOCS
"Build the Range-v3 documentation"
ON "${is_standalone}" OFF)
mark_as_advanced(RANGE_V3_PERF)

View File

@ -1,5 +0,0 @@
# CMake files overview:
- `ranges_options.cmake`: All options to configure the library.
- `ranges_env.cmake`: Detects the environment: operating system, compiler, build-type, ...
- `ranges_flags.cmake`: Sets up all compiler flags.

View File

@ -1,35 +0,0 @@
# Range v3 library
#
# Copyright Luis Martinez de Bartolome Izquierdo 2016
#
# Use, modification and distribution is subject to the
# Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# Project home: https://github.com/ericniebler/range-v3
#
from conans import ConanFile, CMake
class Rangev3Conan(ConanFile):
name = "range-v3"
version = "0.9.0"
license = "Boost Software License - Version 1.0 - August 17th, 2003"
url = "https://github.com/ericniebler/range-v3"
description = """Experimental range library for C++11/14/17"""
# No settings/options are necessary, this is header only
exports_sources = "include*", "LICENSE.txt", "CMakeLists.txt", "cmake/*", "Version.cmake", "version.hpp.in"
no_copy_source = True
def package(self):
cmake = CMake(self)
cmake.definitions["RANGE_V3_TESTS"] = "OFF"
cmake.definitions["RANGE_V3_EXAMPLES"] = "OFF"
cmake.definitions["RANGE_V3_PERF"] = "OFF"
cmake.definitions["RANGE_V3_DOCS"] = "OFF"
cmake.definitions["RANGE_V3_HEADER_CHECKS"] = "OFF"
cmake.configure()
cmake.install()
self.copy("LICENSE.txt", dst="licenses", ignore_case=True, keep_path=False)

View File

@ -1,87 +0,0 @@
#=============================================================================
# Setup the documentation
#=============================================================================
if (NOT DOXYGEN_FOUND)
message(STATUS
"Doxygen not found; the 'doc' and 'gh-pages.{clean,copy,update}' targets "
"will be unavailable.")
return()
endif()
set(CMAKE_FOLDER "doc")
configure_file(Doxyfile.in Doxyfile @ONLY)
add_custom_target(doc.check
COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile
COMMENT "Running Doxygen to validate the documentation"
VERBATIM
)
set_target_properties(doc.check
PROPERTIES FOLDER ${CMAKE_FOLDER}
)
# if (NOT TARGET benchmarks)
# message(STATUS
# "The 'benchmarks' target is not available; the 'doc' and "
# "'gh-pages.{clean,copy,update}' targets will be unavailable. "
# "The 'doc.check' target can still be used to generate the "
# "documentation to check for errors/warnings.")
# return()
# endif()
add_custom_target(doc
COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile
COMMENT "Generating API documentation with Doxygen"
# DEPENDS benchmarks
VERBATIM
)
set_target_properties(doc
PROPERTIES FOLDER ${CMAKE_FOLDER}
)
if (NOT GIT_FOUND)
message(STATUS
"Git was not found; the 'gh-pages.{clean,copy,update}' targets "
"will be unavailable.")
return()
endif()
add_custom_target(gh-pages.clean
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_LIST_DIR}/clean-gh-pages.cmake
COMMAND ${CMAKE_COMMAND} -E remove_directory search
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/gh-pages
COMMENT "Cleaning up doc/gh-pages"
VERBATIM
)
set_target_properties(gh-pages.clean
PROPERTIES FOLDER ${CMAKE_FOLDER}
)
add_custom_target(gh-pages.copy
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/html ${CMAKE_CURRENT_LIST_DIR}/gh-pages
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/gh-pages
COMMENT "Copying the documentation from ${CMAKE_CURRENT_BINARY_DIR}/html to doc/gh-pages"
DEPENDS doc gh-pages.clean
VERBATIM
)
set_target_properties(gh-pages.copy
PROPERTIES FOLDER ${CMAKE_FOLDER}
)
execute_process(
COMMAND ${GIT_EXECUTABLE} -C ${CMAKE_SOURCE_DIR} rev-parse --short HEAD
OUTPUT_VARIABLE RANGE_V3_GIT_SHORT_SHA
OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_custom_target(gh-pages.update
COMMAND ${GIT_EXECUTABLE} add --all .
COMMAND ${GIT_EXECUTABLE} commit -m "Update to ${RANGE_V3_GIT_SHORT_SHA}"
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/gh-pages
COMMENT "Updating the gh-pages branch with freshly built documentation"
DEPENDS gh-pages.copy
VERBATIM
)
set_target_properties(gh-pages.update
PROPERTIES FOLDER ${CMAKE_FOLDER}
)

View File

@ -1,174 +0,0 @@
PROJECT_NAME = "Range-v3"
PROJECT_BRIEF = "Range algorithms, views, and actions for the Standard Library"
PROJECT_LOGO =
PROJECT_NUMBER =
STRIP_FROM_PATH = @Range-v3_SOURCE_DIR@/include
BUILTIN_STL_SUPPORT = YES
STRIP_FROM_INC_PATH = @Range-v3_SOURCE_DIR@/include
ALIASES =
ENABLED_SECTIONS =
# Resources
OUTPUT_DIRECTORY =
INPUT = @Range-v3_SOURCE_DIR@/include \
@Range-v3_SOURCE_DIR@/doc/index.md \
@Range-v3_SOURCE_DIR@/doc/examples.md \
@Range-v3_SOURCE_DIR@/doc/release_notes.md
FILE_PATTERNS = *.hpp *.md
RECURSIVE = YES
EXCLUDE = @Range-v3_SOURCE_DIR@/include/range/v3/detail \
@Range-v3_SOURCE_DIR@/include/range/v3/algorithm/aux_ \
@Range-v3_SOURCE_DIR@/include/range/v3/algorithm/tagspec.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/at.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/back.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/begin_end.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/data.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/distance.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/empty.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/front.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/getlines.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/index.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/istream_range.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/iterator_range.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/range_access.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/range_concepts.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/range_traits.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/size.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/span.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/to_container.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/to_container.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/associated_types.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/basic_iterator.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/common_iterator.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/concepts.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/counted_iterator.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/dangling.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/functional.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/infinity.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/invoke.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/iterator_concepts.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/iterator_traits.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/iterator.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/nullptr_v.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/semiregular.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/tagged_pair.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/tagged_tuple.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/unreachable.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/utility/view_adaptor.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/view_adaptor.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/view_facade.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/view_interface.hpp \
@Range-v3_SOURCE_DIR@/include/range/v3/view/bounded.hpp
EXAMPLE_PATH = @Range-v3_SOURCE_DIR@/example \
@Range-v3_SOURCE_DIR@/test
EXAMPLE_RECURSIVE = YES
IMAGE_PATH = @Range-v3_BINARY_DIR@/image
WARN_IF_UNDOCUMENTED = NO
SHOW_GROUPED_MEMB_INC = YES
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
JAVADOC_AUTOBRIEF = YES
QT_AUTOBRIEF = YES
MULTILINE_CPP_IS_BRIEF = YES
INHERIT_DOCS = NO
SEPARATE_MEMBER_PAGES = NO
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = NO
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
# Generated formats
GENERATE_HTML = YES
GENERATE_LATEX = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST = YES
SHOW_USED_FILES = NO
SHOW_FILES = YES
SHOW_NAMESPACES = YES
LAYOUT_FILE = @Range-v3_SOURCE_DIR@/doc/layout.xml
CLASS_DIAGRAMS = YES
HAVE_DOT = NO
HIDE_UNDOC_RELATIONS = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = NO
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = YES
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = YES
ALPHABETICAL_INDEX = NO
COLS_IN_ALPHA_INDEX = 1
# Preprocessing
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH = @Range-v3_SOURCE_DIR@/include
INCLUDE_FILE_PATTERNS =
PREDEFINED = RANGES_DOXYGEN_INVOKED=1 \
META_DOXYGEN_INVOKED=1 \
CPP_DOXYGEN_INVOKED=1 \
"RANGES_INLINE_VARIABLE(T,N)=inline constexpr T N{};"
SKIP_FUNCTION_MACROS = NO
# Source browsing
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
VERBATIM_HEADERS = NO
# CLANG_ASSISTED_PARSING = NO
# CLANG_OPTIONS =
# HTML output
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 75 # 0 - 359
HTML_COLORSTYLE_SAT = 100 # 0 - 255
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = NO
HTML_DYNAMIC_SECTIONS = YES
HTML_INDEX_NUM_ENTRIES = 0 # Fully expand trees in the Indexes by default
DISABLE_INDEX = YES
GENERATE_TREEVIEW = YES
TREEVIEW_WIDTH = 270
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
SEARCHENGINE = YES
# Mathjax (HTML only)
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =

View File

@ -1,4 +0,0 @@
FILE(GLOB gh_files "*.html" "*.js" "*.css" "*.png")
IF( gh_files )
execute_process( COMMAND ${CMAKE_COMMAND} -E remove ${gh_files} )
ENDIF()

View File

@ -1,62 +0,0 @@
Examples
========
\section example-algorithms Examples: Algorithms
\subsection example-hello Hello, Ranges!
\snippet hello.cpp hello
\subsection example-any-all-none any_of, all_of, none_of
\snippet any_all_none_of.cpp any_all_none_of
\subsection example-count count
\snippet count.cpp count
\subsection example-count_if count_if
\snippet count_if.cpp count_if
\subsection example-find find, find_if, find_if_not on sequence containers
\snippet find.cpp find
\subsection example-for_each-seq for_each on sequence containers
\snippet for_each_sequence.cpp for_each_sequence
\subsection example-for_each-assoc for_each on associative containers
\snippet for_each_assoc.cpp for_each_assoc
\subsection example-is_sorted is_sorted
\snippet is_sorted.cpp is_sorted
\section example-views Examples: Views
\subsection example-filter-transform Filter and transform
\snippet filter_transform.cpp filter_transform
\subsection example-accumulate-ints Generate ints and accumulate
\snippet accumulate_ints.cpp accumulate_ints
\subsection example-comprehension-conversion Convert a range comprehension to a vector
\snippet comprehension_conversion.cpp comprehension_conversion
\section example-actions Examples: Actions
\subsection example-sort-unique Remove non-unique elements from a container
\snippet sort_unique.cpp sort_unique
\section example-gestalt Examples: Putting it all together
\subsection example-calendar Calendar
\snippet calendar.cpp calendar

View File

@ -1,950 +0,0 @@
User Manual {#mainpage}
===========
\tableofcontents
\section tutorial-preface Preface
--------------------------------------------
Range library for C++14/17/20. This code is the basis of [the range support in C++20](http://eel.is/c++draft/#ranges).
**Development Status:**
This code is fairly stable, well-tested, and suitable for casual use, although
currently lacking documentation. 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.
\subsection tutorial-installation Installation
--------------------------------------------
This library is header-only. You can get the source code from the
[range-v3 repository](https://github.com/ericniebler/range-v3) on github. To
compile with Range-v3, just `#include` the individual headers you want.
This distribution actually contains three separate header-only libraries:
* <strong><tt>include/concepts/...</tt></strong> contains the Concepts Portability Preprocessor, or
CPP, which is a set of macros for defining and using concept checks,
regardless of whether your compiler happens to support the C++20 concepts
language feature or not.
* <strong><tt>include/meta/...</tt></strong> contains the Meta Library, which is a set of
meta-programming utilities for processing types and lists of types at compile
time.
* <strong><tt>include/range/...</tt></strong> contains the Range-v3 library, as described below.
The Range-v3 library is physically structured in directories by feature group:
* <strong><tt>include/range/v3/actions/...</tt></strong> contains _actions_, or composable
components that operate eagerly on containers and return the mutated container
for further actions.
* <strong><tt>include/range/v3/algorithms/...</tt></strong> contains all the STL _algorithms_ with
overloads that accept ranges, in addition to the familiar overloads that take iterators.
* <strong><tt>include/range/v3/functional/...</tt></strong> contains many generally useful
components that would be familiar to functional programmers.
* <strong><tt>include/range/v3/iterator/...</tt></strong> contains the definitions of many useful
iterators and iterator-related concepts and utilities.
* <strong><tt>include/range/v3/numeric/...</tt></strong> contains numeric algorithms corresponding
to those found in the standard `<numeric>` header.
* <strong><tt>include/range/v3/range/...</tt></strong> contains range-related utilities, such as
`begin`, `end`, and `size`, range traits and concepts, and conversions to
containers.
* <strong><tt>include/range/v3/utility/...</tt></strong> contains a miscellaneous assortment of
reusable code.
* <strong><tt>include/range/v3/view/...</tt></strong> contains _views_, or composable
components that operate lazily on ranges and that themselves return ranges
that can be operated upon with additional view adaptors.
\subsection tutorial-license 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 acknowledgements.
\subsection tutorial-compilers Supported Compilers
--------------------------------------------------------------------------------
The code is known to work on the following compilers:
- clang 3.6.2
- GCC 5.0.2
- MSVC VS2017 15.9 (`_MSC_VER >= 1916`), with `/std:c++17 /permissive-`
\section tutorial-quick-start Quick Start
--------------------------------------------------------------------------------
Range-v3 is a generic library that augments the existing standard library with
facilities for working with *ranges*. A range can be loosely thought of a pair
of iterators, although they need not be implemented that way. Bundling begin/end
iterators into a single object brings several benefits: convenience,
composability, and correctness.
**Convenience**
It's more convenient to pass a single range object to an algorithm than separate
begin/end iterators. Compare:
~~~~~~~{.cpp}
std::vector<int> v{/*...*/};
std::sort( v.begin(), v.end() );
~~~~~~~
with
~~~~~~~{.cpp}
std::vector<int> v{/*...*/};
ranges::sort( v );
~~~~~~~
Range-v3 contains full implementations of all the standard algorithms with
range-based overloads for convenience.
**Composability**
Having a single range object permits *pipelines* of operations. In a pipeline, a
range is lazily adapted or eagerly mutated in some way, with the result
immediately available for further adaptation or mutation. Lazy adaption is
handled by *views*, and eager mutation is handled by *actions*.
For instance, the below uses _views_ to filter a container using a predicate
and transform the resulting range with a function. Note that the underlying
data is `const` and is not mutated by the views.
~~~~~~~{.cpp}
std::vector<int> const vi{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
using namespace ranges;
auto rng = vi | views::remove_if([](int i){ return i % 2 == 1; })
| views::transform([](int i){ return std::to_string(i); });
// rng == {"2","4","6","8","10"};
~~~~~~~
In the code above, `rng` simply stores a reference to the underlying data and
the filter and transformation functions. No work is done until `rng` is
iterated.
In contrast, _actions_ do their work eagerly, but they also compose. Consider
the code below, which reads some data into a vector, sorts it, and makes it
unique.
~~~~~~~{.cpp}
extern std::vector<int> read_data();
using namespace ranges;
std::vector<int> vi = read_data() | actions::sort | actions::unique;
~~~~~~~
Unlike views, with actions each step in the pipeline (`actions::sort` and
`actions::unique`) accepts a container _by value_, mutates it in place, and
returns it.
**Correctness**
Whether you are using views or actions, you are operating on data in a pure
functional, declarative style. You rarely need to trouble yourself with
iterators, although they are there under the covers should you need them.
By operating declaratively and functionally instead of imperatively, we reduce
the need for overt state manipulation and branches and loops. This brings down
the number of states your program can be in, which brings down your bug counts.
In short, if you can find a way to express your solution as a composition of
functional transformations on your data, you can make your code _correct by
construction_.
\subsection tutorial-views Views
--------------------------------------------------------------------------------
As described above, the big advantage of ranges over iterators is their
composability. They permit a functional style of programming where data is
manipulated by passing it through a series of combinators. In addition, the
combinators can be *lazy*, only doing work when the answer is requested, and
*purely functional*, without mutating the original data. This makes it easier to
reason about your code.
A _view_ is a lightweight wrapper that presents a view of an underlying sequence
of elements in some custom way without mutating or copying it. Views are cheap
to create and copy and have non-owning reference semantics. Below are some
examples that use views:
Filter a container using a predicate and transform it.
~~~~~~~{.cpp}
std::vector<int> const vi{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
using namespace ranges;
auto rng = vi | views::remove_if([](int i){return i % 2 == 1;})
| views::transform([](int i){return std::to_string(i);});
// rng == {"2","4","6","8","10"};
~~~~~~~
Generate an infinite list of integers starting at 1, square them, take the first
10, and sum them:
~~~~~~~{.cpp}
using namespace ranges;
int sum = accumulate(views::ints(1)
| views::transform([](int i){return i*i;})
| views::take(10), 0);
~~~~~~~
Generate a sequence on the fly with a range comprehension and initialize a
vector with it:
~~~~~~~{.cpp}
using namespace ranges;
auto vi =
views::for_each(views::ints(1, 10), [](int i) {
return yield_from(views::repeat_n(i, i));
})
| to<std::vector>();
// vi == {1,2,2,3,3,3,4,4,4,4,5,5,5,5,5,...}
~~~~~~~
### View const-ness
Logically, a view is a factory for iterators, but in practice a view is often
implemented as a state machine, with the state stored within the view object
itself (to keep iterators small) and mutated as the view is iterated. Because
the view contains mutable state, many views lack a `const`-qualified
`begin()`/`end()`. When `const` versions of `begin()`/`end()` are provided, they
are truly `const`; that is, thread-safe.
Since views present the same interface as containers, the temptation is to think
they behave like containers with regard to `const`-ness. This is not the case.
Their behavior with regards to `const`-ness is similar to iterators and
pointers.
The `const`-ness of a view is not related to the `const`-ness of the underlying
data. A non-`const` view may refer to elements that are themselves `const`, and
_vice versa_. This is analogous to pointers; an `int* const` is a `const`
pointer to a mutable `int`, and a `int const*` is a non-`const` pointer to a
`const` `int`.
Use non-`const` views whenever possible. If you need thread-safety, work with
view copies in threads; don't share.
### View validity
Any operation on the underlying range that invalidates its iterators or
sentinels will also invalidate any view that refers to any part of that range.
Additionally, some views (_e.g._, `views::filter`), are invalidated when the
underlying elements of the range are mutated. It is best to recreate a view
after any operation that may have mutated the underlying range.
### List of range views
Below is a list of the lazy range combinators, or views, that Range-v3
provides, and a blurb about how each is intended to be used.
<DL>
<DT>\link ranges::views::addressof_fn `views::addressof`\endlink</DT>
<DD>Given a source range of lvalue references, return a new view that is the result of taking `std::addressof` of each.</DD>
<DT>\link ranges::views::adjacent_filter_fn `views::adjacent_filter`\endlink</DT>
<DD>For each pair of adjacent elements in a source range, evaluate the specified binary predicate. If the predicate evaluates to false, the second element of the pair is removed from the result range; otherwise, it is included. The first element in the source range is always included. (For instance, `adjacent_filter` with `std::not_equal_to` filters out all the non-unique elements.)</DD>
<DT>\link ranges::views::adjacent_remove_if_fn `views::adjacent_remove_if`\endlink</DT>
<DD>For each pair of adjacent elements in a source range, evaluate the specified binary predicate. If the predicate evaluates to true, the first element of the pair is removed from the result range; otherwise, it is included. The last element in the source range is always included.</DD>
<DT>\link ranges::views::all_fn `views::all`\endlink</DT>
<DD>Return a range containing all the elements in the source. Useful for converting containers to ranges.</DD>
<DT>\link ranges::any_view `any_view<T>(rng)`\endlink</DT>
<DD>Type-erased range of elements with value type `T`; can store _any_ range with this value type.</DD>
<DT>\link ranges::views::c_str_fn `views::c_str`\endlink</DT>
<DD>View a `\0`-terminated C string (e.g. from a `const char*`) as a range.</DD>
<DT>\link ranges::views::cartesian_product_fn `views::cartesian_product`\endlink</DT>
<DD>Enumerates the n-ary cartesian product of `n` ranges, i.e., generates all `n`-tuples `(e1, e2, ... , en)` where `e1` is an element of the first range, `e2` is an element of the second range, etc.</DD>
<DT>\link ranges::views::chunk_fn `views::chunk`\endlink</DT>
<DD>Given a source range and an integer *N*, produce a range of contiguous ranges where each inner range has *N* contiguous elements. The final range may have fewer than *N* elements.</DD>
<DT>\link ranges::views::common_fn `views::common`\endlink</DT>
<DD>Convert the source range to a *common* range, where the type of the `end` is the same as the `begin`. Useful for calling algorithms in the `std::` namespace.</DD>
<DT>\link ranges::views::concat_fn `views::concat`\endlink</DT>
<DD>Given *N* source ranges, produce a result range that is the concatenation of all of them.</DD>
<DT>\link ranges::views::const_fn `views::const_`\endlink</DT>
<DD>Present a `const` view of a source range.</DD>
<DT>\link ranges::views::counted_fn `views::counted`\endlink</DT>
<DD>Given an iterator `it` and a count `n`, create a range that starts at `it` and includes the next `n` elements.</DD>
<DT>\link ranges::views::cycle_fn `views::cycle`\endlink</DT>
<DD>Returns an infinite range that endlessly repeats the source range.</DD>
<DT>\link ranges::views::delimit_fn `views::delimit`\endlink</DT>
<DD>Given a source range and a value, return a new range that ends either at the end of the source or at the first occurrence of the value, whichever comes first. Alternatively, `views::delimit` can be called with an iterator and a value, in which case it returns a range that starts at the specified position and ends at the first occurrence of the value.</DD>
<DT>\link ranges::views::drop_fn `views::drop`\endlink</DT>
<DD>Given a source range and an integral count, return a range consisting of all but the first *count* elements from the source range, or an empty range if it has fewer elements.</DD>
<DT>\link ranges::views::drop_last_fn `views::drop_last`\endlink</DT>
<DD>Given a source range and an integral count, return a range consisting of all but the last *count* elements from the source range, or an empty range if it has fewer elements.</DD>
<DT>\link ranges::views::drop_exactly_fn `views::drop_exactly`\endlink</DT>
<DD>Given a source range and an integral count, return a range consisting of all but the first *count* elements from the source range. The source range must have at least that many elements.</DD>
<DT>\link ranges::views::drop_while_fn `views::drop_while`\endlink</DT>
<DD>Remove elements from the front of a range that satisfy a unary predicate.</DD>
<DT>\link ranges::views::empty() `views::empty`\endlink</DT>
<DD>Create an empty range with a given value type.</DD>
<DT>\link ranges::views::enumerate() `views::enumerate`\endlink</DT>
<DD>Pair each element of a range with its index.</DD>
<DT>\link ranges::views::filter_fn `views::filter`\endlink</DT>
<DD>Given a source range and a unary predicate, filter the elements that satisfy the predicate. (For users of Boost.Range, this is like the `filter` adaptor.)</DD>
<DT>\link ranges::views::for_each_fn `views::for_each`\endlink</DT>
<DD>Lazily applies an unary function to each element in the source range that returns another range (possibly empty), flattening the result.</DD>
<DT>\link ranges::views::generate_fn `views::generate`\endlink</DT>
<DD>Given a nullary function, return an infinite range whose elements are generated with the function.</DD>
<DT>\link ranges::views::generate_n_fn `views::generate_n`\endlink</DT>
<DD>Given a nullary function and a count, return a range that generates the requested number of elements by calling the function.</DD>
<DT>\link ranges::views::group_by_fn `views::group_by`\endlink</DT>
<DD>Given a source range and a binary predicate, return a range of ranges where each range contains contiguous elements from the source range such that the following condition holds: for each element in the range apart from the first, when that element and the first element are passed to the binary predicate, the result is true. In essence, `views::group_by` *groups* contiguous elements together with a binary predicate.</DD>
<DT>\link ranges::views::indirect_fn `views::indirect`\endlink</DT>
<DD>Given a source range of readable values (e.g. pointers or iterators), return a new view that is the result of dereferencing each.</DD>
<DT>\link ranges::views::intersperse_fn `views::intersperse`\endlink</DT>
<DD>Given a source range and a value, return a new range where the value is inserted between contiguous elements from the source.</DD>
<DT>\link ranges::views::ints_fn `views::ints`\endlink</DT>
<DD>Generate a range of monotonically increasing `int`s. When used without arguments, it generates the quasi-infinite range [0,1,2,3...]. It can also be called with a lower bound, or with a lower and upper bound (exclusive). An inclusive version is provided by `closed_ints`.</DD>
<DT>\link ranges::views::iota_fn `views::iota`\endlink</DT>
<DD>A generalization of `views::ints` that generates a sequence of monotonically increasing values of any incrementable type. When specified with a single argument, the result is an infinite range beginning at the specified value. With two arguments, the values are assumed to denote a half-open range.</DD>
<DT>\link ranges::views::join_fn `views::join`\endlink</DT>
<DD>Given a range of ranges, join them into a flattened sequence of elements. Optionally, you can specify a value or a range to be inserted between each source range.</DD>
<DT>\link ranges::views::keys_fn `views::keys`\endlink</DT>
<DD>Given a range of `pair`s (like a `std::map`), return a new range consisting of just the first element of the `pair`.</DD>
<DT>\link ranges::views::linear_distribute_fn `views::linear_distribute`\endlink</DT>
<DD>Distributes `n` values linearly in the closed interval `[from, to]` (the end points are always included). If `from == to`, returns `n`-times `to`, and if `n == 1` it returns `to`.</DD>
<DT>\link ranges::views::move_fn `views::move`\endlink</DT>
<DD>Given a source range, return a new range where each element has been has been cast to an rvalue reference.</DD>
<DT>\link ranges::views::partial_sum_fn `views::partial_sum`\endlink</DT>
<DD>Given a range and a binary function, return a new range where the *N*<SUP>th</SUP> element is the result of applying the function to the *N*<SUP>th</SUP> element from the source range and the (N-1)th element from the result range.</DD>
<DT>\link ranges::views::remove_fn `views::remove`\endlink</DT>
<DD>Given a source range and a value, filter out those elements that do not equal value.</DD>
<DT>\link ranges::views::remove_if_fn `views::remove_if`\endlink</DT>
<DD>Given a source range and a unary predicate, filter out those elements that do not satisfy the predicate. (For users of Boost.Range, this is like the `filter` adaptor with the predicate negated.)</DD>
<DT>\link ranges::views::repeat_fn `views::repeat`\endlink</DT>
<DD>Given a value, create a range that is that value repeated infinitely.</DD>
<DT>\link ranges::views::repeat_n_fn `views::repeat_n`\endlink</DT>
<DD>Given a value and a count, create a range that is that value repeated *count* number of times.</DD>
<DT>\link ranges::views::replace_fn `views::replace`\endlink</DT>
<DD>Given a source range, a source value and a target value, create a new range where all elements equal to the source value are replaced with the target value.</DD>
<DT>\link ranges::views::replace_if_fn `views::replace_if`\endlink</DT>
<DD>Given a source range, a unary predicate and a target value, create a new range where all elements that satisfy the predicate are replaced with the target value.</DD>
<DT>\link ranges::views::reverse_fn `views::reverse`\endlink</DT>
<DD>Create a new range that traverses the source range in reverse order.</DD>
<DT>\link ranges::views::sample_fn `views::sample`\endlink</DT>
<DD>Returns a random sample of a range of length `size(range)`.</DD>
<DT>\link ranges::views::single_fn `views::single`\endlink</DT>
<DD>Given a value, create a range with exactly one element.</DD>
<DT>\link ranges::views::slice_fn `views::slice`\endlink</DT>
<DD>Give a source range a lower bound (inclusive) and an upper bound (exclusive), create a new range that begins and ends at the specified offsets. Both the begin and the end can be integers relative to the front, or relative to the end with "`end-2`" syntax.</DD>
<DT>\link ranges::views::sliding_fn `views::sliding`\endlink</DT>
<DD>Given a range and a count `n`, place a window over the first `n` elements of the underlying range. Return the contents of that window as the first element of the adapted range, then slide the window forward one element at a time until hitting the end of the underlying range.</DD>
<DT>\link ranges::views::split_fn `views::split`\endlink</DT>
<DD>Given a source range and a delimiter specifier, split the source range into a range of ranges using the delimiter specifier to find the boundaries. The delimiter specifier can be an element or a range of elements. The elements matching the delimiter are excluded from the resulting range of ranges.</DD>
<DT>\link ranges::views::split_when_fn `views::split_when`\endlink</DT>
<DD>Given a source range and a delimiter specifier, split the source range into a range of ranges using the delimiter specifier to find the boundaries. The delimiter specifier can be a predicate or a function. The predicate should take a single argument of the range's reference type and return `true` if and only if the element is part of a delimiter. The function should accept an iterator and sentinel indicating the current position and end of the source range and return `std::make_pair(true, iterator_past_the_delimiter)` if the current position is a boundary; otherwise `std::make_pair(false, ignored_iterator_value)`. The elements matching the delimiter are excluded from the resulting range of ranges.</DD>
<DT>\link ranges::views::stride_fn `views::stride`\endlink</DT>
<DD>Given a source range and an integral stride value, return a range consisting of every *N*<SUP>th</SUP> element, starting with the first.</DD>
<DT>\link ranges::views::tail_fn `views::tail`\endlink</DT>
<DD>Given a source range, return a new range without the first element. The range must have at least one element.</DD>
<DT>\link ranges::views::take_fn `views::take`\endlink</DT>
<DD>Given a source range and an integral count, return a range consisting of the first *count* elements from the source range, or the complete range if it has fewer elements. (The result of `views::take` is not a `sized_range`.)</DD>
<DT>\link ranges::views::take_exactly_fn `views::take_exactly`\endlink</DT>
<DD>Given a source range and an integral count, return a range consisting of the first *count* elements from the source range. The source range must have at least that many elements. (The result of `views::take_exactly` is a `sized_range`.)</DD>
<DT>\link ranges::views::take_last_fn `views::take_last`\endlink</DT>
<DD>Given a source range and an integral count, return a range consisting of the last *count* elements from the source range. The source range must be a `sized_range`. If the source range does not have at least *count* elements, the full range is returned.</DD>
<DT>\link ranges::views::take_while_fn `views::take_while`\endlink</DT>
<DD>Given a source range and a unary predicate, return a new range consisting of the elements from the front that satisfy the predicate.</DD>
<DT>\link ranges::views::tokenize_fn `views::tokenize`\endlink</DT>
<DD>Given a source range and optionally a submatch specifier and a `std::regex_constants::match_flag_type`, return a `std::regex_token_iterator` to step through the regex submatches of the source range. The submatch specifier may be either a plain `int`, a `std::vector<int>`, or a `std::initializer_list<int>`.</DD>
<DT>\link ranges::views::transform_fn `views::transform`\endlink</DT>
<DD>Given a source range and a unary function, return a new range where each result element is the result of applying the unary function to a source element.</DD>
<DT>\link ranges::views::trim_fn `views::trim`\endlink</DT>
<DD>Given a source bidirectional range and a unary predicate, return a new range without the front and back elements that satisfy the predicate.</DD>
<DT>\link ranges::views::unbounded_fn `views::unbounded`\endlink</DT>
<DD>Given an iterator, return an infinite range that begins at that position.</DD>
<DT>\link ranges::views::unique_fn `views::unique`\endlink</DT>
<DD>Given a range, return a new range where all consecutive elements that compare equal save the first have been filtered out.</DD>
<DT>\link ranges::views::values_fn `views::values`\endlink</DT>
<DD>Given a range of `pair`s (like a `std::map`), return a new range consisting of just the second element of the `pair`.</DD>
<DT>\link ranges::views::zip_fn `views::zip`\endlink</DT>
<DD>Given *N* ranges, return a new range where *M*<SUP>th</SUP> element is the result of calling `make_tuple` on the *M*<SUP>th</SUP> elements of all *N* ranges.</DD>
<DT>\link ranges::views::zip_with_fn `views::zip_with`\endlink</DT>
<DD>Given *N* ranges and a *N*-ary function, return a new range where *M*<SUP>th</SUP> element is the result of calling the function on the *M*<SUP>th</SUP> elements of all *N* ranges.</DD>
</DL>
\subsection tutorial-actions Actions
--------------------------------------------------------------
When you want to mutate a container in-place, or forward it through a chain of
mutating operations, you can use actions. The following examples should make it
clear.
Read data into a vector, sort it, and make it unique.
~~~~~~~{.cpp}
extern std::vector<int> read_data();
using namespace ranges;
std::vector<int> vi = read_data() | actions::sort | actions::unique;
~~~~~~~
Do the same to a `vector` that already contains some data:
~~~~~~~{.cpp}
vi = std::move(vi) | actions::sort | actions::unique;
~~~~~~~
Mutate the container in-place:
~~~~~~~{.cpp}
vi |= actions::sort | actions::unique;
~~~~~~~
Same as above, but with function-call syntax instead of pipe syntax:
~~~~~~~{.cpp}
actions::unique(actions::sort(vi));
~~~~~~~
### List of range actions
Below is a list of the eager range combinators, or actions, that Range-v3
provides, and a blurb about how each is intended to be used.
<DL>
<DT>\link ranges::actions::drop_fn `actions::drop`\endlink</DT>
<DD>Removes the first `N` elements of the source range.</DD>
<DT>\link ranges::actions::drop_while_fn `actions::drop_while`\endlink</DT>
<DD>Removes the first elements of the source range that satisfy the unary predicate.</DD>
<DT>`actions::erase`</DT>
<DD>Removes all elements in the sub-range of the source (range version) or all elements after position.</DD>
<DT>`actions::insert`</DT>
<DD>Inserts all elements of the range into the source at position.</DD>
<DT>\link ranges::actions::join_fn `actions::join`\endlink</DT>
<DD>Flattens a range of ranges.</DD>
<DT> `actions::push_back`</DT>
<DD>Appends elements to the tail of the source.</DD>
<DT>`actions::push_front`</DT>
<DD>Appends elements before the head of the source.</DD>
<DT>\link ranges::actions::remove_if_fn `actions::remove_if`\endlink</DT>
<DD>Removes all elements from the source that satisfy the predicate.</DD>
<DT>\link ranges::actions::remove_fn `actions::remove`\endlink</DT>
<DD>Removes all elements from the source that are equal to value.</DD>
<DT>\link ranges::actions::reverse_fn `actions::reverse`\endlink</DT>
<DD>Reverses all the elements in the container.</DD>
<DT>\link ranges::actions::shuffle_fn `actions::shuffle`\endlink</DT>
<DD>Shuffles the source range.</DD>
<DT>\link ranges::actions::slice_fn `actions::slice`\endlink</DT>
<DD>Removes all elements from the source that are not part of the sub-range.</DD>
<DT>\link ranges::actions::sort_fn `actions::sort`\endlink</DT>
<DD>Sorts the source range (unstable).</DD>
<DT>\link ranges::actions::split_fn `actions::split`\endlink</DT>
<DD>Split a range into a sequence of subranges using a delimiter (a value, a sequence of values, a predicate, or a binary function returning a `pair<bool, N>`).</DD>
<DT>\link ranges::actions::stable_sort_fn `actions::stable_sort`\endlink</DT>
<DD>Sorts the source range (stable).</DD>
<DT>\link ranges::actions::stride_fn `actions::stride`\endlink</DT>
<DD>Removes all elements whose position does not match the stride.</DD>
<DT>\link ranges::actions::take_fn `actions::take`\endlink</DT>
<DD>Keeps the first `N`-th elements of the range, removes the rest.</DD>
<DT>\link ranges::actions::take_while_fn `actions::take_while`\endlink</DT>
<DD>Keeps the first elements that satisfy the predicate, removes the rest.</DD>
<DT>\link ranges::actions::transform_fn `actions::transform`\endlink</DT>
<DD>Replaces elements of the source with the result of the unary function.</DD>
<DT>\link ranges::actions::unique_fn `actions::unique`\endlink</DT>
<DD>Removes adjacent elements of the source that compare equal. If the source is sorted, removes all duplicate elements.</DD>
<DT>\link ranges::actions::unstable_remove_if_fn `actions::unstable_remove_if`\endlink</DT>
<DD>Much faster (each element remove has constant time complexity), unordered version of `remove_if`. Requires bidirectional container.</DD>
</DL>
\subsection tutorial-utilities Utilities
----------------------------------------------
Below we cover some utilities that range-v3 provides for creating your own
view adaptors and iterators.
### Create Custom Views with view_facade
Range-v3 provides a utility for easily creating your own range types, called
\link ranges::view_facade `ranges::view_facade`\endlink. The code below uses
`view_facade` to create a range that traverses a null-terminated string:
~~~~~~~{.cpp}
#include <range/v3/all.hpp>
// A range that iterates over all the characters in a
// null-terminated string.
class c_string_range
: public ranges::view_facade<c_string_range>
{
friend ranges::range_access;
char const * sz_ = "";
char const & read() const { return *sz_; }
bool equal(ranges::default_sentinel_t) const { return *sz_ == '\0'; }
void next() { ++sz_; }
public:
c_string_range() = default;
explicit c_string_range(char const *sz) : sz_(sz)
{
assert(sz != nullptr);
}
};
~~~~~~~
The `view_facade` class generates an iterator and begin/end member functions
from the minimal interface provided by `c_string_range`. This is an example of a
very simple range for which it is not necessary to separate the range itself
from the thing that iterates the range. Future examples will show examples of
more sophisticated ranges.
With `c_string_range`, you can now use algorithms to operate on null-terminated
strings, as below:
~~~~~~~{.cpp}
#include <iostream>
int main()
{
c_string_range r("hello world");
// Iterate over all the characters and print them out
ranges::for_each(r, [](char ch){
std::cout << ch << ' ';
});
// prints: h e l l o w o r l d
}
~~~~~~~
### Create Custom Views with view_adaptor
Often, a new range type is most easily expressed by adapting an existing range
type. That's the case for many of the range views provided by the Range-v3
library; for example, the `views::remove_if` and `views::transform` views. These
are rich types with many moving parts, but thanks to a helper class called
\link ranges::view_adaptor `ranges::view_adaptor`\endlink, they aren't hard
to write.
Below in roughly 2 dozen lines of code is the `transform` view, which takes one
range and transforms all the elements with a unary function.
~~~~~~~{.cpp}
#include <range/v3/all.hpp>
// A class that adapts an existing range with a function
template<class Rng, class Fun>
class transform_view
: public ranges::view_adaptor<transform_view<Rng, Fun>, Rng>
{
friend ranges::range_access;
ranges::semiregular_box_t<Fun> fun_; // Make Fun model semiregular if it doesn't
class adaptor : public ranges::adaptor_base
{
ranges::semiregular_box_t<Fun> fun_;
public:
adaptor() = default;
adaptor(ranges::semiregular_box_t<Fun> const &fun) : fun_(fun) {}
// Here is where we apply Fun to the elements:
auto read(ranges::iterator_t<Rng> it) const -> decltype(fun_(*it))
{
return fun_(*it);
}
};
adaptor begin_adaptor() const { return {fun_}; }
adaptor end_adaptor() const { return {fun_}; }
public:
transform_view() = default;
transform_view(Rng && rng, Fun fun)
: transform_view::view_adaptor{std::forward<Rng>(rng)}
, fun_(std::move(fun))
{}
};
template<class Rng, class Fun>
transform_view<Rng, Fun> transform(Rng && rng, Fun fun)
{
return {std::forward<Rng>(rng), std::move(fun)};
}
~~~~~~~
Range transformation is achieved by defining a nested `adaptor` class that
handles the transformation, and then defining `begin_adaptor` and `end_adaptor`
members that return adaptors for the begin iterator and the end sentinel,
respectively. The `adaptor` class has a `read` member that performs the
transformation. It is passed an iterator to the current element. Other members
are available for customization: `equal`, `next`, `prev`, `advance`, and
`distance_to`; but the transform adaptor accepts the defaults defined in
\link ranges::adaptor_base `ranges::adaptor_base`\endlink.
With `transform_view`, we can print out the first 20 squares:
~~~~~~~{.cpp}
int main()
{
auto squares = ::transform(views::ints(1), [](int i){return i*i;});
for(int i : squares | views::take(20))
std::cout << i << ' ';
std::cout << '\n';
// prints 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400
}
~~~~~~~
The `transform_view` defined above is an input range when it is wrapping an
input range, a forward range when it's wrapping a forward range, etc. That happens
because of smart defaults defined in the `adaptor_base` class that frees you
from having to deal with a host of niggly detail when implementing iterators.
*(Note: the above `transform_view` always stores a copy of the function in the
sentinel. That is only necessary if the underlying range's sentinel type models
bidirectional_iterator. That's a finer point that you shouldn't worry about right
now.)*
#### view_adaptor in details
Each `view_adaptor` contains `base()` member in view and iterator.
`base()` - allow to access "adapted" range/iterator:
~~~~~~~{.cpp}
std::vector<int> vec;
auto list = vec | views::transfom([](int i){ return i+1; });
assert( vec.begin() == list.begin().base() );
assert( vec.begin() == list.base().begin() );
~~~~~~~
Like `basic_iterator`'s `cursor`, `view_adaptor`'s `adaptor` can contain mixin class too,
to inject things into the public interface of the iterator:
~~~~~~~{.cpp}
class adaptor : public ranges::adaptor_base
{
template<class base_mixin>
struct mixin : base_mixin
{
// everything inside this class will be accessible from iterator
using base_mixin::base_mixin;
auto& base_value() const
{
return *this->base();
}
int get_i() const
{
return this->get().i;
}
};
int i = 100;
};
~~~~~~~
From within mixin you can call:
* `get()` - to access adaptor internals
* `base()` - to access adaptable iterator
Iterator/sentinel adaptor may "override" the following members:
~~~~~~~{.cpp}
class adaptor : public ranges::adaptor_base
{
// !For begin_adaptor only!
template<typename Rng>
constexpr auto begin(Rng &rng)
{
return ranges::begin(rng.base());
}
// !For end_adaptor only!
template<typename Rng>
constexpr auto end(Rng &rng)
{
return ranges::end(rng.base());
}
template<typename I>
bool equal(I const &this_iter, I const &that_iter) const
{
return this_iter == that_iter;
}
// or
template<typename I>
bool equal(I const &this_iter, I const &that_iter, adaptor const &that_adapt) const
{
return
*this.some_value == that_adapt.some_value
&& this_iter == that_iter;
}
// !For end_adaptor only!
// Same as equal, but compare iterator with sentinel.
// Not used, if iterator same as sentinel, and both have the same adaptor.
template<typename I, typename S>
constexpr bool empty(I const &it, S const &end) const
{
return it == end;
}
// or
template<typename I, typename S, typename SA>
constexpr bool empty(I const &it, S const &end, SA const &end_adapt) const
{
return
*this.some_value == end_adapt.some_value
&& it == end;
}
template<typename I>
reference_t<I> read(I const &it)
{
return *it;
}
template<typename I>
void next(I &it)
{
++it;
}
// !For bidirectional iterator only!
template<typename I>
void prev(I &it)
{
--it;
}
// !For random access iterator only!
template<typename I>
void advance(I &it, difference_type_t<I> n)
{
it += n;
}
// !For "sized" iterators only!
template<typename I>
difference_type_t<I> distance_to(I const &this_iter, I const &that_iter)
{
return that_iter - this_iter;
}
// or
template<typename I>
difference_type_t<I> distance_to
(I const &this_iter, I const &that_iter, adaptor const &that_adapt)
{
return that_iter - this_iter;
}
}
~~~~~~~
As you can see, some "overrides" have effect only for `begin_adaptor` or
`end_adaptor`. In order to use full potential of adaptor, you need to have
separate adaptors for begin and end:
~~~~~~~{.cpp}
struct adaptor : adaptor_base
{
int n = 0;
void next(iterator_t<Rng>& it)
{
++n;
++it;
}
};
struct sentinel_adaptor : adaptor_base
{
int stop_at;
bool empty(const iterator_t<Rng>&, const adaptor& ia, const sentinel_t<Rng>& s) const
{
return ia.n == stop_at;
}
};
adaptor begin_adaptor() const { return {}; }
sentinel_adaptor end_adaptor() const { return {100}; }
~~~~~~~
Sometimes, you can use the same adaptor for both `begin_adaptor` and `end_adaptor`:
~~~~~~~{.cpp}
struct adaptor : adaptor_base
{
int n = 0;
void next(iterator_t<Rng>& it)
{
++n;
++it;
}
// pay attention, we use equal, not empty. empty() will never trigger.
template<typename I>
bool equal(I const &this_iter, I const &that_iter, adaptor const &that_adapt) const
{
return *this.n == that_adapt.n;
}
};
adaptor begin_adaptor() const { return {}; }
adaptor end_adaptor() const { return {100}; }
~~~~~~~
Note that all the data you store in the adaptor will become part of the iterator.
If you will not "override" `begin_adaptor()` or/and `end_adaptor()` in your view_adaptor, default ones will be used.
### Create Custom Iterators with basic_iterator
Here is an example of Range-v3 compatible random access proxy iterator.
The iterator returns a key/value pair, like the `zip` view.
~~~~~~~{.cpp}
#include <range/v3/iterator/basic_iterator.hpp>
#include <range/v3/utility/common_tuple.hpp>
using KeyIter = typename std::vector<Key>::iterator;
using ValueIter = typename std::vector<Value>::iterator;
struct cursor
{
// basic_iterator derives from "mixin", if present, so it can be used
// to inject things into the public interface of the iterator
struct mixin;
// This is for dereference operator.
using value_type = std::pair<Key, Value>;
ranges::common_pair<Key&, Value&> read() const
{
return { *key_iterator, *value_iterator };
}
bool equal(const cursor& other) const
{
return key_iterator == other.key_iterator;
}
void next()
{
++key_iterator;
++value_iterator;
}
// prev optional. Required for Bidirectional iterator
void prev()
{
--key_iterator;
--value_iterator;
}
// advance and distance_to are optional. Required for random access iterator
void advance(std::ptrdiff_t n)
{
key_iterator += n;
value_iterator += n;
}
std::ptrdiff_t distance_to(const cursor& other) const
{
return other.key_iterator - this->key_iterator;
}
cursor() = default;
cursor(KeyIter key_iterator, ValueIter value_iterator)
: key_iterator(key_iterator)
, value_iterator(value_iterator)
{}
KeyIter key_iterator;
ValueIter value_iterator;
};
struct cursor::mixin : ranges::basic_mixin<cursor>
{
using ranges::basic_mixin<cursor>::basic_mixin;
// It is necessary to expose constructor in this way
mixin(KeyIter key_iterator, ValueIter value_iterator)
: mixin{ cursor(key_iterator, value_iterator) }
{}
KeyIter key_iterator()
{
return this->get().key_iterator;
}
ValueIter value_iterator()
{
return this->get().value_iterator;
}
};
using iterator = ranges::basic_iterator<cursor>;
void test()
{
std::vector<Key> keys = {1};
std::vector<Value> values = {10};
iterator iter(keys.begin(), values.begin());
ranges::common_pair<Key&, Value&> pair = *iter;
Key& key = pair.first;
Value& value = pair.second;
assert(&key == &keys[0]);
assert(&value == &values[0]);
auto key_iter = iter.key_iterator();
assert(key_iter == keys.begin());
}
~~~~~~~
`read()` returns references. But the default for `value_type`, which is
`decay_t<decltype(read())>`, is `common_pair<Key&, Value&>`. That is not correct
in our case. It should be `pair<Key, Value>`, so we explicitly specify
`value_type`.
`ranges::common_pair` has conversions:
> `ranges::common_pair<Key&, Value&>` &harr; `ranges::common_pair<Key, Value>`.
All `ranges::common_pair`s converts to their `std::pair` equivalents, also.
For more information, see [http://wg21.link/P0186#basic-iterators-iterators.basic](http://wg21.link/P0186#basic-iterators-iterators.basic)
\subsection tutorial-concepts Concept Checking
--------------------------------------------------------------------------------
The Range-v3 library makes heavy use of concepts to constrain functions, control
overloading, and check type constraints at compile-time. It achieves this with
the help of a Concepts emulation layer that works on any standard-conforming
C++14 compiler. The library provides many useful concepts, both for the core
language and for iterators and ranges. You can use the concepts framework to
constrain your own code.
For instance, if you would like to write a function that takes an
iterator/sentinel pair, you can write it like this:
~~~~~~~{.cpp}
CPP_template(class Iter, class Sent, class Comp = /*...some_default..*/)
(requires sentinel_for<Sent, Iter>)
void my_algorithm(Iter first, Sent last, Comp comp = Comp{})
{
// ...
}
~~~~~~~
You can then add an overload that take a Range:
~~~~~~~{.cpp}
CPP_template(class Rng, class Comp = /*...some_default..*/)
(requires range<Rng>)
void my_algorithm(Rng && rng, Comp comp = Comp{})
{
return my_algorithm(ranges::begin(rng), ranges::end(rng));
}
~~~~~~~
With the type constraints expressed with the `CPP_template` macro, these
two overloads are guaranteed to not be ambiguous. When compiling with C++20
concepts support, this uses real concept checks. On legacy compilers, it falls
back to using `std::enable_if`.
\subsection tutorial-future Range-v3 and the Future
--------------------------------------------------------------------------------
Range-v3 formed the basis for the
[Technical Specification on Ranges](https://www.iso.org/standard/70910.html),
which has since been merged into the working draft of C++20.
In addition, a subset of range-v3's views are also a part of the C++20 working
draft, with more slated for eventual inclusion in future versions of C++.
The actions, as well as various utilities, have not yet been reviewed by the
Committee, although the basic direction has already passed an initial review.

View File

@ -1,225 +0,0 @@
<doxygenlayout version="1.0">
<!-- Generated by doxygen 1.8.7 -->
<!-- Navigation index tabs for HTML output -->
<navindex>
<tab type="mainpage" visible="yes" title=""/>
<tab type="pages" visible="yes" title="" intro=""/>
<tab type="modules" visible="yes"
title="Reference"
intro="
The reference documentation is split into logical modules, as documented in
the user manual."/>
<tab type="usergroup" visible="yes" title="Indexes">
<tab type="classmembers" visible="yes"
title="Methods"
intro="
This is an index of all the methods with links to the
corresponding documentation."/>
<tab type="classlist" visible="yes"
title="Classes"
intro="
This is an index of all the classes in the library with links to the
corresponding documentation."/>
<tab type="filelist" visible="yes"
title="Files"
intro=""/>
</tab>
<!-- We don't use what's below -->
<tab type="namespaces" visible="no" title="">
<tab type="namespacelist" visible="no" title="" intro=""/>
<tab type="namespacemembers" visible="no" title="" intro=""/>
</tab>
<tab type="examples" visible="no" title="" intro=""/>
<tab type="classes" visible="no" title="">
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="hierarchy" visible="no" title="" intro=""/>
</tab>
<tab type="files" visible="no" title="Files">
<tab type="globals" visible="no" title="Globals" intro=""/>
</tab>
</navindex>
<!-- Layout definition for a class page -->
<class>
<briefdescription visible="no"/>
<detaileddescription title="Description"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<inheritancegraph visible="$CLASS_GRAPH"/>
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
<memberdecl>
<related title="Synopsis of methods" subtitle=" "/>
<nestedclasses visible="yes" title="Instances and minimal complete definitions"/>
<friends title=""/>
<membergroups visible="yes"/>
<!-- We don't use what's below -->
<publictypes title=""/>
<services title=""/>
<interfaces title=""/>
<publicslots title=""/>
<signals title=""/>
<publicmethods title=""/>
<publicstaticmethods title=""/>
<publicattributes title=""/>
<publicstaticattributes title=""/>
<protectedtypes title=""/>
<protectedslots title=""/>
<protectedmethods title=""/>
<protectedstaticmethods title=""/>
<protectedattributes title=""/>
<protectedstaticattributes title=""/>
<packagetypes title=""/>
<packagemethods title=""/>
<packagestaticmethods title=""/>
<packageattributes title=""/>
<packagestaticattributes title=""/>
<properties title=""/>
<events title=""/>
<privatetypes title=""/>
<privateslots title=""/>
<privatemethods title=""/>
<privatestaticmethods title=""/>
<privateattributes title=""/>
<privatestaticattributes title=""/>
</memberdecl>
<memberdef>
<related title="Methods"/>
<functions title=""/>
<variables title=""/>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<!-- This is not for C++ -->
<services title=""/>
<interfaces title=""/>
<constructors title=""/>
<properties title=""/>
<events title=""/>
</memberdef>
<allmemberslink visible="yes"/>
<usedfiles visible="$SHOW_USED_FILES"/>
<authorsection visible="yes"/>
</class>
<!-- Layout definition for a namespace page -->
<namespace>
<briefdescription visible="yes"/>
<memberdecl>
<nestednamespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<classes visible="yes" title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection visible="yes"/>
</namespace>
<!-- Layout definition for a file page -->
<file>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<includegraph visible="$INCLUDE_GRAPH"/>
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
<sourcelink visible="yes"/>
<memberdecl>
<classes visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection/>
</file>
<!-- Layout definition for a group page -->
<group>
<briefdescription visible="no"/>
<detaileddescription title="Description"/>
<groupgraph visible="$GROUP_GRAPHS"/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<dirs visible="yes" title=""/>
<files visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
<membergroups visible="yes"/>
</memberdecl>
<memberdef>
<pagedocs/>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
</memberdef>
<authorsection visible="yes"/>
</group>
<!-- Layout definition for a directory page -->
<directory>
<briefdescription visible="yes"/>
<directorygraph visible="yes"/>
<memberdecl>
<dirs visible="yes"/>
<files visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
</directory>
</doxygenlayout>

View File

@ -1,308 +0,0 @@
Release Notes {#release_notes}
=============
\section v0-9-1 Version 0.9.1
_Released:_ Sept 1, 2019.
gcc-9.x portability fixes.
\section v0-9-0 Version 0.9.0 "Std::ranger Things"
_Released:_ Aug 26, 2019.
Bring many interfaces into sync with the C++20 draft.
* **NEW:** An improved concepts portability layer with macros that use C++20
concepts when the compiler supports them.
* **NEW:** An improved directory structure that keeps disjoint parts of the
library -- iterators, ranges, algorithms, actions, views, functional
programming support, and general utilities -- physically separate.
* **NEW:** A `RANGES_DEEP_STL_INTEGRATION` configuration option that makes your
STL implementation default to structural conformance to infer iterator
category, as in C++20. Applies to libc++, libstdc++, and MSVC's Standard
Library.
* **NEW:** A `ranges::cpp20` namespace that contains all the functionality of
C++20's `std::ranges` namespace.
* All concept names have been given standard_case (renamed from PascalCase) and
have been harmonized with the C++20 draft.
* The following range access customization points no longer accept rvalue ranges
by default:
- `ranges::begin`
- `ranges::end`
- `ranges::rbegin`
- `ranges::rend`
- `ranges::cbegin`
- `ranges::cend`
- `ranges::crbegin`
- `ranges::crend`
- `ranges::data`
- `ranges::cdata`
* Iterators may specify an `iterator_concept` type alias in addition to
`iterator_category` -- either as a nested type or as a member of a
`std::iterator_traits` specialization -- to denote conformance to the C++20
iterator concepts as distinct from the C++98 iterator requirements.
(See [P1037 "Deep Integration of the Ranges TS"](http://wg21.link/p1037)
for more information.)
* The `ranges::value_type` trait has been renamed to `readable_traits`.
* The `ranges::difference_type` trait has been renamed to `incrementable_traits`.
* The `ranges::iterator_category` trait has been deprecated. Specialize
`std::iterator_traits` to non-intrusively specify an iterator's category
and (optionally) concept.
* Rename the `ranges::view` namespace to `ranges::views` and `ranges::action` to
`ranges::actions` (with deprecated namespace aliases for migration).
* Rename `view::bounded` to `views::common`.
* Rename `unreachable` to `unreachable_sentinel_t`.
* Change `dangling` from a class template that wraps an iterator to a class that
acts as a placeholder for an iterator that would otherwise dangle.
* Implement C++20's `subrange` as a view that wraps an iterator/sentinel pair;
deprecate `iterator_range`.
* Deprecate implicit conversion from view types to containers; rename
`ranges::to_` to `ranges::to` and extend it to support converting a
range-of-ranges to a container-of-containers.
* Deprecate the `ranges::v3` inline versioning namespace.
* The following views have had minor changes to bring them into conformance with
the C++20 working draft:
- `join_view`
- `single_view`
- `empty_view`
- `split_view`
- `reverse_view`
- `all_view`
- `take_view`
- `iota_view`
<p/>`iota_view<std::[u]intmax_t>`, in particular, is given a user-defined
`difference_type` that avoids integer overflow.
* New names for the iterator and range type aliases:
| Old Name | New Name |
|-------------------------------|-----------------------------|
| `value_type_t` | `iter_value_t` |
| `reference_t` | `iter_reference_t` |
| `difference_type_t` | `iter_difference_t` |
| `size_type_t` | _deprecated_ |
| `rvalue_reference_t` | `iter_rvalue_reference_t` |
| `range_value_type_t` | `range_value_t` |
| `range_difference_type_t` | `range_difference_t` |
| `range_size_type_t` | `range_size_t` |
\section v0-5-0 Version 0.5.0
_Released:_ Apr 30, 2019.
* **NEW:** MSVC support, from @CaseyCarter :tada: (See the docs for the list of supported compilers.)
* **NEW:** `view::enumerate`, from @MikeGitb
* **NEW:** `view::addressof`, from @tower120
* **NEW:** `unstable_remove_if` algorithm and action, from @tower120
* **NEW:** `adjacent_remove_if` algorithm and action, from @cjdb
* **NEW:** `ostream_joiner`, from @sv1990
* `view::drop_while` and `view::take_while` get projection support, from @mrpi
* `view::filter` and `view::remove_if` get projection support, from @mrpi
* `view::unique` accepts optional comparison operator, from @tete17
* `action::slice` supports sliding from the end, from @tete17
* Support coroutines on MSVC, from @CaseyCarter
* Faster `view::generate_n`, from GitHub user @tower120
* Improved aligned new detection for libc++ on iOS, from @mtak-
* Various CMake improvements, from @johelegp
* `view_adaptor` supports `basic_iterator`-style mixins, from @tower120
* Fix `ranges::advance` for random-access iterators for `n==0`, from @tower120
* Bugs fixed: [#755](https://github.com/ericniebler/range-v3/issues/755), [#759](https://github.com/ericniebler/range-v3/issues/759), [#942](https://github.com/ericniebler/range-v3/issues/942), [#946](https://github.com/ericniebler/range-v3/issues/946), [#952](https://github.com/ericniebler/range-v3/issues/952), [#975](https://github.com/ericniebler/range-v3/issues/975), [#978](https://github.com/ericniebler/range-v3/issues/978), [#986](https://github.com/ericniebler/range-v3/issues/986), [#996](https://github.com/ericniebler/range-v3/issues/996), [#1041](https://github.com/ericniebler/range-v3/issues/1041), [#1047](https://github.com/ericniebler/range-v3/issues/1047), [#1088](https://github.com/ericniebler/range-v3/issues/1088), [#1094](https://github.com/ericniebler/range-v3/issues/1094), [#1107](https://github.com/ericniebler/range-v3/issues/1107), [#1129](https://github.com/ericniebler/range-v3/issues/1129)
\section v0-4-0 Version 0.4.0
_Released:_ Oct 18, 2018.
- Minor interface-breaking changes:
* `single_view` returns by `const &` (see [#817](https://github.com/ericniebler/range-v3/issues/817)).
* `reverse_view` of a non-Sized, non-Bounded RandomAccess range (eg., a null-terminated string) no longer satisfies SizedRange.
* The `generate` and `generate_n` views now return the generated values by xvalue reference (`T &&`) to the value cached within the view (see [#905](https://github.com/ericniebler/range-v3/issues/905)).
* Views no longer prefer returning constant iterators when they can; some views have different constant and mutable iterators.
- Enhancements:
* Views can successfully adapt other views that have different constant and mutable iterators.
* The `single` and `empty` views are much closer to the versions as specified in [P0896](http://wg21.link/P0896).
- Bug fixes:
* "single_view should not copy the value" [#817](https://github.com/ericniebler/range-v3/issues/817).
* "Calling back() on strided range does not return the correct last value in range" [#901](https://github.com/ericniebler/range-v3/issues/901).
* "generate(foo) | take(n) calls foo n+1 times" [#819](https://github.com/ericniebler/range-v3/issues/819).
* "generate seems broken with move-only return types" [#905](https://github.com/ericniebler/range-v3/issues/905).
* "Unexpected behavior in generate with return by reference" [#807](https://github.com/ericniebler/range-v3/issues/807).
* "Inconsistent behaviour of ranges::distance with ranges::view::zip using infinite views." [#783](https://github.com/ericniebler/range-v3/issues/783).
* "Infinite loop when using ranges::view::cycle with an infinite range" [#780](https://github.com/ericniebler/range-v3/issues/780).
* "Composing ranges::view::cycle with ranges::view::slice" [#778](https://github.com/ericniebler/range-v3/issues/778).
* "cartesian_product view, now with moar bugs." [#919](https://github.com/ericniebler/range-v3/issues/919).
\section v0-3-7 Version 0.3.7
_Released:_ Sept 19, 2018.
- Improved support for clang-cl (thanks to @CaseyCarter).
- Fix for `any_view<T, category::sized | category::input>` (see #869).
- Fix `iter_move` of a `ranges::reverse_iterator` (see #888).
- Fix `move_sentinel` comparisons (see #889).
- Avoid ambiguity created by `boost::advance` and `std::advance` (see #893).
\section v0-3-6 Version 0.3.6
_Released:_ May 15, 2018.
- NEW: `view::exclusive_scan` (thanks to GitHub user @mitsutaka-takeda).
- All views get non-`const` overloads of `.empty()` and `.size()` (see [ericniebler/stl2\#793](https://github.com/ericniebler/stl2/issues/793)).
- Upgrade Conan support for conan 1.0.
- `subspan` interface tweaks.
- Fix bug in `view::split` (see [this stackoverflow question](https://stackoverflow.com/questions/49015671)).
- Fix bug in `view::stride` (see [ericniebler/stl2\#805](https://github.com/ericniebler/stl2/issues/805)).
- Fix `const`-correctness problem in `view::chunk` (see [this stackoverflow question](https://stackoverflow.com/questions/49210190)).
- Replace uses of `ranges::result_of` with `ranges::invoke_result`.
- Fix potential buffer overrun of `view::drop` over RandomAccessRanges.
- Lots of `view::cartesian_product` fixes (see [ericniebler/stl2\#820](https://github.com/ericniebler/stl2/issues/820), [ericniebler/stl2\#823](https://github.com/ericniebler/stl2/issues/823)).
- Work around gcc-8 regression regarding `volatile` `std::initializer_list`s (see [ericniebler/stl2\#826](https://github.com/ericniebler/stl2/issues/826)).
- Fix `const`-correctness problem of `view::take`.
\section v0-3-5 Version 0.3.5
_Released:_ February 17, 2018.
- Rvalues may satisfy `Writable` (see [ericniebler/stl2\#387](https://github.com/ericniebler/stl2/issues/387)).
- `view_interface` gets a bounds-checking `at` method.
- `chunk_view` works on Input ranges.
- Fix bug in `group_by_view`.
- Improved concept checks for `partial_sum` numeric algorithm.
- Define `ContiguousIterator` concept and `contiguous_iterator_tag` iterator
category tag.
- Sundry `span` fixes.
- `action::insert` avoids interfering with `vector`'s exponentional growth
strategy.
- Add an experimental `shared` view for views that need container-like scratch
space to do their work.
- Faster, simpler `reverse_view`.
- Rework `ranges::reference_wrapper` to avoid [LWG\#2993](https://wg21.link/lwg2993).
- Reworked `any_view`, the type-erased view wrapper.
- `equal` algorithm is `constexpr` in C++14.
- `stride_view` no longer needs an `atomic` data member.
- `const`-correct `drop_view`.
- `adjacent_filter_view` supports bidirectional iteration.
- Massive `view_adaptor` cleanup to remove the need for a `mutable` data
member holding the adapted view.
- Fix `counting_iterator` post-increment bug.
- `tail_view` of an empty range is an empty range, not undefined behavior.
- Various portability fixes for gcc and clang trunk.
\section v0-3-0 Version 0.3.0
_Released:_ June 30, 2017.
- Input views may now be move-only (from @CaseyCarter)
- Input `any_view`s are now *much* more efficient (from @CaseyCarter)
- Better support for systems lacking a working `<thread>` header (from @CaseyCarter)
\section v0-2-6 Version 0.2.6
_Released:_ June 21, 2017.
- Experimental coroutines with `ranges::experimental::generator` (from @CaseyCarter)
- `ranges::optional` now behaves like `std::optional` (from @CaseyCarter)
- Extensive bug fixes with Input ranges (from @CaseyCarter)
\section v0-2-5 Version 0.2.5
_Released:_ May 16, 2017.
- `view::chunk` works on Input ranges (from @CaseyCarter)
- `for_each_n` algorithm (from @khlebnikov)
- Portability fixes for MinGW, clang-3.6 and -3.7, and gcc-7; and cmake 3.0
\section v0-2-4 Version 0.2.4
_Released:_ April 12, 2017.
Fix the following bug:
- `action::stable_sort` of `vector` broken on Clang 3.8.1 since ~last Xmas (ericniebler/range-v3#632).
\section v0-2-3 Version 0.2.3
_Released:_ April 4, 2017.
Fix the following bug:
- iterators that return move-only types by value do not satisfy Readable (ericniebler/stl2#399).
\section v0-2-2 Version 0.2.2
_Released:_ March 30, 2017.
New in this release:
- `view::linear_distribute(from,to,n)` - A view of `n` elements between `from` and `to`, distributed evenly.
- `view::indices(n)` - A view of the indices `[0,1,2...n-1]`.
- `view::closed_indices(n)` - A view of the indices `[0,1,2...n]`.
This release deprecates `view::ints(n)` as confusing to new users.
\section v0-2-1 Version 0.2.1
_Released:_ March 22, 2017.
New in this release:
- `view::cartesian_product`
- `action::reverse`
\section v0-2-0 Version 0.2.0
_Released:_ March 13, 2017.
Bring many interfaces into sync with the Ranges TS.
- Many interfaces are simply renamed. The following table shows the old names
and the new. (All names are in the `ranges::v3` namespace.)
| Old Name | New Name |
|-------------------------------|---------------------------|
| `indirect_swap` | `iter_swap` |
| `indirect_move` | `iter_move` |
| `iterator_value_t` | `value_type_t` |
| `iterator_reference_t` | `reference_t` |
| `iterator_difference_t` | `difference_type_t` |
| `iterator_size_t` | `size_type_t` |
| `iterator_rvalue_reference_t` | `rvalue_reference_t` |
| `iterator_common_reference_t` | `iter_common_reference_t` |
| `range_value_t` | `range_value_type_t` |
| `range_difference_t` | `range_difference_type_t` |
| `range_size_t` | `range_size_type_t` |
| `range_iterator_t` | `iterator_t` |
| `range_sentinel_t` | `sentinel_t` |
- `common_iterator` now requires that its two types (`Iterator` and `Sentinel`)
are different. Use `common_iterator_t<I, S>` to get the old behavior (i.e., if the two types are the same, it is an alias for `I`; otherwise, it is
`common_iterator<I, S>`).
- The following iterator adaptors now work with iterators that return proxies
from their postfix increment operator (i.e., `operator++(int)`):
* `common_iterator`
* `counted_iterator`
- The following customization points are now implemented per the Ranges TS
spec and will no longer find the associated unconstrained overload in
namespace `std::`:
* `ranges::begin`
* `ranges::end`
* `ranges::size`
* `ranges::swap`
* `ranges::iter_swap`
(In practice, this has very little effect but it may effect overloading in
rare situations.)
- `ranges::is_swappable` now only takes one template parameter. The new
`ranges::is_swappable_with<T, U>` tests whether `T` and `U` are swappable.
`ranges::is_swappable<T>` is equivalent to `ranges::is_swappable_with<T &, T &>`.
- The following object concepts have changed to conform with the Ranges TS
specification, and approved changes (see [P0547](http://wg21.link/p0547)):
* `Destructible`
* `Constructible`
* `DefaultConstructible`
* `MoveConstructible`
* `MoveConstructible`
* `Movable`
* `Assignable`
- The `View` concept is no longer satisfied by reference types.
- The syntax for defining a concept has changed slightly. See [iterator/concepts.hpp](https://github.com/ericniebler/range-v3/blob/master/include/range/v3/iterator/concepts.hpp) for examples.
\section v0-1-1 Version 0.1.1
- Small tweak to `Writable` concept to fix #537.
\section v0-1-0 Version 0.1.0
- March 8, 2017, Begin semantic versioning

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +0,0 @@
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="607">
<tr>
<td width="172" align="left" valign="top">Document number:</td>
<td width="435">
<span style="background-color: #FFFF00">D4128</span>=yy-nnnn
</td>
</tr>
<tr>
<td width="172" align="left" valign="top">Date:</td>
<td width="435">2014-10-10</td>
</tr>
<tr>
<td width="172" align="left" valign="top">Project:</td>
<td width="435">Programming Language C++, Library Working Group</td>
</tr>
<tr>
<td width="172" align="left" valign="top">Reply-to:</td>
<td width="435">
Eric Niebler &lt;<a href="mailto:eniebler@boost.org">eniebler@boost.org</a>&gt;,<br/>
Sean Parent &lt;<a href="mailto:sparent@adobe.com">sparent@adobe.com</a>&gt;,<br/>
Andrew Sutton &lt;<a href="mailto:andrew.n.sutton@gmail.com">andrew.n.sutton@gmail.com</a>&gt;
</td>
</tr>
</table>

View File

@ -1,67 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"$if(lang)$ lang="$lang$" xml:lang="$lang$"$endif$>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
$for(author-meta)$
<meta name="author" content="$author-meta$" />
$endfor$
$if(date-meta)$
<meta name="date" content="$date-meta$" />
$endif$
<title>$if(title-prefix)$$title-prefix$ - $endif$$pagetitle$</title>
<style type="text/css">code{white-space: pre;}</style>
$if(quotes)$
<style type="text/css">q { quotes: "“" "”" "" ""; }</style>
$endif$
$if(highlighting-css)$
<style type="text/css">
$highlighting-css$
</style>
$endif$
$for(css)$
<link rel="stylesheet" href="$css$" $if(html5)$$else$type="text/css" $endif$/>
$endfor$
$if(math)$
$math$
$endif$
$for(header-includes)$
$header-includes$
$endfor$
</head>
<body>
$for(include-before)$
$include-before$
$endfor$
$if(title)$
<div id="$idprefix$header">
<h1 class="title">$title$</h1>
$if(subtitle)$
<h1 class="subtitle">$subtitle$</h1>
$endif$
$for(author)$
<h2 class="author">$author$</h2>
$endfor$
$if(date)$
<h3 class="date">$date$</h3>
$endif$
</div>
$endif$
<blockquote>
<p>“A beginning is the time for taking the most delicate care that the balances are correct.”</p>
<p>
Frank Herbert, <em>Dune</em>
</p>
</blockquote>
$if(toc)$
<div id="$idprefix$TOC">
$toc$
</div>
$endif$
$body$
$for(include-after)$
$include-after$
$endfor$
</body>
</html>

View File

@ -1 +0,0 @@
pandoc -f markdown_github+yaml_metadata_block+citations -t html -o D4128.html --filter pandoc-citeproc --csl=acm-sig-proceedings.csl --number-sections --toc -s -S --template=pandoc-template --include-before-body=header.html D4128.md

View File

@ -1,155 +0,0 @@
cxx_binary(
name = 'comprehensions',
srcs = [
'comprehensions.cpp',
],
deps = [
'//:range-v3',
],
compiler_flags = [
'-std=c++14',
],
)
cxx_binary(
name = 'count_if',
srcs = [
'count_if.cpp',
],
deps = [
'//:range-v3',
],
compiler_flags = [
'-std=c++14',
],
)
cxx_binary(
name = 'count',
srcs = [
'count.cpp',
],
deps = [
'//:range-v3',
],
compiler_flags = [
'-std=c++14',
],
)
cxx_binary(
name = 'find',
srcs = [
'find.cpp',
],
deps = [
'//:range-v3',
],
compiler_flags = [
'-std=c++14',
],
)
cxx_binary(
name = 'for_each_assoc',
srcs = [
'for_each_assoc.cpp',
],
deps = [
'//:range-v3',
],
compiler_flags = [
'-std=c++14',
],
)
cxx_binary(
name = 'for_each_sequence',
srcs = [
'for_each_sequence.cpp',
],
deps = [
'//:range-v3',
],
compiler_flags = [
'-std=c++14',
],
)
cxx_binary(
name = 'hello',
srcs = [
'hello.cpp',
],
deps = [
'//:range-v3',
],
compiler_flags = [
'-std=c++14',
],
)
cxx_binary(
name = 'is_sorted',
srcs = [
'is_sorted.cpp',
],
deps = [
'//:range-v3',
],
compiler_flags = [
'-std=c++14',
],
)
cxx_binary(
name = 'filter_transform',
srcs = [
'filter_transform.cpp',
],
deps = [
'//:range-v3',
],
compiler_flags = [
'-std=c++14',
],
)
cxx_binary(
name = 'accumulate_ints',
srcs = [
'accumulate_ints.cpp',
],
deps = [
'//:range-v3',
],
compiler_flags = [
'-std=c++14',
],
)
cxx_binary(
name = 'comprehension_conversion',
srcs = [
'comprehension_conversion.cpp',
],
deps = [
'//:range-v3',
],
compiler_flags = [
'-std=c++14',
],
)
cxx_binary(
name = 'sort_unique',
srcs = [
'sort_unique.cpp',
],
deps = [
'//:range-v3',
],
compiler_flags = [
'-std=c++14',
],
)

View File

@ -1,38 +0,0 @@
set(CMAKE_FOLDER "example")
# examples use a less draconian set of compiler warnings
ranges_append_flag(RANGES_HAS_WNO_MISSING_BRACES -Wno-missing-braces)
ranges_append_flag(RANGES_HAS_WNO_SHORTEN_64_TO_32 -Wno-shorten-64-to-32)
ranges_append_flag(RANGES_HAS_WNO_GLOBAL_CONSTRUCTORS -Wno-global-constructors)
rv3_add_test(example.comprehensions comprehensions comprehensions.cpp)
rv3_add_test(example.hello hello hello.cpp)
rv3_add_test(example.count count count.cpp)
rv3_add_test(example.count_if count_if count_if.cpp)
rv3_add_test(example.any_all_none_of any_all_none_of any_all_none_of.cpp)
rv3_add_test(example.for_each_sequence for_each_sequence for_each_sequence.cpp)
rv3_add_test(example.for_each_assoc for_each_assoc for_each_assoc.cpp)
rv3_add_test(example.is_sorted is_sorted is_sorted.cpp)
rv3_add_test(example.find find find.cpp)
rv3_add_test(example.filter_transform filter_transform filter_transform.cpp)
rv3_add_test(example.accumulate_ints accumulate_ints accumulate_ints.cpp)
rv3_add_test(example.comprehension_conversion comprehension_conversion comprehension_conversion.cpp)
rv3_add_test(example.sort_unique sort_unique sort_unique.cpp)
# Guarded with a variable because the calendar example causes gcc to puke.
if(RANGES_BUILD_CALENDAR_EXAMPLE)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED OFF)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.59.0 COMPONENTS date_time program_options)
if (Boost_FOUND)
add_executable(calendar calendar.cpp)
target_include_directories(calendar SYSTEM PRIVATE ${Boost_INCLUDE_DIRS})
target_link_libraries(calendar range-v3 ${Boost_LIBRARIES})
message(STATUS "boost: ${Boost_LIBRARY_DIRS}")
target_compile_definitions(calendar PRIVATE BOOST_NO_AUTO_PTR)
target_compile_options(calendar PRIVATE -std=gnu++14)
set_target_properties(calendar PROPERTIES LINK_FLAGS "-L${Boost_LIBRARY_DIRS}")
endif()
endif()

View File

@ -1,37 +0,0 @@
// Range v3 library
//
// Copyright Eric Niebler 2019
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
///[accumulate_ints]
// Sums the first ten squares and prints them, using views::ints to generate
// and infinite range of integers, views::transform to square them, views::take
// to drop all but the first 10, and accumulate to sum them.
#include <iostream>
#include <vector>
#include <range/v3/numeric/accumulate.hpp>
#include <range/v3/view/iota.hpp>
#include <range/v3/view/take.hpp>
#include <range/v3/view/transform.hpp>
using std::cout;
int main()
{
using namespace ranges;
int sum = accumulate(views::ints(1, unreachable) | views::transform([](int i) {
return i * i;
}) | views::take(10),
0);
// prints: 385
cout << sum << '\n';
}
///[accumulate_ints]

View File

@ -1,44 +0,0 @@
// Range v3 library
//
// Copyright Jeff Garland 2017
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
//[any_all_none_of]]
// Demonstrates any_of, all_of, none_of
// output
// vector: [6,2,3,4,5,6]
// vector any_of is_six: true
// vector all_of is_six: false
// vector none_of is_six: false
#include <range/v3/algorithm/all_of.hpp>
#include <range/v3/algorithm/any_of.hpp>
#include <range/v3/algorithm/for_each.hpp>
#include <range/v3/algorithm/none_of.hpp>
#include <range/v3/view/all.hpp>
#include <iostream>
#include <vector>
using std::cout;
auto is_six = [](int i) { return i == 6; };
int
main()
{
std::vector<int> v{6, 2, 3, 4, 5, 6};
cout << std::boolalpha;
cout << "vector: " << ranges::views::all(v) << '\n';
cout << "vector any_of is_six: " << ranges::any_of(v, is_six) << '\n';
cout << "vector all_of is_six: " << ranges::all_of(v, is_six) << '\n';
cout << "vector none_of is_six: " << ranges::none_of(v, is_six) << '\n';
}
//[any_all_none_of]]

View File

@ -1,441 +0,0 @@
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#include <range/v3/detail/config.hpp>
#if RANGES_CXX_RETURN_TYPE_DEDUCTION >= RANGES_CXX_RETURN_TYPE_DEDUCTION_14 && \
RANGES_CXX_GENERIC_LAMBDAS >= RANGES_CXX_GENERIC_LAMBDAS_14
///[calendar]
// Usage:
// calendar 2015
//
// Output:
/*
January February March
1 2 3 1 2 3 4 5 6 7 1 2 3 4 5 6 7
4 5 6 7 8 9 10 8 9 10 11 12 13 14 8 9 10 11 12 13 14
11 12 13 14 15 16 17 15 16 17 18 19 20 21 15 16 17 18 19 20 21
18 19 20 21 22 23 24 22 23 24 25 26 27 28 22 23 24 25 26 27 28
25 26 27 28 29 30 31 29 30 31
April May June
1 2 3 4 1 2 1 2 3 4 5 6
5 6 7 8 9 10 11 3 4 5 6 7 8 9 7 8 9 10 11 12 13
12 13 14 15 16 17 18 10 11 12 13 14 15 16 14 15 16 17 18 19 20
19 20 21 22 23 24 25 17 18 19 20 21 22 23 21 22 23 24 25 26 27
26 27 28 29 30 24 25 26 27 28 29 30 28 29 30
31
July August September
1 2 3 4 1 1 2 3 4 5
5 6 7 8 9 10 11 2 3 4 5 6 7 8 6 7 8 9 10 11 12
12 13 14 15 16 17 18 9 10 11 12 13 14 15 13 14 15 16 17 18 19
19 20 21 22 23 24 25 16 17 18 19 20 21 22 20 21 22 23 24 25 26
26 27 28 29 30 31 23 24 25 26 27 28 29 27 28 29 30
30 31
October November December
1 2 3 1 2 3 4 5 6 7 1 2 3 4 5
4 5 6 7 8 9 10 8 9 10 11 12 13 14 6 7 8 9 10 11 12
11 12 13 14 15 16 17 15 16 17 18 19 20 21 13 14 15 16 17 18 19
18 19 20 21 22 23 24 22 23 24 25 26 27 28 20 21 22 23 24 25 26
25 26 27 28 29 30 31 29 30 27 28 29 30 31
// */
// Credits:
// Thanks to H. S. Teoh for the article that served as the
// inspiration for this example:
// <http://wiki.dlang.org/Component_programming_with_ranges>
// Thanks to github's Arzar for bringing date::week_number
// to my attention.
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/program_options.hpp>
#include <algorithm>
#include <cstddef>
#include <functional>
#include <iostream>
#include <range/v3/action/join.hpp>
#include <range/v3/algorithm/copy.hpp>
#include <range/v3/algorithm/for_each.hpp>
#include <range/v3/algorithm/mismatch.hpp>
#include <range/v3/core.hpp>
#include <range/v3/iterator/stream_iterators.hpp>
#include <range/v3/view/all.hpp>
#include <range/v3/view/concat.hpp>
#include <range/v3/view/group_by.hpp>
#include <range/v3/view/iota.hpp>
#include <range/v3/view/join.hpp>
#include <range/v3/view/repeat_n.hpp>
#include <range/v3/view/single.hpp>
#include <range/v3/view/take.hpp>
#include <range/v3/view/transform.hpp>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
namespace po = boost::program_options;
namespace greg = boost::gregorian;
using date = greg::date;
using day = greg::date_duration;
using namespace ranges;
namespace boost
{
namespace gregorian
{
date &operator++(date &d)
{
return d = d + day(1);
}
date operator++(date &d, int)
{
return ++d - day(1);
}
}
}
namespace ranges
{
template<>
struct incrementable_traits<date>
{
using difference_type = date::duration_type::duration_rep::int_type;
};
}
CPP_assert(incrementable<date>);
auto
dates(unsigned short start, unsigned short stop)
{
return views::iota(date{start, greg::Jan, 1}, date{stop, greg::Jan, 1});
}
auto
dates_from(unsigned short year)
{
return views::iota(date{year, greg::Jan, 1});
}
auto
by_month()
{
return views::group_by(
[](date a, date b) { return a.month() == b.month(); });
}
auto
by_week()
{
return views::group_by([](date a, date b) {
// ++a because week_number is Mon-Sun and we want Sun-Sat
return (++a).week_number() == (++b).week_number();
});
}
std::string
format_day(date d)
{
return boost::str(boost::format("%|3|") % d.day());
}
// In: range<range<date>>: month grouped by weeks.
// Out: range<std::string>: month with formatted weeks.
auto
format_weeks()
{
return views::transform([](/*range<date>*/ auto week) {
return boost::str(boost::format("%1%%2%%|22t|") %
std::string(front(week).day_of_week() * 3u, ' ') %
(week | views::transform(format_day) | actions::join));
});
}
// Return a formatted string with the title of the month
// corresponding to a date.
std::string
month_title(date d)
{
return boost::str(boost::format("%|=22|") % d.month().as_long_string());
}
// In: range<range<date>>: year of months of days
// Out: range<range<std::string>>: year of months of formatted wks
auto
layout_months()
{
return views::transform([](/*range<date>*/ auto month) {
auto week_count =
static_cast<std::ptrdiff_t>(distance(month | by_week()));
return views::concat(
views::single(month_title(front(month))),
month | by_week() | format_weeks(),
views::repeat_n(std::string(22, ' '), 6 - week_count));
});
}
namespace cal_example
{
// In: range<T>
// Out: range<range<T>>, where each inner range has $n$ elements.
// The last range may have fewer.
template<class Rng>
class chunk_view : public view_adaptor<chunk_view<Rng>, Rng>
{
CPP_assert(forward_range<Rng>);
ranges::range_difference_t<Rng> n_;
friend range_access;
class adaptor;
adaptor begin_adaptor()
{
return adaptor{n_, ranges::end(this->base())};
}
public:
chunk_view() = default;
chunk_view(Rng rng, ranges::range_difference_t<Rng> n)
: chunk_view::view_adaptor(std::move(rng))
, n_(n)
{}
};
template<class Rng>
class chunk_view<Rng>::adaptor : public adaptor_base
{
ranges::range_difference_t<Rng> n_;
sentinel_t<Rng> end_;
public:
adaptor() = default;
adaptor(ranges::range_difference_t<Rng> n, sentinel_t<Rng> last)
: n_(n)
, end_(last)
{}
auto read(iterator_t<Rng> it) const
{
return views::take(make_subrange(std::move(it), end_), n_);
}
void next(iterator_t<Rng> &it)
{
ranges::advance(it, n_, end_);
}
void prev() = delete;
void distance_to() = delete;
};
} // namespace cal_example
// In: range<T>
// Out: range<range<T>>, where each inner range has $n$ elements.
// The last range may have fewer.
auto
chunk(std::size_t n)
{
return make_pipeable([=](auto &&rng) {
using Rng = decltype(rng);
return cal_example::chunk_view<views::all_t<Rng>>{
views::all(std::forward<Rng>(rng)),
static_cast<ranges::range_difference_t<Rng>>(n)};
});
}
// Flattens a range of ranges by iterating the inner
// ranges in round-robin fashion.
template<class Rngs>
class interleave_view : public view_facade<interleave_view<Rngs>>
{
friend range_access;
std::vector<range_value_t<Rngs>> rngs_;
struct cursor;
cursor begin_cursor()
{
return {0, &rngs_, views::transform(rngs_, ranges::begin) | to<std::vector>};
}
public:
interleave_view() = default;
explicit interleave_view(Rngs rngs)
: rngs_(std::move(rngs) | to<std::vector>)
{}
};
template<class Rngs>
struct interleave_view<Rngs>::cursor
{
std::size_t n_;
std::vector<range_value_t<Rngs>> *rngs_;
std::vector<iterator_t<range_value_t<Rngs>>> its_;
decltype(auto) read() const
{
return *its_[n_];
}
void next()
{
if(0 == ((++n_) %= its_.size()))
for_each(its_, [](auto &it) { ++it; });
}
bool equal(default_sentinel_t) const
{
if(n_ != 0)
return false;
auto ends = *rngs_ | views::transform(ranges::end);
return its_.end() != std::mismatch(
its_.begin(), its_.end(), ends.begin(), std::not_equal_to<>{}).first;
}
CPP_member
auto equal(cursor const& that) const -> CPP_ret(bool)(
requires forward_range<range_value_t<Rngs>>)
{
return n_ == that.n_ && its_ == that.its_;
}
};
// In: range<range<T>>
// Out: range<T>, flattened by walking the ranges
// round-robin fashion.
auto
interleave()
{
return make_pipeable([](auto &&rngs) {
using Rngs = decltype(rngs);
return interleave_view<views::all_t<Rngs>>(
views::all(std::forward<Rngs>(rngs)));
});
}
// In: range<range<T>>
// Out: range<range<T>>, transposing the rows and columns.
auto
transpose()
{
return make_pipeable([](auto &&rngs) {
using Rngs = decltype(rngs);
CPP_assert(forward_range<Rngs>);
return std::forward<Rngs>(rngs)
| interleave()
| chunk(static_cast<std::size_t>(distance(rngs)));
});
}
// In: range<range<range<string>>>
// Out: range<range<range<string>>>, transposing months.
auto
transpose_months()
{
return views::transform(
[](/*range<range<string>>*/ auto rng) { return rng | transpose(); });
}
// In: range<range<string>>
// Out: range<string>, joining the strings of the inner ranges
auto
join_months()
{
return views::transform(
[](/*range<string>*/ auto rng) { return actions::join(rng); });
}
// In: range<date>
// Out: range<string>, lines of formatted output
auto
format_calendar(std::size_t months_per_line)
{
return make_pipeable([=](auto &&rng) {
using Rng = decltype(rng);
return std::forward<Rng>(rng)
// Group the dates by month:
| by_month()
// Format the month into a range of strings:
| layout_months()
// Group the months that belong side-by-side:
| chunk(months_per_line)
// Transpose the rows and columns of the size-by-side months:
| transpose_months()
// Ungroup the side-by-side months:
| views::join
// Join the strings of the transposed months:
| join_months();
});
}
int
main(int argc, char *argv[]) try
{
// Declare the supported options.
po::options_description desc("Allowed options");
desc.add_options()("help", "produce help message")(
"start", po::value<unsigned short>(), "Year to start")(
"stop", po::value<std::string>(), "Year to stop")(
"per-line",
po::value<std::size_t>()->default_value(3u),
"Nbr of months per line");
po::positional_options_description p;
p.add("start", 1).add("stop", 1);
po::variables_map vm;
po::store(
po::command_line_parser(argc, argv).options(desc).positional(p).run(),
vm);
po::notify(vm);
if(vm.count("help") || 1 != vm.count("start"))
{
std::cerr << desc << '\n';
return 1;
}
auto const start = vm["start"].as<unsigned short>();
auto const stop = 0 == vm.count("stop")
? (unsigned short)(start + 1)
: vm["stop"].as<std::string>() == "never"
? (unsigned short)-1
: boost::lexical_cast<unsigned short>(
vm["stop"].as<std::string>());
auto const months_per_line = vm["per-line"].as<std::size_t>();
if(stop != (unsigned short)-1 && stop <= start)
{
std::cerr << "ERROR: The stop year must be larger than the start"
<< '\n';
return 1;
}
if((unsigned short)-1 != stop)
{
copy(dates(start, stop) | format_calendar(months_per_line),
ostream_iterator<>(std::cout, "\n"));
}
else
{
copy(dates_from(start) | format_calendar(months_per_line),
ostream_iterator<>(std::cout, "\n"));
}
}
catch(std::exception &e)
{
std::cerr << "ERROR: Unhandled exception\n";
std::cerr << " what(): " << e.what();
return 1;
}
///[calendar]
#else
#pragma message( \
"calendar requires C++14 return type deduction and generic lambdas")
int
main()
{}
#endif

View File

@ -1,35 +0,0 @@
// Range v3 library
//
// Copyright Eric Niebler 2019
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
///[comprehension_conversion]
// Use a range comprehension (views::for_each) to construct a custom range, and
// then convert it to a std::vector.
#include <iostream>
#include <vector>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/for_each.hpp>
#include <range/v3/view/iota.hpp>
#include <range/v3/view/repeat_n.hpp>
using std::cout;
int main()
{
using namespace ranges;
auto vi = views::for_each(views::ints(1, 6),
[](int i) { return yield_from(views::repeat_n(i, i)); }) |
to<std::vector>();
// prints: [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
cout << views::all(vi) << '\n';
}
///[comprehension_conversion]

View File

@ -1,124 +0,0 @@
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#include <chrono>
#include <iostream>
#include <range/v3/all.hpp>
using namespace ranges;
int
main()
{
// Define an infinite range containing all the Pythagorean triples:
auto triples = views::for_each(views::iota(1), [](int z) {
return views::for_each(views::iota(1, z + 1), [=](int x) {
return views::for_each(views::iota(x, z + 1), [=](int y) {
return yield_if(x * x + y * y == z * z,
std::make_tuple(x, y, z));
});
});
});
//// This alternate syntax also works:
// auto triples = iota(1) >>= [] (int z) { return
// iota(1, z+1) >>= [=](int x) { return
// iota(x, z+1) >>= [=](int y) { return
// yield_if(x*x + y*y == z*z,
// std::make_tuple(x, y, z)); };}; };
// Display the first 100 triples
RANGES_FOR(auto triple, triples | views::take(100))
{
std::cout << '(' << std::get<0>(triple) << ',' << std::get<1>(triple)
<< ',' << std::get<2>(triple) << ')' << '\n';
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Benchmark Code
////////////////////////////////////////////////////////////////////////////////////////////////////
class timer
{
private:
std::chrono::high_resolution_clock::time_point start_;
public:
timer()
{
reset();
}
void reset()
{
start_ = std::chrono::high_resolution_clock::now();
}
std::chrono::milliseconds elapsed() const
{
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start_);
}
friend std::ostream &operator<<(std::ostream &sout, timer const &t)
{
return sout << t.elapsed().count() << "ms";
}
};
void
benchmark()
{
// Define an infinite range containing all the Pythagorean triples:
auto triples = views::for_each(views::iota(1), [](int z) {
return views::for_each(views::iota(1, z + 1), [=](int x) {
return views::for_each(views::iota(x, z + 1), [=](int y) {
return yield_if(x * x + y * y == z * z,
std::make_tuple(x, y, z));
});
});
});
static constexpr int max_triples = 3000;
timer t;
int result = 0;
RANGES_FOR(auto triple, triples | views::take(max_triples))
{
int i, j, k;
std::tie(i, j, k) = triple;
result += (i + j + k);
}
std::cout << t << '\n';
std::cout << result << '\n';
result = 0;
int found = 0;
t.reset();
for(int z = 1;; ++z)
{
for(int x = 1; x <= z; ++x)
{
for(int y = x; y <= z; ++y)
{
if(x * x + y * y == z * z)
{
result += (x + y + z);
++found;
if(found == max_triples)
goto done;
}
}
}
}
done:
std::cout << t << '\n';
std::cout << result << '\n';
}

View File

@ -1,40 +0,0 @@
// Range v3 library
//
// Copyright Jeff Garland 2017
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
///[count]
// This example demonstrates counting the number of
// elements that match a given value.
// output...
// vector: 2
// array: 2
#include <iostream>
#include <range/v3/algorithm/count.hpp> // specific includes
#include <vector>
using std::cout;
int
main()
{
std::vector<int> v{6, 2, 3, 4, 5, 6};
// note the count return is a numeric type
// like int or long -- auto below make sure
// it matches the implementation
auto c = ranges::count(v, 6);
cout << "vector: " << c << '\n';
std::array<int, 6> a{6, 2, 3, 4, 5, 6};
c = ranges::count(a, 6);
cout << "array: " << c << '\n';
}
///[count]

View File

@ -1,39 +0,0 @@
// Range v3 library
//
// Copyright Jeff Garland 2017
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
///[count_if]
// This example counts element of a range that match a supplied predicate.
// output
// vector: 2
// array: 2
#include <array>
#include <iostream>
#include <range/v3/algorithm/count_if.hpp> // specific includes
#include <vector>
using std::cout;
auto is_six = [](int i) -> bool { return i == 6; };
int
main()
{
std::vector<int> v{6, 2, 3, 4, 5, 6};
auto c = ranges::count_if(v, is_six);
cout << "vector: " << c << '\n'; // 2
std::array<int, 6> a{6, 2, 3, 4, 5, 6};
c = ranges::count_if(a, is_six);
cout << "array: " << c << '\n'; // 2
}
///[count_if]

View File

@ -1,34 +0,0 @@
// Range v3 library
//
// Copyright Eric Niebler 2019
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
///[filter_transform]
// This example demonstrates filtering and transforming a range on the
// fly with view adaptors.
#include <iostream>
#include <string>
#include <vector>
#include <range/v3/view/filter.hpp>
#include <range/v3/view/transform.hpp>
using std::cout;
int main()
{
std::vector<int> const vi{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
using namespace ranges;
auto rng = vi | views::filter([](int i) { return i % 2 == 0; }) |
views::transform([](int i) { return std::to_string(i); });
// prints: [2,4,6,8,10]
cout << rng << '\n';
}
///[filter_transform]

View File

@ -1,118 +0,0 @@
// Range v3 library
//
// Copyright Jeff Garland 2017
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
///[find]
// vector: *i: 6
// didn't find 10
// *i: 6
// *i: 2
// *i after ++ (2 expected): 2
// array: *i: 6
// list: *i: 6
// fwd_list: *i: 4
// deque: *i: 6
#include <array>
#include <deque>
#include <forward_list>
#include <iostream>
#include <list>
#include <range/v3/all.hpp>
#include <vector>
using std::cout;
auto is_six = [](int i) -> bool { return i == 6; };
int
main()
{
cout << "vector: ";
std::vector<int> v{6, 2, 6, 4, 6, 1};
{
auto i = ranges::find(v, 6); // 1 2 3 4 5 6
cout << "*i: " << *i << '\n';
}
{
auto i = ranges::find(v, 10); // 1 2 3 4 5 6
if(i == ranges::end(v))
{
cout << "didn't find 10\n";
}
}
{
auto i = ranges::find_if(v, is_six);
if(i != ranges::end(v))
{
cout << "*i: " << *i << '\n';
}
}
{
auto i = ranges::find_if_not(v, is_six);
if(i != ranges::end(v))
{
cout << "*i: " << *i << '\n';
}
}
{
auto i = ranges::find(v, 6);
i++;
if(i != ranges::end(v))
{
cout << "*i after ++ (2 expected): " << *i;
}
}
cout << "\narray: ";
std::array<int, 6> a{6, 2, 3, 4, 5, 1};
{
auto i = ranges::find(a, 6);
if(i != ranges::end(a))
{
cout << "*i: " << *i;
}
}
cout << "\nlist: ";
std::list<int> li{6, 2, 3, 4, 5, 1};
{
auto i = ranges::find(li, 6);
if(i != ranges::end(li))
{
cout << "*i: " << *i;
}
}
cout << "\nfwd_list: ";
std::forward_list<int> fl{6, 2, 3, 4, 5, 1};
{
auto i = ranges::find(fl, 4);
if(i != ranges::end(fl))
{
cout << "*i: " << *i;
}
}
cout << "\ndeque: ";
std::deque<int> d{6, 2, 3, 4, 5, 1};
{
auto i = ranges::find(d, 6);
if(i != ranges::end(d))
{
cout << "*i: " << *i;
}
}
cout << '\n';
}
///[find]

View File

@ -1,58 +0,0 @@
// Range v3 library
//
// Copyright Jeff Garland 2017
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
///[for_each_assoc]
// for_each with associative containers
// output
// set: 1 2 3 4 5 6
// map: one:1 three:3 two:2
// unordered_map: three:3 one:1 two:2
// unordered_set: 6 5 4 3 2 1
#include <iostream>
#include <map>
#include <range/v3/algorithm/for_each.hpp>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
using std::cout;
using std::string;
auto print = [](int i) { cout << i << ' '; };
// must take a pair for map types
auto printm = [](std::pair<string, int> p) {
cout << p.first << ":" << p.second << ' ';
};
int
main()
{
cout << "set: ";
std::set<int> si{1, 2, 3, 4, 5, 6};
ranges::for_each(si, print);
cout << "\nmap: ";
std::map<string, int> msi{{"one", 1}, {"two", 2}, {"three", 3}};
ranges::for_each(msi, printm);
cout << "\nunordered map: ";
std::unordered_map<string, int> umsi{{"one", 1}, {"two", 2}, {"three", 3}};
ranges::for_each(umsi, printm);
cout << "\nunordered set: ";
std::unordered_set<int> usi{1, 2, 3, 4, 5, 6};
ranges::for_each(usi, print);
cout << '\n';
}
///[for_each_assoc]

View File

@ -1,59 +0,0 @@
// Range v3 library
//
// Copyright Jeff Garland 2017
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
///[for_each_sequence]
// Use the for_each to print from various containers
// output
// vector: 1 2 3 4 5 6
// array: 1 2 3 4 5 6
// list: 1 2 3 4 5 6
// fwd_list: 1 2 3 4 5 6
// deque: 1 2 3 4 5 6
#include <array>
#include <deque>
#include <forward_list>
#include <iostream>
#include <list>
#include <queue>
#include <range/v3/algorithm/for_each.hpp> // specific includes
#include <stack>
#include <vector>
using std::cout;
auto print = [](int i) { cout << i << ' '; };
int
main()
{
cout << "vector: ";
std::vector<int> v{1, 2, 3, 4, 5, 6};
ranges::for_each(v, print); // 1 2 3 4 5 6
cout << "\narray: ";
std::array<int, 6> a{1, 2, 3, 4, 5, 6};
ranges::for_each(a, print);
cout << "\nlist: ";
std::list<int> ll{1, 2, 3, 4, 5, 6};
ranges::for_each(ll, print);
cout << "\nfwd_list: ";
std::forward_list<int> fl{1, 2, 3, 4, 5, 6};
ranges::for_each(fl, print);
cout << "\ndeque: ";
std::deque<int> d{1, 2, 3, 4, 5, 6};
ranges::for_each(d, print);
cout << '\n';
}
///[for_each_sequence]

View File

@ -1,29 +0,0 @@
// Range v3 library
//
// Copyright Jeff Garland 2017
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
///[hello]
#include <iostream>
#include <range/v3/all.hpp> // get everything
#include <string>
using std::cout;
int
main()
{
std::string s{"hello"};
// output: h e l l o
ranges::for_each(s, [](char c) { cout << c << ' '; });
cout << '\n';
}
///[hello]

View File

@ -1,35 +0,0 @@
// Range v3 library
//
// Copyright Jeff Garland 2017
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
///[is_sorted]
// Check if a container is sorted
// output
// vector: true
// array: false
#include <array>
#include <iostream>
#include <range/v3/algorithm/is_sorted.hpp> // specific includes
#include <vector>
using std::cout;
int
main()
{
cout << std::boolalpha;
std::vector<int> v{1, 2, 3, 4, 5, 6};
cout << "vector: " << ranges::is_sorted(v) << '\n';
std::array<int, 6> a{6, 2, 3, 4, 5, 6};
cout << "array: " << ranges::is_sorted(a) << '\n';
}
///[is_sorted]

View File

@ -1,34 +0,0 @@
// Range v3 library
//
// Copyright Eric Niebler 2019
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
///[sort_unique]
// Remove all non-unique elements from a container.
#include <iostream>
#include <vector>
#include <range/v3/action/sort.hpp>
#include <range/v3/action/unique.hpp>
#include <range/v3/view/all.hpp>
using std::cout;
int main()
{
std::vector<int> vi{9, 4, 5, 2, 9, 1, 0, 2, 6, 7, 4, 5, 6, 5, 9, 2, 7,
1, 4, 5, 3, 8, 5, 0, 2, 9, 3, 7, 5, 7, 5, 5, 6, 1,
4, 3, 1, 8, 4, 0, 7, 8, 8, 2, 6, 5, 3, 4, 5};
using namespace ranges;
vi |= actions::sort | actions::unique;
// prints: [0,1,2,3,4,5,6,7,8,9]
cout << views::all(vi) << '\n';
}
///[sort_unique]

File diff suppressed because it is too large Load Diff

View File

@ -1,326 +0,0 @@
/// \file
// Concepts library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
#ifndef CPP_SWAP_HPP
#define CPP_SWAP_HPP
#include <tuple>
#include <utility>
#include <type_traits>
#include <meta/meta.hpp>
// Note: constexpr implies inline, to retain the same visibility
// C++14 constexpr functions are inline in C++11
#if (defined(__cpp_constexpr) && __cpp_constexpr >= 201304L) ||\
(!defined(__cpp_constexpr) && __cplusplus >= 201402L)
#define CPP_CXX14_CONSTEXPR constexpr
#else
#define CPP_CXX14_CONSTEXPR inline
#endif
#ifndef CPP_CXX_INLINE_VARIABLES
#ifdef __cpp_inline_variables // TODO: fix this if SD-6 picks another name
#define CPP_CXX_INLINE_VARIABLES __cpp_inline_variables
// TODO: remove once clang defines __cpp_inline_variables (or equivalent)
#elif defined(__clang__) && \
(__clang_major__ > 3 || __clang_major__ == 3 && __clang_minor__ == 9) && \
__cplusplus > 201402L
#define CPP_CXX_INLINE_VARIABLES 201606L
#else
#define CPP_CXX_INLINE_VARIABLES __cplusplus
#endif // __cpp_inline_variables
#endif // CPP_CXX_INLINE_VARIABLES
#if defined(_MSC_VER) && !defined(__clang__)
#define CPP_WORKAROUND_MSVC_895622 // Error when phase 1 name binding finds only deleted function
#endif
#if CPP_CXX_INLINE_VARIABLES < 201606L
#define CPP_INLINE_VAR
#define CPP_INLINE_VARIABLE(type, name) \
inline namespace \
{ \
constexpr auto &name = ::concepts::detail::static_const<type>::value; \
} \
/**/
#else // CPP_CXX_INLINE_VARIABLES >= 201606L
#define CPP_INLINE_VAR inline
#define CPP_INLINE_VARIABLE(type, name) \
inline constexpr type name{}; \
/**/
#endif // CPP_CXX_INLINE_VARIABLES
#if CPP_CXX_INLINE_VARIABLES < 201606L
#define CPP_DEFINE_CPO(type, name) \
inline namespace \
{ \
constexpr auto &name = ::concepts::detail::static_const<type>::value; \
} \
/**/
#else // CPP_CXX_INLINE_VARIABLES >= 201606L
#define CPP_DEFINE_CPO(type, name) \
inline namespace _ \
{ \
inline constexpr type name{}; \
} \
/**/
#endif // CPP_CXX_INLINE_VARIABLES
#if defined(_MSC_VER) && !defined(__clang__)
#define CPP_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME
#else // ^^^ defined(_MSC_VER) ^^^ / vvv !defined(_MSC_VER) vvv
#if defined(__GNUC__) || defined(__clang__)
#define CPP_PRAGMA(X) _Pragma(#X)
#define CPP_DIAGNOSTIC_IGNORE_PRAGMAS \
CPP_PRAGMA(GCC diagnostic ignored "-Wpragmas")
#define CPP_DIAGNOSTIC_IGNORE(X) \
CPP_DIAGNOSTIC_IGNORE_PRAGMAS \
CPP_PRAGMA(GCC diagnostic ignored "-Wunknown-pragmas") \
CPP_PRAGMA(GCC diagnostic ignored X)
#define CPP_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME \
CPP_DIAGNOSTIC_IGNORE("-Wunknown-warning-option") \
CPP_DIAGNOSTIC_IGNORE("-Winit-list-lifetime")
#else
#define CPP_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME
#endif
#endif // MSVC/Generic configuration switch
namespace concepts
{
/// \cond
namespace detail
{
template<typename T>
CPP_INLINE_VAR constexpr bool is_movable_v =
std::is_object<T>::value &&
std::is_move_constructible<T>::value &&
std::is_move_assignable<T>::value;
template<typename T>
struct static_const
{
static constexpr T const value {};
};
template<typename T>
constexpr T const static_const<T>::value;
}
/// \endcond
template<typename T>
struct is_swappable;
template<typename T>
struct is_nothrow_swappable;
template<typename T, typename U>
struct is_swappable_with;
template<typename T, typename U>
struct is_nothrow_swappable_with;
template<typename T, typename U = T>
CPP_CXX14_CONSTEXPR
meta::if_c<
std::is_move_constructible<T>::value &&
std::is_assignable<T &, U>::value, T>
exchange(T &t, U &&u)
noexcept(
std::is_nothrow_move_constructible<T>::value &&
std::is_nothrow_assignable<T &, U>::value)
{
T tmp((T &&) t);
t = (U &&) u;
CPP_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME
return tmp;
}
/// \cond
namespace adl_swap_detail
{
struct nope
{};
// Intentionally create an ambiguity with std::swap, which is
// (possibly) unconstrained.
template<typename T>
nope swap(T &, T &) = delete;
template<typename T, std::size_t N>
nope swap(T (&)[N], T (&)[N]) = delete;
#ifdef CPP_WORKAROUND_MSVC_895622
nope swap();
#endif
template<typename T, typename U>
decltype(swap(std::declval<T>(), std::declval<U>())) try_adl_swap_(int);
template<typename T, typename U>
nope try_adl_swap_(long);
template<typename T, typename U = T>
CPP_INLINE_VAR constexpr bool is_adl_swappable_v =
!META_IS_SAME(decltype(adl_swap_detail::try_adl_swap_<T, U>(42)), nope);
struct swap_fn
{
// Dispatch to user-defined swap found via ADL:
template<typename T, typename U>
CPP_CXX14_CONSTEXPR
meta::if_c<is_adl_swappable_v<T, U>>
operator()(T &&t, U &&u) const
noexcept(noexcept(swap((T &&) t, (U &&) u)))
{
swap((T &&) t, (U &&) u);
}
// For intrinsically swappable (i.e., movable) types for which
// a swap overload cannot be found via ADL, swap by moving.
template<typename T>
CPP_CXX14_CONSTEXPR
meta::if_c<
!is_adl_swappable_v<T &> &&
detail::is_movable_v<T>>
operator()(T &a, T &b) const
noexcept(noexcept(b = concepts::exchange(a, (T &&) b)))
{
b = concepts::exchange(a, (T &&) b);
}
// For arrays of intrinsically swappable (i.e., movable) types
// for which a swap overload cannot be found via ADL, swap array
// elements by moving.
template<typename T, typename U, std::size_t N>
CPP_CXX14_CONSTEXPR
meta::if_c<
!is_adl_swappable_v<T (&)[N], U (&)[N]> &&
is_swappable_with<T &, U &>::value>
operator()(T (&t)[N], U (&u)[N]) const
noexcept(is_nothrow_swappable_with<T &, U &>::value)
{
for(std::size_t i = 0; i < N; ++i)
(*this)(t[i], u[i]);
}
// For rvalue pairs and tuples of swappable types, swap the
// members. This permits code like:
// ranges::swap(std::tie(a,b,c), std::tie(d,e,f));
template<typename F0, typename S0, typename F1, typename S1>
CPP_CXX14_CONSTEXPR
meta::if_c<is_swappable_with<F0, F1>::value && is_swappable_with<S0, S1>::value>
operator()(std::pair<F0, S0> &&left, std::pair<F1, S1> &&right) const
noexcept(
is_nothrow_swappable_with<F0, F1>::value &&
is_nothrow_swappable_with<S0, S1>::value)
{
swap_fn()(static_cast<std::pair<F0, S0> &&>(left).first,
static_cast<std::pair<F1, S1> &&>(right).first);
swap_fn()(static_cast<std::pair<F0, S0> &&>(left).second,
static_cast<std::pair<F1, S1> &&>(right).second);
}
template<typename ...Ts, typename ...Us>
CPP_CXX14_CONSTEXPR
meta::if_c<meta::and_c<is_swappable_with<Ts, Us>::value...>::value>
operator()(std::tuple<Ts...> &&left, std::tuple<Us...> &&right) const
noexcept(meta::and_c<is_nothrow_swappable_with<Ts, Us>::value...>::value)
{
swap_fn::impl(
static_cast<std::tuple<Ts...> &&>(left),
static_cast<std::tuple<Us...> &&>(right),
meta::make_index_sequence<sizeof...(Ts)>{});
}
private:
template<typename... Ts>
static constexpr int ignore_unused(Ts &&...)
{
return 0;
}
template<typename T, typename U, std::size_t ...Is>
CPP_CXX14_CONSTEXPR
static void impl(T &&left, U &&right, meta::index_sequence<Is...>)
{
(void) swap_fn::ignore_unused(
(swap_fn()(std::get<Is>(static_cast<T &&>(left)),
std::get<Is>(static_cast<U &&>(right))), 42)...);
}
};
template<typename T, typename U, typename = void>
struct is_swappable_with_
: std::false_type
{};
template<typename T, typename U>
struct is_swappable_with_<T, U, meta::void_<
decltype(swap_fn()(std::declval<T>(), std::declval<U>())),
decltype(swap_fn()(std::declval<U>(), std::declval<T>()))>>
: std::true_type
{};
template<typename T, typename U>
struct is_nothrow_swappable_with_
: meta::bool_<noexcept(swap_fn()(std::declval<T>(), std::declval<U>())) &&
noexcept(swap_fn()(std::declval<U>(), std::declval<T>()))>
{};
// Q: Should std::reference_wrapper be considered a proxy wrt swapping rvalues?
// A: No. Its operator= is currently defined to reseat the references, so
// std::swap(ra, rb) already means something when ra and rb are (lvalue)
// reference_wrappers. That reseats the reference wrappers but leaves the
// referents unmodified. Treating rvalue reference_wrappers differently would
// be confusing.
// Q: Then why is it OK to "re"-define swap for pairs and tuples of references?
// A: Because as defined above, swapping an rvalue tuple of references has the same
// semantics as swapping an lvalue tuple of references. Rather than reseat the
// references, assignment happens *through* the references.
// Q: But I have an iterator whose operator* returns an rvalue
// std::reference_wrapper<T>. How do I make it model indirectly_swappable?
// A: With an overload of iter_swap.
}
/// \endcond
/// \ingroup group-utility
template<typename T, typename U>
struct is_swappable_with
: adl_swap_detail::is_swappable_with_<T, U>
{};
/// \ingroup group-utility
template<typename T, typename U>
struct is_nothrow_swappable_with
: meta::and_<
is_swappable_with<T, U>,
adl_swap_detail::is_nothrow_swappable_with_<T, U>>
{};
/// \ingroup group-utility
template<typename T>
struct is_swappable
: is_swappable_with<T &, T &>
{};
/// \ingroup group-utility
template<typename T>
struct is_nothrow_swappable
: is_nothrow_swappable_with<T &, T &>
{};
/// \ingroup group-utility
/// \relates adl_swap_detail::swap_fn
CPP_DEFINE_CPO(adl_swap_detail::swap_fn, swap)
}
#endif

View File

@ -1,363 +0,0 @@
/// \file
// Concepts library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
#ifndef CPP_TYPE_TRAITS_HPP
#define CPP_TYPE_TRAITS_HPP
#include <tuple>
#include <utility>
#include <type_traits>
#include <meta/meta.hpp>
namespace concepts
{
template<typename T>
using remove_cvref_t =
typename std::remove_cv<
typename std::remove_reference<T>::type>::type;
/// \cond
namespace detail
{
template<typename From, typename To>
using is_convertible = std::is_convertible<meta::_t<std::add_rvalue_reference<From>>, To>;
template<bool>
struct if_else_
{
template<typename, typename U>
using invoke = U;
};
template<>
struct if_else_<true>
{
template<typename T, typename>
using invoke = T;
};
template<bool B, typename T, typename U>
using if_else_t = meta::invoke<if_else_<B>, T, U>;
template<bool>
struct if_
{};
template<>
struct if_<true>
{
template<typename T>
using invoke = T;
};
template<bool B, typename T = void>
using if_t = meta::invoke<if_<B>, T>;
template<typename From, typename To>
struct _copy_cv_
{
using type = To;
};
template<typename From, typename To>
struct _copy_cv_<From const, To>
{
using type = To const;
};
template<typename From, typename To>
struct _copy_cv_<From volatile, To>
{
using type = To volatile;
};
template<typename From, typename To>
struct _copy_cv_<From const volatile, To>
{
using type = To const volatile;
};
template<typename From, typename To>
using _copy_cv = meta::_t<_copy_cv_<From, To>>;
////////////////////////////////////////////////////////////////////////////////////////
template<typename T, typename U, typename = void>
struct _builtin_common;
template<typename T, typename U>
using _builtin_common_t = meta::_t<_builtin_common<T, U>>;
template<typename T, typename U>
using _cond_res = decltype(true ? std::declval<T>() : std::declval<U>());
template<typename T, typename U, typename R = _builtin_common_t<T &, U &>>
using _rref_res =
if_else_t<std::is_reference<R>::value, meta::_t<std::remove_reference<R>> &&, R>;
template<typename T, typename U>
using _lref_res = _cond_res<_copy_cv<T, U> &, _copy_cv<U, T> &>;
template<typename T>
struct as_cref_
{
using type = T const &;
};
template<typename T>
struct as_cref_<T &>
{
using type = T const &;
};
template<typename T>
struct as_cref_<T &&>
{
using type = T const &;
};
template<>
struct as_cref_<void>
{
using type = void;
};
template<>
struct as_cref_<void const>
{
using type = void const;
};
template<typename T>
using as_cref_t = typename as_cref_<T>::type;
template<typename T>
using decay_t = typename std::decay<T>::type;
#if !defined(__GNUC__) || defined(__clang__)
template<typename T, typename U, typename = void>
struct _builtin_common_2
{};
template<typename T, typename U>
struct _builtin_common_2<T, U, meta::void_<_cond_res<as_cref_t<T>, as_cref_t<U>>>>
: std::decay<_cond_res<as_cref_t<T>, as_cref_t<U>>>
{};
template<typename T, typename U, typename /* = void */>
struct _builtin_common
: _builtin_common_2<T, U>
{};
template<typename T, typename U>
struct _builtin_common<T &&, U &&, if_t<
is_convertible<T &&, _rref_res<T, U>>::value &&
is_convertible<U &&, _rref_res<T, U>>::value>>
{
using type = _rref_res<T, U>;
};
template<typename T, typename U>
struct _builtin_common<T &, U &>
: meta::defer<_lref_res, T, U>
{};
template<typename T, typename U>
struct _builtin_common<T &, U &&, if_t<
is_convertible<U &&, _builtin_common_t<T &, U const &>>::value>>
: _builtin_common<T &, U const &>
{};
template<typename T, typename U>
struct _builtin_common<T &&, U &>
: _builtin_common<U &, T &&>
{};
#else
template<typename T, typename U, typename = void>
struct _builtin_common_
{};
template<typename T, typename U>
struct _builtin_common_<T, U, meta::void_<_cond_res<as_cref_t<T>, as_cref_t<U>>>>
: std::decay<_cond_res<as_cref_t<T>, as_cref_t<U>>>
{};
template<typename T, typename U, typename /* = void */>
struct _builtin_common
: _builtin_common_<T, U>
{};
template<typename T, typename U, typename = void>
struct _builtin_common_rr
: _builtin_common_<T &&, U &&>
{};
template<typename T, typename U>
struct _builtin_common_rr<T, U, if_t<
is_convertible<T &&, _rref_res<T, U>>::value &&
is_convertible<U &&, _rref_res<T, U>>::value>>
{
using type = _rref_res<T, U>;
};
template<typename T, typename U>
struct _builtin_common<T &&, U &&>
: _builtin_common_rr<T, U>
{};
template<typename T, typename U>
struct _builtin_common<T &, U &>
: meta::defer<_lref_res, T, U>
{};
template<typename T, typename U, typename = void>
struct _builtin_common_lr
: _builtin_common_<T &, T &&>
{};
template<typename T, typename U>
struct _builtin_common_lr<T, U, if_t<
is_convertible<U &&, _builtin_common_t<T &, U const &>>::value>>
: _builtin_common<T &, U const &>
{};
template<typename T, typename U>
struct _builtin_common<T &, U &&>
: _builtin_common_lr<T, U>
{};
template<typename T, typename U>
struct _builtin_common<T &&, U &>
: _builtin_common<U &, T &&>
{};
#endif
}
/// \endcond
/// \addtogroup group-utility Utility
/// @{
///
/// Users should specialize this to hook the \c common_with concept
/// until \c std gets a SFINAE-friendly \c std::common_type and there's
/// some sane way to deal with cv and ref qualifiers.
template<typename ...Ts>
struct common_type
{};
template<typename T>
struct common_type<T>
: std::decay<T>
{};
template<typename T, typename U>
struct common_type<T, U>
: detail::if_else_t<
(META_IS_SAME(detail::decay_t<T>, T) &&
META_IS_SAME(detail::decay_t<U>, U) ),
meta::defer<detail::_builtin_common_t, T, U>,
common_type<detail::decay_t<T>, detail::decay_t<U>>>
{};
template<typename... Ts>
using common_type_t = typename common_type<Ts...>::type;
template<typename T, typename U, typename... Vs>
struct common_type<T, U, Vs...>
: meta::lazy::fold<meta::list<U, Vs...>, T, meta::quote<common_type_t>>
{};
/// @}
/// \addtogroup group-utility Utility
/// @{
///
/// Users can specialize this to hook the \c common_reference_with concept.
/// \sa `common_reference`
template<
typename T,
typename U,
template<typename> class TQual,
template<typename> class UQual>
struct basic_common_reference
{};
/// \cond
namespace detail
{
using _rref =
meta::quote_trait<std::add_rvalue_reference>;
using _lref =
meta::quote_trait<std::add_lvalue_reference>;
template<typename>
struct _xref
{
template<typename T>
using invoke = T;
};
template<typename T>
struct _xref<T &&>
{
template<typename U>
using invoke =
meta::_t<std::add_rvalue_reference<meta::invoke<_xref<T>, U>>>;
};
template<typename T>
struct _xref<T &>
{
template<typename U>
using invoke =
meta::_t<std::add_lvalue_reference<meta::invoke<_xref<T>, U>>>;
};
template<typename T>
struct _xref<T const>
{
template<typename U>
using invoke = U const;
};
template<typename T>
struct _xref<T volatile>
{
template<typename U>
using invoke = U volatile;
};
template<typename T>
struct _xref<T const volatile>
{
template<typename U>
using invoke = U const volatile;
};
template<typename T, typename U>
using _basic_common_reference =
basic_common_reference<
remove_cvref_t<T>,
remove_cvref_t<U>,
_xref<T>::template invoke,
_xref<U>::template invoke>;
template<typename T, typename U, typename = void>
struct _common_reference2
: if_else_t<
meta::is_trait<_basic_common_reference<T, U>>::value,
_basic_common_reference<T, U>,
common_type<T, U>>
{};
template<typename T, typename U>
struct _common_reference2<T, U, if_t<std::is_reference<_builtin_common_t<T, U>>::value>>
: _builtin_common<T, U>
{};
}
/// \endcond
/// Users can specialize this to hook the \c common_reference_with concept.
/// \sa `basic_common_reference`
template<typename ...Ts>
struct common_reference
{};
template<typename T>
struct common_reference<T>
{
using type = T;
};
template<typename T, typename U>
struct common_reference<T, U>
: detail::_common_reference2<T, U>
{};
template<typename... Ts>
using common_reference_t = typename common_reference<Ts...>::type;
template<typename T, typename U, typename... Vs>
struct common_reference<T, U, Vs...>
: meta::lazy::fold<meta::list<U, Vs...>, T, meta::quote<common_reference_t>>
{};
/// @}
} // namespace concepts
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,359 +0,0 @@
/// \file meta_fwd.hpp Forward declarations
//
// Meta library
//
// Copyright Eric Niebler 2014-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/meta
//
#ifndef META_FWD_HPP
#define META_FWD_HPP
#include <type_traits>
#include <utility>
#ifdef __clang__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-variable-declarations"
#endif
#define META_CXX_STD_14 201402L
#define META_CXX_STD_17 201703L
#if defined(_MSVC_LANG) && _MSVC_LANG > __cplusplus // Older clangs define _MSVC_LANG < __cplusplus
#define META_CXX_VER _MSVC_LANG
#else
#define META_CXX_VER __cplusplus
#endif
#if defined(__apple_build_version__) || defined(__clang__)
#if defined(__apple_build_version__) || (defined(__clang__) && __clang_major__ < 6)
#define META_WORKAROUND_LLVM_28385 // https://llvm.org/bugs/show_bug.cgi?id=28385
#endif
#elif defined(_MSC_VER)
#define META_HAS_MAKE_INTEGER_SEQ 1
#if _MSC_VER < 1920
#define META_WORKAROUND_MSVC_702792 // Bogus C4018 comparing constant expressions with dependent type
#define META_WORKAROUND_MSVC_703656 // ICE with pack expansion inside decltype in alias template
#endif
#if _MSC_VER < 1921
#define META_WORKAROUND_MSVC_756112 // fold expression + alias templates in template argument
#endif
#elif defined(__GNUC__)
#define META_WORKAROUND_GCC_86356 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86356
#if __GNUC__ < 8
#define META_WORKAROUND_GCC_UNKNOWN1 // Older GCCs don't like fold + debug + -march=native
#endif
#if __GNUC__ == 5 && __GNUC_MINOR__ == 1
#define META_WORKAROUND_GCC_66405 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66405
#endif
#if __GNUC__ < 5
#define META_WORKAROUND_CWG_1558 // https://wg21.link/cwg1558
#endif
#endif
#ifndef META_CXX_VARIABLE_TEMPLATES
#ifdef __cpp_variable_templates
#define META_CXX_VARIABLE_TEMPLATES __cpp_variable_templates
#else
#define META_CXX_VARIABLE_TEMPLATES (META_CXX_VER >= META_CXX_STD_14)
#endif
#endif
#ifndef META_CXX_INLINE_VARIABLES
#ifdef __cpp_inline_variables
#define META_CXX_INLINE_VARIABLES __cpp_inline_variables
#else
#define META_CXX_INLINE_VARIABLES (META_CXX_VER >= META_CXX_STD_17)
#endif
#endif
#ifndef META_INLINE_VAR
#if META_CXX_INLINE_VARIABLES
#define META_INLINE_VAR inline
#else
#define META_INLINE_VAR
#endif
#endif
#ifndef META_CXX_INTEGER_SEQUENCE
#ifdef __cpp_lib_integer_sequence
#define META_CXX_INTEGER_SEQUENCE __cpp_lib_integer_sequence
#else
#define META_CXX_INTEGER_SEQUENCE (META_CXX_VER >= META_CXX_STD_14)
#endif
#endif
#ifndef META_HAS_MAKE_INTEGER_SEQ
#ifdef __has_builtin
#if __has_builtin(__make_integer_seq)
#define META_HAS_MAKE_INTEGER_SEQ 1
#endif
#endif
#endif
#ifndef META_HAS_MAKE_INTEGER_SEQ
#define META_HAS_MAKE_INTEGER_SEQ 0
#endif
#ifndef META_HAS_TYPE_PACK_ELEMENT
#ifdef __has_builtin
#if __has_builtin(__type_pack_element)
#define META_HAS_TYPE_PACK_ELEMENT 1
#endif
#endif
#endif
#ifndef META_HAS_TYPE_PACK_ELEMENT
#define META_HAS_TYPE_PACK_ELEMENT 0
#endif
#if !defined(META_DEPRECATED) && !defined(META_DISABLE_DEPRECATED_WARNINGS)
#if defined(__cpp_attribute_deprecated) || META_CXX_VER >= META_CXX_STD_14
#define META_DEPRECATED(...) [[deprecated(__VA_ARGS__)]]
#elif defined(__clang__) || defined(__GNUC__)
#define META_DEPRECATED(...) __attribute__((deprecated(__VA_ARGS__)))
#endif
#endif
#ifndef META_DEPRECATED
#define META_DEPRECATED(...)
#endif
#ifndef META_CXX_FOLD_EXPRESSIONS
#ifdef __cpp_fold_expressions
#define META_CXX_FOLD_EXPRESSIONS __cpp_fold_expressions
#else
#define META_CXX_FOLD_EXPRESSIONS (META_CXX_VER >= META_CXX_STD_17)
#endif
#endif
#if META_CXX_FOLD_EXPRESSIONS
#if !META_CXX_VARIABLE_TEMPLATES
#error Fold expressions, but no variable templates?
#endif
#endif
#if defined(__cpp_concepts) && __cpp_concepts > 0
#if !META_CXX_VARIABLE_TEMPLATES
#error Concepts, but no variable templates?
#endif
#if __cpp_concepts <= 201507L
#define META_CONCEPT concept bool
// TS concepts subsumption barrier for atomic expressions
#define META_CONCEPT_BARRIER(...) ::meta::detail::barrier<__VA_ARGS__>
#else
#define META_CONCEPT concept
#define META_CONCEPT_BARRIER(...) __VA_ARGS__
#endif
#define META_TYPE_CONSTRAINT(...) __VA_ARGS__
#else
#define META_TYPE_CONSTRAINT(...) typename
#endif
#if (defined(__cpp_lib_type_trait_variable_templates) && \
__cpp_lib_type_trait_variable_templates > 0)
#define META_CXX_TRAIT_VARIABLE_TEMPLATES 1
#else
#define META_CXX_TRAIT_VARIABLE_TEMPLATES 0
#endif
#if defined(__clang__)
#define META_IS_SAME(...) __is_same(__VA_ARGS__)
#elif defined(__GNUC__) && __GNUC__ >= 6
#define META_IS_SAME(...) __is_same_as(__VA_ARGS__)
#elif META_CXX_TRAIT_VARIABLE_TEMPLATES
#define META_IS_SAME(...) std::is_same_v<__VA_ARGS__>
#else
#define META_IS_SAME(...) std::is_same<__VA_ARGS__>::value
#endif
#if defined(__GNUC__) || defined(_MSC_VER)
#define META_IS_BASE_OF(...) __is_base_of(__VA_ARGS__)
#elif META_CXX_TRAIT_VARIABLE_TEMPLATES
#define META_IS_BASE_OF(...) std::is_base_of_v<__VA_ARGS__>
#else
#define META_IS_BASE_OF(...) std::is_base_of<__VA_ARGS__>::value
#endif
#if defined(__clang__) || defined(_MSC_VER) || \
(defined(__GNUC__) && __GNUC__ >= 8)
#define META_IS_CONSTRUCTIBLE(...) __is_constructible(__VA_ARGS__)
#elif META_CXX_TRAIT_VARIABLE_TEMPLATES
#define META_IS_CONSTRUCTIBLE(...) std::is_constructible_v<__VA_ARGS__>
#else
#define META_IS_CONSTRUCTIBLE(...) std::is_constructible<__VA_ARGS__>::value
#endif
/// \cond
// Non-portable forward declarations of standard containers
#ifdef _LIBCPP_VERSION
#define META_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
#define META_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#elif defined(_MSVC_STL_VERSION)
#define META_BEGIN_NAMESPACE_STD _STD_BEGIN
#define META_END_NAMESPACE_STD _STD_END
#else
#define META_BEGIN_NAMESPACE_STD namespace std {
#define META_END_NAMESPACE_STD }
#endif
#if defined(__GLIBCXX__)
#define META_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
#define META_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
#define META_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#define META_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER
#else
#define META_BEGIN_NAMESPACE_VERSION
#define META_END_NAMESPACE_VERSION
#define META_BEGIN_NAMESPACE_CONTAINER
#define META_END_NAMESPACE_CONTAINER
#endif
#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 4000
#define META_TEMPLATE_VIS _LIBCPP_TEMPLATE_VIS
#elif defined(_LIBCPP_VERSION)
#define META_TEMPLATE_VIS _LIBCPP_TYPE_VIS_ONLY
#else
#define META_TEMPLATE_VIS
#endif
/// \endcond
namespace meta
{
#if META_CXX_INTEGER_SEQUENCE
using std::integer_sequence;
#else
template <typename T, T...>
struct integer_sequence;
#endif
template <typename... Ts>
struct list;
template <typename T>
struct id;
template <template <typename...> class>
struct quote;
template <typename T, template <T...> class F>
struct quote_i;
template <template <typename...> class C, typename... Ts>
struct defer;
template <typename T, template <T...> class C, T... Is>
struct defer_i;
#if META_CXX_VARIABLE_TEMPLATES || defined(META_DOXYGEN_INVOKED)
/// is_v
/// Test whether a type \p T is an instantiation of class
/// template \p C.
/// \ingroup trait
template <typename, template <typename...> class>
META_INLINE_VAR constexpr bool is_v = false;
template <typename... Ts, template <typename...> class C>
META_INLINE_VAR constexpr bool is_v<C<Ts...>, C> = true;
#endif
#ifdef META_CONCEPT
namespace detail
{
template <bool B>
META_INLINE_VAR constexpr bool barrier = B;
template <class T, T> struct require_constant; // not defined
}
template <typename...>
META_CONCEPT is_true = META_CONCEPT_BARRIER(true);
template <typename T, typename U>
META_CONCEPT same_as =
META_CONCEPT_BARRIER(META_IS_SAME(T, U));
template <template <typename...> class C, typename... Ts>
META_CONCEPT valid = requires
{
typename C<Ts...>;
};
template <typename T, template <T...> class C, T... Is>
META_CONCEPT valid_i = requires
{
typename C<Is...>;
};
template <typename T>
META_CONCEPT trait = requires
{
typename T::type;
};
template <typename T>
META_CONCEPT invocable = requires
{
typename quote<T::template invoke>;
};
template <typename T>
META_CONCEPT list_like = is_v<T, list>;
// clang-format off
template <typename T>
META_CONCEPT integral = requires
{
typename T::type;
typename T::value_type;
typename T::type::value_type;
}
&& same_as<typename T::value_type, typename T::type::value_type>
#if META_CXX_TRAIT_VARIABLE_TEMPLATES
&& std::is_integral_v<typename T::value_type>
#else
&& std::is_integral<typename T::value_type>::value
#endif
&& requires
{
// { T::value } -> same_as<const typename T::value_type&>;
T::value;
requires same_as<decltype(T::value), const typename T::value_type>;
typename detail::require_constant<decltype(T::value), T::value>;
// { T::type::value } -> same_as<const typename T::value_type&>;
T::type::value;
requires same_as<decltype(T::type::value), const typename T::value_type>;
typename detail::require_constant<decltype(T::type::value), T::type::value>;
requires T::value == T::type::value;
// { T{}() } -> same_as<typename T::value_type>;
T{}();
requires same_as<decltype(T{}()), typename T::value_type>;
typename detail::require_constant<decltype(T{}()), T{}()>;
requires T{}() == T::value;
{ T{} } -> typename T::value_type;
};
// clang-format on
#endif // META_CONCEPT
namespace extension
{
template <META_TYPE_CONSTRAINT(invocable) F, typename L>
struct apply;
}
} // namespace meta
#ifdef __clang__
#pragma GCC diagnostic pop
#endif
#endif

View File

@ -1,61 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Gonzalo Brito Gadeschi 2017.
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
module concepts {
umbrella "concepts"
export *
}
module meta {
umbrella "meta"
export *
}
module range_v3 {
umbrella "range"
export *
exclude header "range/v3/algorithm/tagspec.hpp"
exclude header "range/v3/at.hpp"
exclude header "range/v3/back.hpp"
exclude header "range/v3/begin_end.hpp"
exclude header "range/v3/data.hpp"
exclude header "range/v3/distance.hpp"
exclude header "range/v3/empty.hpp"
exclude header "range/v3/front.hpp"
exclude header "range/v3/getlines.hpp"
exclude header "range/v3/index.hpp"
exclude header "range/v3/istream_range.hpp"
exclude header "range/v3/iterator_range.hpp"
exclude header "range/v3/range_access.hpp"
exclude header "range/v3/range_concepts.hpp"
exclude header "range/v3/range_traits.hpp"
exclude header "range/v3/size.hpp"
exclude header "range/v3/span.hpp"
exclude header "range/v3/to_container.hpp"
exclude header "range/v3/utility/associated_types.hpp"
exclude header "range/v3/utility/basic_iterator.hpp"
exclude header "range/v3/utility/common_iterator.hpp"
exclude header "range/v3/utility/concepts.hpp"
exclude header "range/v3/utility/counted_iterator.hpp"
exclude header "range/v3/utility/dangling.hpp"
exclude header "range/v3/utility/functional.hpp"
exclude header "range/v3/utility/infinity.hpp"
exclude header "range/v3/utility/invoke.hpp"
exclude header "range/v3/utility/iterator_concepts.hpp"
exclude header "range/v3/utility/iterator_traits.hpp"
exclude header "range/v3/utility/iterator.hpp"
exclude header "range/v3/utility/nullptr_v.hpp"
exclude header "range/v3/utility/unreachable.hpp"
exclude header "range/v3/view_adaptor.hpp"
exclude header "range/v3/view_facade.hpp"
exclude header "range/v3/view_interface.hpp"
exclude header "range/v3/view/bounded.hpp"
}

View File

@ -1,42 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_HPP
#define RANGES_V3_ACTION_HPP
#include <range/v3/action/action.hpp>
#include <range/v3/action/adjacent_remove_if.hpp>
#include <range/v3/action/concepts.hpp>
#include <range/v3/action/drop.hpp>
#include <range/v3/action/drop_while.hpp>
#include <range/v3/action/erase.hpp>
#include <range/v3/action/insert.hpp>
#include <range/v3/action/join.hpp>
#include <range/v3/action/push_back.hpp>
#include <range/v3/action/push_front.hpp>
#include <range/v3/action/remove_if.hpp>
#include <range/v3/action/reverse.hpp>
#include <range/v3/action/shuffle.hpp>
#include <range/v3/action/slice.hpp>
#include <range/v3/action/sort.hpp>
#include <range/v3/action/split.hpp>
#include <range/v3/action/split_when.hpp>
#include <range/v3/action/stable_sort.hpp>
#include <range/v3/action/stride.hpp>
#include <range/v3/action/take.hpp>
#include <range/v3/action/take_while.hpp>
#include <range/v3/action/transform.hpp>
#include <range/v3/action/unique.hpp>
#include <range/v3/action/unstable_remove_if.hpp>
#endif

View File

@ -1,125 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_CONTAINER_ACTION_HPP
#define RANGES_V3_CONTAINER_ACTION_HPP
#include <type_traits>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/concepts.hpp>
#include <range/v3/functional/arithmetic.hpp>
#include <range/v3/functional/concepts.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/view/ref.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct action_access
{
template<typename Action>
struct impl
{
// clang-format off
template<typename... Ts, typename A = Action>
static constexpr auto CPP_auto_fun(bind)(Ts &&... ts)
(
return A::bind(static_cast<Ts &&>(ts)...)
)
// clang-format on
};
};
struct make_action_fn
{
template<typename Fun>
constexpr action<Fun> operator()(Fun fun) const
{
return action<Fun>{detail::move(fun)};
}
};
/// \ingroup group-actions
/// \relates make_action_fn
RANGES_INLINE_VARIABLE(make_action_fn, make_action)
template<typename Action>
struct action : pipeable_base
{
private:
Action action_;
friend pipeable_access;
// Piping requires things are passed by value.
template<typename Rng, typename Act>
static auto pipe(Rng && rng, Act && act)
-> CPP_ret(invoke_result_t<Action &, Rng>)( //
requires range<Rng> && invocable<Action &, Rng> &&
(!std::is_reference<Rng>::value))
{
return invoke(act.action_, detail::move(rng));
}
public:
action() = default;
constexpr explicit action(Action a) noexcept(
std::is_nothrow_move_constructible<Action>::value)
: action_(detail::move(a))
{}
// Calling directly requires things are passed by reference.
template<typename Rng, typename... Rest>
auto operator()(Rng & rng, Rest &&... rest) const
-> CPP_ret(invoke_result_t<Action const &, Rng &, Rest...>)( //
requires range<Rng> && invocable<Action const &, Rng &, Rest...>)
{
return invoke(action_, rng, static_cast<Rest &&>(rest)...);
}
// Currying overload.
// clang-format off
template<typename T, typename... Rest, typename A = Action>
auto CPP_auto_fun(operator())(T &&t, Rest &&... rest)(const)
(
return make_action(
action_access::impl<A>::bind(action_,
static_cast<T &&>(t),
static_cast<Rest &&>(rest)...))
)
// clang-format on
};
template<typename Rng, typename Action>
auto operator|=(Rng & rng, Action && action) -> CPP_ret(Rng &)( //
requires is_pipeable<Action>::value && range<Rng &> &&
invocable<bitwise_or, ref_view<Rng>, Action &> && same_as<
ref_view<Rng>, invoke_result_t<bitwise_or, ref_view<Rng>, Action &>>)
{
views::ref(rng) | action;
return rng;
}
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,70 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler
// Copyright Christopher Di Bella
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_ADJACENT_REMOVE_IF_HPP
#define RANGES_V3_ACTION_ADJACENT_REMOVE_IF_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/erase.hpp>
#include <range/v3/algorithm/adjacent_remove_if.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct adjacent_remove_if_fn
{
private:
friend action_access;
template<typename Pred, typename Proj = identity>
static auto CPP_fun(bind)(adjacent_remove_if_fn adjacent_remove_if, Pred pred,
Proj proj = {})( //
requires(!range<Pred>))
{
return bind_back(adjacent_remove_if, std::move(pred), std::move(proj));
}
public:
template<typename Rng, typename Pred, typename Proj = identity>
auto operator()(Rng && rng, Pred pred, Proj proj = {}) const
-> CPP_ret(Rng)( //
requires forward_range<Rng> &&
erasable_range<Rng, iterator_t<Rng>, sentinel_t<Rng>> &&
indirect_relation<Pred, projected<iterator_t<Rng>, Proj>> &&
permutable<iterator_t<Rng>>)
{
auto i = adjacent_remove_if(rng, std::move(pred), std::move(proj));
erase(rng, std::move(i), end(rng));
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \sa action
/// \sa with_braced_init_args
RANGES_INLINE_VARIABLE(action<adjacent_remove_if_fn>, adjacent_remove_if)
} // namespace actions
/// @}
} // namespace ranges
#endif // RANGES_V3_ACTION_ADJACENT_REMOVE_IF_HPP

View File

@ -1,163 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_CONCEPTS_HPP
#define RANGES_V3_ACTION_CONCEPTS_HPP
#include <utility>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
namespace ranges
{
/// \cond
namespace detail
{
template<typename T>
struct movable_input_iterator
{
using iterator_category = std::input_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T *;
using reference = T &&;
movable_input_iterator() = default;
movable_input_iterator & operator++();
movable_input_iterator operator++(int);
bool operator==(movable_input_iterator const &) const;
bool operator!=(movable_input_iterator const &) const;
T && operator*() const;
};
} // namespace detail
/// \endcond
/// \addtogroup group-range
/// @{
// std::array is a semi_container, native arrays are not.
// clang-format off
CPP_def
(
template(typename T)
concept semi_container,
forward_range<T> && default_constructible<uncvref_t<T>> &&
movable<uncvref_t<T>> &&
!view_<T>
);
// std::vector is a container, std::array is not
CPP_def
(
template(typename T)
concept container,
semi_container<T> &&
constructible_from<
uncvref_t<T>,
detail::movable_input_iterator<range_value_t<T>>,
detail::movable_input_iterator<range_value_t<T>>>
);
CPP_def
(
template(typename C)
concept reservable,
requires (C &c, C const &cc, range_size_t<C> s)
(
c.reserve(s),
cc.capacity(),
cc.max_size(),
concepts::requires_<same_as<decltype(cc.capacity()), range_size_t<C>>>,
concepts::requires_<same_as<decltype(cc.max_size()), range_size_t<C>>>
) &&
container<C> && sized_range<C>
);
CPP_def
(
template(typename C, typename I)
concept reservable_with_assign,
requires (C &c, I i)
(
c.assign(i, i)
) &&
reservable<C> && input_iterator<I>
);
CPP_def
(
template(typename C)
concept random_access_reservable,
reservable<C> && random_access_range<C>
);
// clang-format on
/// \cond
namespace detail
{
template<typename T>
auto is_lvalue_container_like(T &) noexcept -> CPP_ret(std::true_type)( //
requires container<T>)
{
return {};
}
template<typename T>
auto is_lvalue_container_like(reference_wrapper<T>) noexcept
-> CPP_ret(meta::not_<std::is_rvalue_reference<T>>)( //
requires container<T>)
{
return {};
}
template<typename T>
auto is_lvalue_container_like(std::reference_wrapper<T>) noexcept
-> CPP_ret(std::true_type)( //
requires container<T>)
{
return {};
}
template<typename T>
auto is_lvalue_container_like(ref_view<T>) noexcept -> CPP_ret(std::true_type)( //
requires container<T>)
{
return {};
}
template<typename T>
using is_lvalue_container_like_t =
decltype(detail::is_lvalue_container_like(std::declval<T>()));
} // namespace detail
/// \endcond
// clang-format off
CPP_def
(
template(typename T)
concept lvalue_container_like,
implicitly_convertible_to<detail::is_lvalue_container_like_t<T>,
std::true_type> &&
forward_range<T>
);
// clang-format on
/// @}
} // namespace ranges
#endif

View File

@ -1,66 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_DROP_HPP
#define RANGES_V3_ACTION_DROP_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/erase.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct drop_fn
{
private:
friend action_access;
template<typename Int>
static auto CPP_fun(bind)(drop_fn drop, Int n)( //
requires integral<Int>)
{
return bind_back(drop, n);
}
public:
template<typename Rng>
auto operator()(Rng && rng, range_difference_t<Rng> n) const
-> CPP_ret(Rng)( //
requires forward_range<Rng> &&
erasable_range<Rng &, iterator_t<Rng>, iterator_t<Rng>>)
{
RANGES_EXPECT(n >= 0);
ranges::actions::erase(
rng, begin(rng), ranges::next(begin(rng), n, end(rng)));
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \relates drop_fn
/// \sa action
RANGES_INLINE_VARIABLE(action<drop_fn>, drop)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,65 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_DROP_WHILE_HPP
#define RANGES_V3_ACTION_DROP_WHILE_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/erase.hpp>
#include <range/v3/algorithm/find_if_not.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct drop_while_fn
{
private:
friend action_access;
template<typename Fun>
static auto CPP_fun(bind)(drop_while_fn drop_while, Fun fun)( //
requires(!range<Fun>))
{
return bind_back(drop_while, std::move(fun));
}
public:
template<typename Rng, typename Fun>
auto operator()(Rng && rng, Fun fun) const -> CPP_ret(Rng)( //
requires forward_range<Rng> &&
indirect_unary_predicate<Fun, iterator_t<Rng>> &&
erasable_range<Rng &, iterator_t<Rng>, iterator_t<Rng>>)
{
ranges::actions::erase(
rng, begin(rng), find_if_not(begin(rng), end(rng), std::move(fun)));
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \relates drop_while_fn
/// \sa action
RANGES_INLINE_VARIABLE(action<drop_while_fn>, drop_while)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,76 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_ERASE_HPP
#define RANGES_V3_ACTION_ERASE_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/insert.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \cond
namespace adl_erase_detail
{
template<typename Cont, typename I, typename S>
auto erase(Cont && cont, I first, S last) //
-> CPP_ret(decltype(unwrap_reference(cont).erase(first, last)))( //
requires lvalue_container_like<Cont> && forward_iterator<I> &&
sentinel_for<S, I>)
{
return unwrap_reference(cont).erase(first, last);
}
struct erase_fn
{
template<typename Rng, typename I, typename S>
auto operator()(Rng && rng, I first, S last) const
-> CPP_ret(decltype(erase((Rng &&) rng, first, last)))( //
requires range<Rng> && forward_iterator<I> && sentinel_for<S, I>)
{
return erase(static_cast<Rng &&>(rng), first, last);
}
};
} // namespace adl_erase_detail
/// \endcond
/// \ingroup group-actions
RANGES_INLINE_VARIABLE(adl_erase_detail::erase_fn, erase)
namespace actions
{
using ranges::erase;
}
/// \addtogroup group-range
/// @{
// clang-format off
CPP_def
(
template(typename Rng, typename I, typename S)
concept erasable_range,
requires (Rng &&rng, I first, S last)
(
ranges::erase(static_cast<Rng &&>(rng), first, last)
) &&
range<Rng>
);
// clang-format on
/// @}
} // namespace ranges
#endif

View File

@ -1,301 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_INSERT_HPP
#define RANGES_V3_ACTION_INSERT_HPP
#include <initializer_list>
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/concepts.hpp>
#include <range/v3/algorithm/max.hpp>
#include <range/v3/iterator/common_iterator.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \cond
namespace adl_insert_detail
{
template<typename Cont, typename... Args>
using insert_result_t = decltype(
unwrap_reference(std::declval<Cont>()).insert(std::declval<Args>()...));
template<typename Cont, typename T>
auto insert(Cont && cont, T && t) -> CPP_ret(insert_result_t<Cont &, T>)( //
requires lvalue_container_like<Cont> &&
(!range<T> && constructible_from<range_value_t<Cont>, T>))
{
return unwrap_reference(cont).insert(static_cast<T &&>(t));
}
template<typename Cont, typename I, typename S>
auto insert(Cont && cont, I i, S j)
-> CPP_ret(insert_result_t<Cont &, detail::cpp17_iterator_t<I, S>,
detail::cpp17_iterator_t<I, S>>)( //
requires lvalue_container_like<Cont> && sentinel_for<S, I> && (!range<S>))
{
return unwrap_reference(cont).insert(detail::cpp17_iterator_t<I, S>{i},
detail::cpp17_iterator_t<I, S>{j});
}
template<typename Cont, typename Rng>
auto insert(Cont && cont, Rng && rng)
-> CPP_ret(insert_result_t<Cont &, detail::range_cpp17_iterator_t<Rng>,
detail::range_cpp17_iterator_t<Rng>>)( //
requires lvalue_container_like<Cont> && range<Rng>)
{
return unwrap_reference(cont).insert(
detail::range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
detail::range_cpp17_iterator_t<Rng>{ranges::end(rng)});
}
template<typename Cont, typename I, typename T>
auto insert(Cont && cont, I p, T && t)
-> CPP_ret(insert_result_t<Cont &, I, T>)( //
requires lvalue_container_like<Cont> && input_iterator<I> &&
(!range<T> && constructible_from<range_value_t<Cont>, T>))
{
return unwrap_reference(cont).insert(p, static_cast<T &&>(t));
}
template<typename Cont, typename I, typename N, typename T>
auto insert(Cont && cont, I p, N n, T && t)
-> CPP_ret(insert_result_t<Cont &, I, N, T>)( //
requires lvalue_container_like<Cont> && input_iterator<I> &&
integral<N> && constructible_from<range_value_t<Cont>, T>)
{
return unwrap_reference(cont).insert(p, n, static_cast<T &&>(t));
}
/// \cond
namespace detail
{
using ranges::detail::cpp17_iterator_t;
using ranges::detail::range_cpp17_iterator_t;
template<typename Cont, typename P>
auto insert_reserve_helper(Cont & cont, P const p,
range_size_t<Cont> const delta)
-> CPP_ret(iterator_t<Cont>)( //
requires container<Cont> && input_iterator<P> &&
random_access_reservable<Cont>)
{
auto const old_size = ranges::size(cont);
auto const max_size = cont.max_size();
RANGES_EXPECT(delta <= max_size - old_size);
auto const new_size = old_size + delta;
auto const old_capacity = cont.capacity();
auto const index = p - ranges::begin(cont);
if(old_capacity < new_size)
{
auto const new_capacity =
(old_capacity <= max_size / 3 * 2)
? ranges::max(old_capacity + old_capacity / 2, new_size)
: max_size;
cont.reserve(new_capacity);
}
return ranges::begin(cont) + index;
}
template<typename Cont, typename P, typename I, typename S>
auto insert_impl(Cont && cont, P p, I i, S j, std::false_type)
-> CPP_ret(decltype(unwrap_reference(cont).insert(
p, cpp17_iterator_t<I, S>{i}, cpp17_iterator_t<I, S>{j})))( //
requires sentinel_for<S, I> && (!range<S>))
{
using C = cpp17_iterator_t<I, S>;
return unwrap_reference(cont).insert(p, C{i}, C{j});
}
template<typename Cont, typename P, typename I, typename S>
auto insert_impl(Cont && cont_, P p, I i, S j, std::true_type)
-> CPP_ret(decltype(unwrap_reference(cont_).insert(
ranges::begin(unwrap_reference(cont_)), cpp17_iterator_t<I, S>{i},
cpp17_iterator_t<I, S>{j})))( //
requires sized_sentinel_for<S, I> && random_access_reservable<Cont> &&
(!range<S>))
{
using C = cpp17_iterator_t<I, S>;
auto && cont = unwrap_reference(cont_);
auto const delta = static_cast<range_size_t<Cont>>(j - i);
auto pos = insert_reserve_helper(cont, std::move(p), delta);
return cont.insert(pos, C{std::move(i)}, C{std::move(j)});
}
template<typename Cont, typename I, typename Rng>
auto insert_impl(Cont && cont, I p, Rng && rng, std::false_type)
-> CPP_ret(decltype(unwrap_reference(cont).insert(
p, range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
range_cpp17_iterator_t<Rng>{ranges::end(rng)})))( //
requires range<Rng>)
{
using C = range_cpp17_iterator_t<Rng>;
return unwrap_reference(cont).insert(
p, C{ranges::begin(rng)}, C{ranges::end(rng)});
}
template<typename Cont, typename I, typename Rng>
auto insert_impl(Cont && cont_, I p, Rng && rng, std::true_type)
-> CPP_ret(decltype(unwrap_reference(cont_).insert(
begin(unwrap_reference(cont_)),
range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
range_cpp17_iterator_t<Rng>{ranges::end(rng)})))( //
requires random_access_reservable<Cont> && sized_range<Rng>)
{
using C = range_cpp17_iterator_t<Rng>;
auto && cont = unwrap_reference(cont_);
auto const delta = static_cast<range_size_t<Cont>>(ranges::size(rng));
auto pos = insert_reserve_helper(cont, std::move(p), delta);
return cont.insert(pos, C{ranges::begin(rng)}, C{ranges::end(rng)});
}
} // namespace detail
/// \endcond
template<typename Cont, typename P, typename I, typename S>
auto insert(Cont && cont, P p, I i, S j) -> CPP_ret(decltype(detail::insert_impl(
static_cast<Cont &&>(cont), std::move(p), std::move(i), std::move(j),
meta::bool_<random_access_reservable<Cont> &&
sized_sentinel_for<S, I>>{})))( //
requires lvalue_container_like<Cont> && input_iterator<P> &&
sentinel_for<S, I> &&
(!range<S>))
{
return detail::insert_impl(static_cast<Cont &&>(cont),
std::move(p),
std::move(i),
std::move(j),
meta::bool_ < random_access_reservable<Cont> &&
sized_sentinel_for<S, I>> {});
}
template<typename Cont, typename I, typename Rng>
auto insert(Cont && cont, I p, Rng && rng)
-> CPP_ret(decltype(detail::insert_impl(
static_cast<Cont &&>(cont), std::move(p), static_cast<Rng &&>(rng),
meta::bool_<random_access_reservable<Cont> && sized_range<Rng>>{})))( //
requires lvalue_container_like<Cont> && input_iterator<I> && range<Rng>)
{
return detail::insert_impl(static_cast<Cont &&>(cont),
std::move(p),
static_cast<Rng &&>(rng),
meta::bool_ < random_access_reservable<Cont> &&
sized_range<Rng>> {});
}
struct insert_fn
{
template<typename Rng, typename... Args>
using insert_result_t =
decltype(insert(std::declval<Rng>(), std::declval<Args>()...));
template<typename Rng, typename T>
auto operator()(Rng && rng, T && t) const
-> CPP_ret(insert_result_t<Rng, T>)( //
requires range<Rng> &&
(!range<T>)&&constructible_from<range_value_t<Rng>, T>)
{
return insert(static_cast<Rng &&>(rng), static_cast<T &&>(t));
}
template<typename Rng, typename Rng2>
auto operator()(Rng && rng, Rng2 && rng2) const
-> CPP_ret(insert_result_t<Rng, Rng2>)( //
requires range<Rng> && range<Rng2>)
{
static_assert(!is_infinite<Rng>::value,
"Attempting to insert an infinite range into a container");
return insert(static_cast<Rng &&>(rng), static_cast<Rng2 &&>(rng2));
}
template<typename Rng, typename T>
auto operator()(Rng && rng, std::initializer_list<T> rng2) const
-> CPP_ret(insert_result_t<Rng, std::initializer_list<T> &>)( //
requires range<Rng>)
{
return insert(static_cast<Rng &&>(rng), rng2);
}
template<typename Rng, typename I, typename S>
auto operator()(Rng && rng, I i, S j) const
-> CPP_ret(insert_result_t<Rng, I, S>)( //
requires range<Rng> && sentinel_for<S, I> && (!range<S>))
{
return insert(static_cast<Rng &&>(rng), std::move(i), std::move(j));
}
template<typename Rng, typename I, typename T>
auto operator()(Rng && rng, I p, T && t) const
-> CPP_ret(insert_result_t<Rng, I, T>)( //
requires range<Rng> && input_iterator<I> &&
(!range<T>)&&constructible_from<range_value_t<Rng>, T>)
{
return insert(
static_cast<Rng &&>(rng), std::move(p), static_cast<T &&>(t));
}
template<typename Rng, typename I, typename Rng2>
auto operator()(Rng && rng, I p, Rng2 && rng2) const
-> CPP_ret(insert_result_t<Rng, I, Rng2>)( //
requires range<Rng> && input_iterator<I> && range<Rng2>)
{
static_assert(!is_infinite<Rng>::value,
"Attempting to insert an infinite range into a container");
return insert(
static_cast<Rng &&>(rng), std::move(p), static_cast<Rng2 &&>(rng2));
}
template<typename Rng, typename I, typename T>
auto operator()(Rng && rng, I p, std::initializer_list<T> rng2) const
-> CPP_ret(insert_result_t<Rng, I, std::initializer_list<T> &>)( //
requires range<Rng> && input_iterator<I>)
{
return insert(static_cast<Rng &&>(rng), std::move(p), rng2);
}
template<typename Rng, typename I, typename N, typename T>
auto operator()(Rng && rng, I p, N n, T && t) const
-> CPP_ret(insert_result_t<Rng, I, N, T>)( //
requires range<Rng> && input_iterator<I> && integral<N> &&
(!range<T>)&&constructible_from<range_value_t<Rng>, T>)
{
return insert(
static_cast<Rng &&>(rng), std::move(p), n, static_cast<T &&>(t));
}
template<typename Rng, typename P, typename I, typename S>
auto operator()(Rng && rng, P p, I i, S j) const
-> CPP_ret(insert_result_t<Rng, P, I, S>)( //
requires range<Rng> && input_iterator<P> && sentinel_for<S, I> &&
(!range<S>))
{
return insert(
static_cast<Rng &&>(rng), std::move(p), std::move(i), std::move(j));
}
};
} // namespace adl_insert_detail
/// \endcond
/// \ingroup group-actions
RANGES_INLINE_VARIABLE(adl_insert_detail::insert_fn, insert)
namespace actions
{
using ranges::insert;
}
} // namespace ranges
#endif

View File

@ -1,65 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_JOIN_HPP
#define RANGES_V3_ACTION_JOIN_HPP
#include <vector>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/concepts.hpp>
#include <range/v3/action/push_back.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
template<typename Rng>
using join_action_value_t_ =
meta::if_c<(bool)ranges::container<range_value_t<Rng>>, range_value_t<Rng>,
std::vector<range_value_t<range_value_t<Rng>>>>;
struct join_fn
{
public:
template<typename Rng>
auto operator()(Rng && rng) const -> CPP_ret(join_action_value_t_<Rng>)( //
requires input_range<Rng> && input_range<range_value_t<Rng>> &&
semiregular<join_action_value_t_<Rng>>)
{
join_action_value_t_<Rng> ret;
auto last = ranges::end(rng);
for(auto it = begin(rng); it != last; ++it)
push_back(ret, *it);
return ret;
}
};
/// \ingroup group-actions
/// \relates join_fn
/// \sa action
RANGES_INLINE_VARIABLE(action<join_fn>, join)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,134 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_PUSH_BACK_HPP
#define RANGES_V3_ACTION_PUSH_BACK_HPP
#include <utility>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/insert.hpp>
#include <range/v3/detail/with_braced_init_args.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \cond
namespace adl_push_back_detail
{
template<typename Cont, typename T>
using push_back_t = decltype(static_cast<void>(
unwrap_reference(std::declval<Cont &>()).push_back(std::declval<T>())));
template<typename Cont, typename Rng>
using insert_t = decltype(static_cast<void>(
ranges::insert(std::declval<Cont &>(), std::declval<sentinel_t<Cont>>(),
std::declval<Rng>())));
template<typename Cont, typename T>
auto push_back(Cont && cont, T && t) -> CPP_ret(push_back_t<Cont, T>)( //
requires lvalue_container_like<Cont> &&
(!range<T>)&&constructible_from<range_value_t<Cont>, T>)
{
unwrap_reference(cont).push_back(static_cast<T &&>(t));
}
template<typename Cont, typename Rng>
auto push_back(Cont && cont, Rng && rng) -> CPP_ret(insert_t<Cont, Rng>)( //
requires lvalue_container_like<Cont> && range<Rng>)
{
ranges::insert(cont, end(cont), static_cast<Rng &&>(rng));
}
/// \cond
// clang-format off
CPP_def
(
template(typename Rng, typename T)
concept can_push_back_,
requires (Rng &&rng, T &&t)
(
push_back(rng, (T &&) t)
)
);
// clang-format on
/// \endcond
struct push_back_fn
{
private:
friend actions::action_access;
template<typename T>
static auto bind(push_back_fn push_back, T && val)
{
return bind_back(push_back, static_cast<T &&>(val));
}
#ifdef RANGES_WORKAROUND_MSVC_OLD_LAMBDA
template<typename T, std::size_t N>
struct lamduh
{
T (&val_)[N];
template<typename Rng>
auto operator()(Rng && rng) const
-> invoke_result_t<push_back_fn, Rng, T (&)[N]>
{
return push_back_fn{}(static_cast<Rng &&>(rng), val_);
}
};
template<typename T, std::size_t N>
static lamduh<T, N> bind(push_back_fn, T (&val)[N])
{
return {val};
}
#else // ^^^ workaround / no workaround vvv
template<typename T, std::size_t N>
static auto bind(push_back_fn, T (&val)[N])
{
return [&val](auto && rng)
-> invoke_result_t<push_back_fn, decltype(rng), T(&)[N]>
{
return push_back_fn{}(static_cast<decltype(rng)>(rng), val);
};
}
#endif // RANGES_WORKAROUND_MSVC_OLD_LAMBDA
public:
template<typename Rng, typename T>
auto operator()(Rng && rng, T && t) const -> CPP_ret(Rng)( //
requires input_range<Rng> && can_push_back_<Rng, T> &&
(range<T> || constructible_from<range_value_t<Rng>, T>))
{
push_back(rng, static_cast<T &&>(t));
return static_cast<Rng &&>(rng);
}
};
} // namespace adl_push_back_detail
/// \endcond
namespace actions
{
/// \ingroup group-actions
RANGES_INLINE_VARIABLE(
detail::with_braced_init_args<action<adl_push_back_detail::push_back_fn>>,
push_back)
} // namespace actions
using actions::push_back;
} // namespace ranges
#endif

View File

@ -1,132 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_PUSH_FRONT_HPP
#define RANGES_V3_ACTION_PUSH_FRONT_HPP
#include <utility>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/insert.hpp>
#include <range/v3/detail/with_braced_init_args.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \cond
namespace adl_push_front_detail
{
template<typename Cont, typename T>
using push_front_t = decltype(static_cast<void>(
unwrap_reference(std::declval<Cont &>()).push_front(std::declval<T>())));
template<typename Cont, typename Rng>
using insert_t = decltype(static_cast<void>(
ranges::insert(std::declval<Cont &>(), std::declval<iterator_t<Cont>>(),
std::declval<Rng>())));
template<typename Cont, typename T>
auto push_front(Cont && cont, T && t) -> CPP_ret(push_front_t<Cont, T>)( //
requires lvalue_container_like<Cont> &&
(!range<T>)&&constructible_from<range_value_t<Cont>, T>)
{
unwrap_reference(cont).push_front(static_cast<T &&>(t));
}
template<typename Cont, typename Rng>
auto push_front(Cont && cont, Rng && rng) -> CPP_ret(insert_t<Cont, Rng>)( //
requires lvalue_container_like<Cont> && range<Rng>)
{
ranges::insert(cont, begin(cont), static_cast<Rng &&>(rng));
}
// clang-format off
CPP_def
(
template(typename Rng, typename T)
concept can_push_front_,
requires (Rng &&rng, T &&t)
(
push_front(rng, (T &&) t)
)
);
// clang-format on
struct push_front_fn
{
private:
friend actions::action_access;
template<typename T>
static auto bind(push_front_fn push_front, T && val)
{
return bind_back(push_front, static_cast<T &&>(val));
}
#ifdef RANGES_WORKAROUND_MSVC_OLD_LAMBDA
template<typename T, std::size_t N>
struct lamduh
{
T (&val_)[N];
template<typename Rng>
auto operator()(Rng && rng) const
-> invoke_result_t<push_front_fn, Rng, T (&)[N]>
{
return push_front_fn{}(static_cast<Rng &&>(rng), val_);
}
};
template<typename T, std::size_t N>
static lamduh<T, N> bind(push_front_fn, T (&val)[N])
{
return {val};
}
#else // ^^^ workaround / no workaround vvv
template<typename T, std::size_t N>
static auto bind(push_front_fn, T (&val)[N])
{
return [&val](auto && rng)
-> invoke_result_t<push_front_fn, decltype(rng), T(&)[N]>
{
return push_front_fn{}(static_cast<decltype(rng)>(rng), val);
};
}
#endif // RANGES_WORKAROUND_MSVC_OLD_LAMBDA
public:
template<typename Rng, typename T>
auto operator()(Rng && rng, T && t) const -> CPP_ret(Rng)( //
requires input_range<Rng> && can_push_front_<Rng, T> &&
(range<T> || constructible_from<range_value_t<Rng>, T>))
{
push_front(rng, static_cast<T &&>(t));
return static_cast<Rng &&>(rng);
}
};
} // namespace adl_push_front_detail
/// \endcond
namespace actions
{
/// \ingroup group-actions
RANGES_INLINE_VARIABLE(
detail::with_braced_init_args<action<adl_push_front_detail::push_front_fn>>,
push_front)
} // namespace actions
using actions::push_front;
} // namespace ranges
#endif

View File

@ -1,72 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Andrey Diduh 2019
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_REMOVE_HPP
#define RANGES_V3_ACTION_REMOVE_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/erase.hpp>
#include <range/v3/algorithm/remove.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct remove_fn
{
private:
friend action_access;
template<typename V, typename P>
static auto CPP_fun(bind)(remove_fn remove, V && value, P proj)( //
requires(!range<V>))
{
return bind_back(remove, static_cast<V &&>(value), std::move(proj));
}
template<typename V>
static auto bind(remove_fn remove, V && value)
{
return bind_back(remove, static_cast<V &&>(value), identity{});
}
public:
template<typename Rng, typename V, typename P = identity>
auto operator()(Rng && rng, V const & value, P proj = {}) const
-> CPP_ret(Rng)( //
requires forward_range<Rng> && permutable<iterator_t<Rng>> &&
erasable_range<Rng, iterator_t<Rng>, sentinel_t<Rng>> &&
indirect_relation<equal_to, projected<iterator_t<Rng>, P>,
V const *>)
{
auto it = ranges::remove(rng, value, std::move(proj));
ranges::erase(rng, it, ranges::end(rng));
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \sa action
/// \sa with_braced_init_args
RANGES_INLINE_VARIABLE(action<remove_fn>, remove)
} // namespace actions
/// @}
} // namespace ranges
#endif // include guard

View File

@ -1,69 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_REMOVE_IF_HPP
#define RANGES_V3_ACTION_REMOVE_IF_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/erase.hpp>
#include <range/v3/algorithm/remove_if.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
// TODO Look at all the special cases handled by erase_if in Library Fundamentals 2
/// \addtogroup group-actions
/// @{
namespace actions
{
struct remove_if_fn
{
private:
friend action_access;
template<typename C, typename P = identity>
static auto CPP_fun(bind)(remove_if_fn remove_if, C pred, P proj = P{})( //
requires(!range<C>))
{
return bind_back(remove_if, std::move(pred), std::move(proj));
}
public:
template<typename Rng, typename C, typename P = identity>
auto operator()(Rng && rng, C pred, P proj = P{}) const -> CPP_ret(Rng)( //
requires forward_range<Rng> &&
erasable_range<Rng &, iterator_t<Rng>, iterator_t<Rng>> &&
permutable<iterator_t<Rng>> &&
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>)
{
auto it = ranges::remove_if(rng, std::move(pred), std::move(proj));
ranges::erase(rng, it, ranges::end(rng));
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \sa action
RANGES_INLINE_VARIABLE(action<remove_if_fn>, remove_if)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,56 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
// Copyright Gonzalo Brito Gadeschi 2017
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_REVERSE_HPP
#define RANGES_V3_ACTION_REVERSE_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/algorithm/reverse.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
/// Reversed the source range in-place.
struct reverse_fn
{
private:
friend action_access;
public:
template<typename Rng>
auto operator()(Rng && rng) const -> CPP_ret(Rng)( //
requires bidirectional_range<Rng> && permutable<iterator_t<Rng>>)
{
ranges::reverse(rng);
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \relates reverse_fn
/// \sa action
RANGES_INLINE_VARIABLE(action<reverse_fn>, reverse)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,96 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Filip Matzner 2015
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_SHUFFLE_HPP
#define RANGES_V3_ACTION_SHUFFLE_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/algorithm/shuffle.hpp>
#include <range/v3/functional/bind.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct shuffle_fn
{
private:
friend action_access;
template<typename Gen>
static auto CPP_fun(bind)(shuffle_fn shuffle, Gen && gen)( //
requires uniform_random_bit_generator<Gen>)
{
return bind_back(shuffle, static_cast<Gen &&>(gen));
}
#ifdef RANGES_WORKAROUND_MSVC_OLD_LAMBDA
template<typename Gen>
struct lamduh
{
Gen & gen_;
template<typename Rng>
auto operator()(Rng && rng) const
-> invoke_result_t<shuffle_fn, Rng, Gen &>
{
return shuffle_fn{}(static_cast<Rng &&>(rng), gen_);
}
};
template<typename Gen>
static lamduh<Gen> CPP_fun(bind)(shuffle_fn, Gen & gen)( //
requires uniform_random_bit_generator<Gen>)
{
return {gen};
}
#else // ^^^ workaround / no workaround vvv
template<typename Gen>
static auto CPP_fun(bind)(shuffle_fn, Gen & gen)( //
requires uniform_random_bit_generator<Gen>)
{
return [&gen](auto && rng)
-> invoke_result_t<shuffle_fn, decltype(rng), Gen &> {
return shuffle_fn{}(static_cast<decltype(rng)>(rng), gen);
};
}
#endif // RANGES_WORKAROUND_MSVC_OLD_LAMBDA
public:
template<typename Rng, typename Gen>
auto operator()(Rng && rng, Gen && gen) const -> CPP_ret(Rng)( //
requires random_access_range<Rng> && permutable<iterator_t<Rng>> &&
uniform_random_bit_generator<std::remove_reference_t<Gen>> &&
convertible_to<invoke_result_t<Gen &>, range_difference_t<Rng>>)
{
ranges::shuffle(rng, static_cast<Gen &&>(gen));
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \relates shuffle_fn
/// \sa `action`
RANGES_INLINE_VARIABLE(action<shuffle_fn>, shuffle)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,154 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_SLICE_HPP
#define RANGES_V3_ACTION_SLICE_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/erase.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/view/interface.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct slice_fn
{
private:
friend action_access;
template<typename D>
using diff_t = range_difference_t<D>;
// Overloads for the pipe syntax: rng | actions::slice(from, to)
template<typename D>
static auto CPP_fun(bind)(slice_fn slice, D from, D to)( //
requires integral<D>)
{
return bind_back(slice, from, to);
}
template<typename D>
static auto CPP_fun(bind)(slice_fn slice, D from, detail::from_end_<D> to)( //
requires integral<D>)
{
return bind_back(slice, from, to);
}
template<typename D>
static auto CPP_fun(bind)(slice_fn slice, detail::from_end_<D> from,
detail::from_end_<D> to)( //
requires integral<D>)
{
return bind_back(slice, from, to);
}
template<typename D>
static auto CPP_fun(bind)(slice_fn slice, D from, end_fn const & to)( //
requires integral<D>)
{
return bind_back(slice, from, to);
}
template<typename D>
static auto CPP_fun(bind)(slice_fn slice, detail::from_end_<D> from,
end_fn const & to)( //
requires integral<D>)
{
return bind_back(slice, from, to);
}
public:
template<typename Rng, typename I = iterator_t<Rng>>
auto operator()(Rng && rng, diff_t<Rng> from, diff_t<Rng> to) const
-> CPP_ret(Rng)( //
requires forward_range<Rng> && erasable_range<Rng &, I, I>)
{
RANGES_EXPECT(0 <= from && 0 <= to && from <= to);
RANGES_EXPECT(!sized_range<Rng> || to <= distance(rng));
ranges::actions::erase(rng, begin(rng), next(begin(rng), from));
ranges::actions::erase(rng, next(begin(rng), to - from), end(rng));
return static_cast<Rng &&>(rng);
}
template<typename Rng, typename I = iterator_t<Rng>>
auto operator()(Rng && rng, diff_t<Rng> from,
detail::from_end_<diff_t<Rng>> to) const -> CPP_ret(Rng)( //
requires bidirectional_range<Rng> && erasable_range<Rng &, I, I>)
{
RANGES_EXPECT(0 <= from && to.dist_ <= 0);
RANGES_EXPECT(!sized_range<Rng> || from - to.dist_ <= distance(rng));
ranges::actions::erase(rng, begin(rng), next(begin(rng), from));
if(to.dist_ != 0)
{
auto const last = next(begin(rng), end(rng));
ranges::actions::erase(rng, prev(last, -to.dist_), last);
}
return static_cast<Rng &&>(rng);
}
template<typename Rng, typename I = iterator_t<Rng>>
auto operator()(Rng && rng, detail::from_end_<diff_t<Rng>> from,
detail::from_end_<diff_t<Rng>> to) const -> CPP_ret(Rng)( //
requires bidirectional_range<Rng> && erasable_range<Rng &, I, I>)
{
RANGES_EXPECT(from.dist_ <= 0 && to.dist_ <= 0 && from.dist_ <= to.dist_);
RANGES_EXPECT(!sized_range<Rng> || 0 <= distance(rng) + from.dist_);
auto last = next(begin(rng), end(rng));
ranges::actions::erase(rng, prev(last, -to.dist_), last);
last = next(begin(rng), end(rng));
ranges::actions::erase(
rng, begin(rng), prev(last, to.dist_ - from.dist_));
return static_cast<Rng &&>(rng);
}
template<typename Rng, typename I = iterator_t<Rng>>
auto operator()(Rng && rng, diff_t<Rng> from, end_fn const &) const
-> CPP_ret(Rng)( //
requires forward_range<Rng> && erasable_range<Rng &, I, I>)
{
RANGES_EXPECT(0 <= from);
RANGES_EXPECT(!sized_range<Rng> || from <= distance(rng));
ranges::actions::erase(rng, begin(rng), next(begin(rng), from));
return static_cast<Rng &&>(rng);
}
template<typename Rng, typename I = iterator_t<Rng>>
auto operator()(Rng && rng, detail::from_end_<diff_t<Rng>> from,
end_fn const &) const -> CPP_ret(Rng)( //
requires bidirectional_range<Rng> && erasable_range<Rng &, I, I>)
{
RANGES_EXPECT(from.dist_ <= 0);
RANGES_EXPECT(!sized_range<Rng> || 0 <= distance(rng) + from.dist_);
auto const last = next(begin(rng), end(rng));
ranges::actions::erase(rng, begin(rng), prev(last, -from.dist_));
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \relates slice_fn
/// \sa action
RANGES_INLINE_VARIABLE(action<slice_fn>, slice)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,64 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_SORT_HPP
#define RANGES_V3_ACTION_SORT_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/algorithm/sort.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct sort_fn
{
private:
friend action_access;
template<typename C, typename P = identity>
static auto CPP_fun(bind)(sort_fn sort, C pred, P proj = {})( //
requires(!range<C>))
{
return bind_back(sort, std::move(pred), std::move(proj));
}
public:
template<typename Rng, typename C = less, typename P = identity>
auto operator()(Rng && rng, C pred = {}, P proj = {}) const
-> CPP_ret(Rng)( //
requires forward_range<Rng> && sortable<iterator_t<Rng>, C, P>)
{
ranges::sort(rng, std::move(pred), std::move(proj));
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \relates sort_fn
/// \sa `action`
RANGES_INLINE_VARIABLE(action<sort_fn>, sort)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,78 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_SPLIT_HPP
#define RANGES_V3_ACTION_SPLIT_HPP
#include <vector>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/concepts.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/view/split.hpp>
#include <range/v3/view/transform.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct split_fn
{
private:
template<typename Rng>
using split_value_t = meta::if_c<(bool)ranges::container<Rng>, uncvref_t<Rng>,
std::vector<range_value_t<Rng>>>;
public:
// BUGBUG something is not right with the actions. It should be possible
// to move a container into a split and have elements moved into the result.
template<typename Rng>
auto operator()(Rng && rng, range_value_t<Rng> val) const
-> CPP_ret(std::vector<split_value_t<Rng>>)( //
requires input_range<Rng> && indirectly_comparable<
iterator_t<Rng>, range_value_t<Rng> const *, ranges::equal_to>)
{
return views::split(rng, std::move(val)) |
views::transform(to<split_value_t<Rng>>()) | to_vector;
}
template<typename Rng, typename Pattern>
auto operator()(Rng && rng, Pattern && pattern) const
-> CPP_ret(std::vector<split_value_t<Rng>>)( //
requires input_range<Rng> && viewable_range<Pattern> &&
forward_range<Pattern> && indirectly_comparable<
iterator_t<Rng>, iterator_t<Pattern>, ranges::equal_to> &&
(forward_range<Rng> || detail::tiny_range<Pattern>))
{
return views::split(rng, static_cast<Pattern &&>(pattern)) |
views::transform(to<split_value_t<Rng>>()) | to_vector;
}
};
/// \ingroup group-actions
/// \relates split_fn
/// \sa action
RANGES_INLINE_VARIABLE(action<split_fn>, split)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,81 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_SPLIT_WHEN_HPP
#define RANGES_V3_ACTION_SPLIT_WHEN_HPP
#include <vector>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/concepts.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/view/split_when.hpp>
#include <range/v3/view/transform.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct split_when_fn
{
private:
template<typename Rng>
using split_value_t = meta::if_c<(bool)ranges::container<Rng>, uncvref_t<Rng>,
std::vector<range_value_t<Rng>>>;
public:
// BUGBUG something is not right with the actions. It should be possible
// to move a container into a split and have elements moved into the result.
template<typename Rng, typename Fun>
auto operator()(Rng && rng, Fun fun) const //
-> CPP_ret(std::vector<split_value_t<Rng>>)( //
requires forward_range<Rng> && //
invocable<Fun &, iterator_t<Rng>, sentinel_t<Rng>> && invocable<
Fun &, iterator_t<Rng>, iterator_t<Rng>> &&
copy_constructible<Fun> && convertible_to<
invoke_result_t<Fun &, iterator_t<Rng>, sentinel_t<Rng>>,
std::pair<bool, iterator_t<Rng>>>)
{
return views::split_when(rng, std::move(fun)) |
views::transform(to<split_value_t<Rng>>()) | to_vector;
}
template<typename Rng, typename Fun>
auto operator()(Rng && rng, Fun fun) const
-> CPP_ret(std::vector<split_value_t<Rng>>)( //
requires forward_range<Rng> && predicate<
Fun const &, range_reference_t<Rng>> && copy_constructible<Fun>)
{
return views::split_when(rng, std::move(fun)) |
views::transform(to<split_value_t<Rng>>()) | to_vector;
}
};
/// \ingroup group-actions
/// \relates split_fn
/// \sa action
RANGES_INLINE_VARIABLE(action<split_when_fn>, split_when)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,65 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_STABLE_SORT_HPP
#define RANGES_V3_ACTION_STABLE_SORT_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/algorithm/stable_sort.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct stable_sort_fn
{
private:
friend action_access;
template<typename C, typename P = identity>
static auto CPP_fun(bind)(stable_sort_fn stable_sort, C pred,
P proj = P{})( //
requires(!range<C>))
{
return bind_back(stable_sort, std::move(pred), std::move(proj));
}
public:
template<typename Rng, typename C = less, typename P = identity>
auto operator()(Rng && rng, C pred = C{}, P proj = P{}) const
-> CPP_ret(Rng)( //
requires forward_range<Rng> && sortable<iterator_t<Rng>, C, P>)
{
ranges::stable_sort(rng, std::move(pred), std::move(proj));
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \relates stable_sort_fn
/// \sa action
RANGES_INLINE_VARIABLE(action<stable_sort_fn>, stable_sort)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,81 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_STRIDE_HPP
#define RANGES_V3_ACTION_STRIDE_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/erase.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct stride_fn
{
private:
friend action_access;
template<typename D>
static auto CPP_fun(bind)(stride_fn stride, D step)( //
requires integral<D>)
{
return bind_back(stride, step);
}
public:
template<typename Rng, typename D = range_difference_t<Rng>>
auto operator()(Rng && rng, range_difference_t<Rng> const step) const
-> CPP_ret(Rng)( //
requires forward_range<Rng> &&
erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>> &&
permutable<iterator_t<Rng>>)
{
using I = iterator_t<Rng>;
using S = sentinel_t<Rng>;
RANGES_EXPECT(0 < step);
if(1 < step)
{
I first = ranges::begin(rng);
S const last = ranges::end(rng);
if(first != last)
{
for(I i = ranges::next(++first, step - 1, last); i != last;
advance(i, step, last), ++first)
{
*first = iter_move(i);
}
}
ranges::actions::erase(rng, first, last);
}
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \relates stride_fn
/// \sa action
RANGES_INLINE_VARIABLE(action<stride_fn>, stride)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,66 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_TAKE_HPP
#define RANGES_V3_ACTION_TAKE_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/erase.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct take_fn
{
private:
friend action_access;
template<typename Int>
static auto CPP_fun(bind)(take_fn take, Int n)( //
requires integral<Int>)
{
return bind_back(take, n);
}
public:
template<typename Rng>
auto operator()(Rng && rng, range_difference_t<Rng> n) const
-> CPP_ret(Rng)( //
requires forward_range<Rng> &&
erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>>)
{
RANGES_EXPECT(n >= 0);
ranges::actions::erase(
rng, ranges::next(begin(rng), n, end(rng)), end(rng));
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \relates take_fn
/// \sa action
RANGES_INLINE_VARIABLE(action<take_fn>, take)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,65 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_TAKE_WHILE_HPP
#define RANGES_V3_ACTION_TAKE_WHILE_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/erase.hpp>
#include <range/v3/algorithm/find_if_not.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct take_while_fn
{
private:
friend action_access;
template<typename Fun>
static auto CPP_fun(bind)(take_while_fn take_while, Fun fun)( //
requires(!range<Fun>))
{
return bind_back(take_while, std::move(fun));
}
public:
template<typename Rng, typename Fun>
auto operator()(Rng && rng, Fun fun) const -> CPP_ret(Rng)( //
requires forward_range<Rng> &&
erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>> &&
indirect_unary_predicate<Fun, iterator_t<Rng>>)
{
ranges::actions::erase(
rng, find_if_not(begin(rng), end(rng), std::move(fun)), end(rng));
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \relates take_while_fn
/// \sa action
RANGES_INLINE_VARIABLE(action<take_while_fn>, take_while)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,64 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_TRANSFORM_HPP
#define RANGES_V3_ACTION_TRANSFORM_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/algorithm/transform.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct transform_fn
{
private:
friend action_access;
template<typename F, typename P = identity>
static auto CPP_fun(bind)(transform_fn transform, F fun, P proj = P{})( //
requires(!range<F>))
{
return bind_back(transform, std::move(fun), std::move(proj));
}
public:
template<typename Rng, typename F, typename P = identity>
auto operator()(Rng && rng, F fun, P proj = P{}) const -> CPP_ret(Rng)( //
requires input_range<Rng> && copy_constructible<F> &&
writable<iterator_t<Rng>,
indirect_result_t<F &, projected<iterator_t<Rng>, P>>>)
{
ranges::transform(rng, begin(rng), std::move(fun), std::move(proj));
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \relates transform_fn
/// \sa action
RANGES_INLINE_VARIABLE(action<transform_fn>, transform)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,68 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_UNIQUE_HPP
#define RANGES_V3_ACTION_UNIQUE_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/erase.hpp>
#include <range/v3/algorithm/unique.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct unique_fn
{
private:
friend action_access;
template<typename C, typename P = identity>
static auto CPP_fun(bind)(unique_fn unique, C pred, P proj = P{})( //
requires(!range<C>))
{
return bind_back(unique, std::move(pred), std::move(proj));
}
public:
template<typename Rng, typename C = equal_to, typename P = identity>
auto operator()(Rng && rng, C pred = C{}, P proj = P{}) const
-> CPP_ret(Rng)( //
requires forward_range<Rng> &&
erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>> &&
sortable<iterator_t<Rng>, C, P>)
{
auto it = ranges::unique(rng, std::move(pred), std::move(proj));
ranges::erase(rng, it, end(rng));
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \relates unique_fn
/// \sa action
RANGES_INLINE_VARIABLE(action<unique_fn>, unique)
} // namespace actions
/// @}
} // namespace ranges
#endif

View File

@ -1,74 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Andrey Diduh 2019
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ACTION_UNSTABLE_REMOVE_IF_HPP
#define RANGES_V3_ACTION_UNSTABLE_REMOVE_IF_HPP
#include <utility>
#include <concepts/concepts.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/action/action.hpp>
#include <range/v3/action/erase.hpp>
#include <range/v3/algorithm/unstable_remove_if.hpp>
#include <range/v3/functional/bind_back.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
namespace ranges
{
/// \addtogroup group-actions
/// @{
namespace actions
{
struct unstable_remove_if_fn
{
private:
friend action_access;
template<typename C, typename P = identity>
static auto CPP_fun(bind)(unstable_remove_if_fn unstable_remove_if, C pred,
P proj = P{})( //
requires(!range<C>))
{
return bind_back(unstable_remove_if, std::move(pred), std::move(proj));
}
public:
template<typename Rng, typename C, typename P = identity>
auto operator()(Rng && rng, C pred, P proj = P{}) const -> CPP_ret(Rng)( //
requires bidirectional_range<Rng> && common_range<Rng> &&
permutable<iterator_t<Rng>> &&
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>> &&
erasable_range<Rng, iterator_t<Rng>, iterator_t<Rng>>)
{
auto it = ranges::unstable_remove_if(ranges::begin(rng),
ranges::end(rng),
std::move(pred),
std::move(proj));
ranges::erase(rng, it, ranges::end(rng));
return static_cast<Rng &&>(rng);
}
};
/// \ingroup group-actions
/// \sa `action`
/// \sa `actions::unstable_remove_if_fn`
RANGES_INLINE_VARIABLE(action<unstable_remove_if_fn>, unstable_remove_if)
} // namespace actions
/// @}
} // namespace ranges
#endif // RANGES_V3_ACTION_UNSTABLE_REMOVE_IF_HPP

View File

@ -1,108 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ALGORITHM_HPP
#define RANGES_V3_ALGORITHM_HPP
#include <range/v3/detail/config.hpp>
RANGES_DISABLE_WARNINGS
#include <range/v3/algorithm/adjacent_find.hpp>
#include <range/v3/algorithm/adjacent_remove_if.hpp>
#include <range/v3/algorithm/all_of.hpp>
#include <range/v3/algorithm/any_of.hpp>
#include <range/v3/algorithm/binary_search.hpp>
#include <range/v3/algorithm/copy.hpp>
#include <range/v3/algorithm/copy_backward.hpp>
#include <range/v3/algorithm/copy_if.hpp>
#include <range/v3/algorithm/copy_n.hpp>
#include <range/v3/algorithm/count.hpp>
#include <range/v3/algorithm/count_if.hpp>
#include <range/v3/algorithm/ends_with.hpp>
#include <range/v3/algorithm/equal.hpp>
#include <range/v3/algorithm/equal_range.hpp>
#include <range/v3/algorithm/fill.hpp>
#include <range/v3/algorithm/fill_n.hpp>
#include <range/v3/algorithm/find.hpp>
#include <range/v3/algorithm/find_end.hpp>
#include <range/v3/algorithm/find_first_of.hpp>
#include <range/v3/algorithm/find_if.hpp>
#include <range/v3/algorithm/find_if_not.hpp>
#include <range/v3/algorithm/for_each.hpp>
#include <range/v3/algorithm/for_each_n.hpp>
#include <range/v3/algorithm/generate.hpp>
#include <range/v3/algorithm/generate_n.hpp>
#include <range/v3/algorithm/heap_algorithm.hpp>
#include <range/v3/algorithm/inplace_merge.hpp>
#include <range/v3/algorithm/is_partitioned.hpp>
#include <range/v3/algorithm/is_sorted.hpp>
#include <range/v3/algorithm/is_sorted_until.hpp>
#include <range/v3/algorithm/lexicographical_compare.hpp>
#include <range/v3/algorithm/lower_bound.hpp>
#include <range/v3/algorithm/max.hpp>
#include <range/v3/algorithm/max_element.hpp>
#include <range/v3/algorithm/merge.hpp>
#include <range/v3/algorithm/min.hpp>
#include <range/v3/algorithm/min_element.hpp>
#include <range/v3/algorithm/minmax.hpp>
#include <range/v3/algorithm/minmax_element.hpp>
#include <range/v3/algorithm/mismatch.hpp>
#include <range/v3/algorithm/move.hpp>
#include <range/v3/algorithm/move_backward.hpp>
#include <range/v3/algorithm/none_of.hpp>
#include <range/v3/algorithm/nth_element.hpp>
#include <range/v3/algorithm/partial_sort.hpp>
#include <range/v3/algorithm/partial_sort_copy.hpp>
#include <range/v3/algorithm/partition.hpp>
#include <range/v3/algorithm/partition_copy.hpp>
#include <range/v3/algorithm/partition_point.hpp>
#include <range/v3/algorithm/permutation.hpp>
#include <range/v3/algorithm/remove.hpp>
#include <range/v3/algorithm/remove_copy.hpp>
#include <range/v3/algorithm/remove_copy_if.hpp>
#include <range/v3/algorithm/remove_if.hpp>
#include <range/v3/algorithm/replace.hpp>
#include <range/v3/algorithm/replace_copy.hpp>
#include <range/v3/algorithm/replace_copy_if.hpp>
#include <range/v3/algorithm/replace_if.hpp>
#include <range/v3/algorithm/reverse.hpp>
#include <range/v3/algorithm/reverse_copy.hpp>
#include <range/v3/algorithm/rotate.hpp>
#include <range/v3/algorithm/rotate_copy.hpp>
#include <range/v3/algorithm/sample.hpp>
#include <range/v3/algorithm/search.hpp>
#include <range/v3/algorithm/search_n.hpp>
#include <range/v3/algorithm/set_algorithm.hpp>
#include <range/v3/algorithm/shuffle.hpp>
#include <range/v3/algorithm/sort.hpp>
#include <range/v3/algorithm/stable_partition.hpp>
#include <range/v3/algorithm/stable_sort.hpp>
#include <range/v3/algorithm/starts_with.hpp>
#include <range/v3/algorithm/swap_ranges.hpp>
#include <range/v3/algorithm/transform.hpp>
#include <range/v3/algorithm/unique.hpp>
#include <range/v3/algorithm/unique_copy.hpp>
#include <range/v3/algorithm/unstable_remove_if.hpp>
#include <range/v3/algorithm/upper_bound.hpp>
// BUGBUG
#include <range/v3/algorithm/aux_/equal_range_n.hpp>
#include <range/v3/algorithm/aux_/lower_bound_n.hpp>
#include <range/v3/algorithm/aux_/merge_n.hpp>
#include <range/v3/algorithm/aux_/merge_n_with_buffer.hpp>
#include <range/v3/algorithm/aux_/sort_n_with_buffer.hpp>
#include <range/v3/algorithm/aux_/upper_bound_n.hpp>
RANGES_RE_ENABLE_WARNINGS
#endif

View File

@ -1,73 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ALGORITHM_ADJACENT_FIND_HPP
#define RANGES_V3_ALGORITHM_ADJACENT_FIND_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_BEGIN_NIEBLOID(adjacent_find)
/// \brief function template \c adjacent_find
///
/// range-based version of the \c adjacent_find std algorithm
///
/// \pre `Rng` is a model of the `Range` concept
/// \pre `C` is a model of the `BinaryPredicate` concept
template<typename I, typename S, typename C = equal_to, typename P = identity>
auto RANGES_FUN_NIEBLOID(adjacent_find)(
I first, S last, C pred = C{}, P proj = P{}) //
->CPP_ret(I)( //
requires forward_iterator<I> && sentinel_for<S, I> &&
indirect_relation<C, projected<I, P>>)
{
if(first == last)
return first;
auto inext = first;
for(; ++inext != last; first = inext)
if(invoke(pred, invoke(proj, *first), invoke(proj, *inext)))
return first;
return inext;
}
/// \overload
template<typename Rng, typename C = equal_to, typename P = identity>
auto RANGES_FUN_NIEBLOID(adjacent_find)(Rng && rng, C pred = C{}, P proj = P{}) //
->CPP_ret(safe_iterator_t<Rng>)( //
requires forward_range<Rng> &&
indirect_relation<C, projected<iterator_t<Rng>, P>>)
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_END_NIEBLOID(adjacent_find)
namespace cpp20
{
using ranges::adjacent_find;
}
/// @}
} // namespace ranges
#endif // RANGE_ALGORITHM_ADJACENT_FIND_HPP

View File

@ -1,91 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler
// Copyright Christopher Di Bella
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ALGORITHM_ADJACENT_REMOVE_IF_HPP
#define RANGES_V3_ALGORITHM_ADJACENT_REMOVE_IF_HPP
#include <functional>
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/adjacent_find.hpp>
#include <range/v3/algorithm/move.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/move.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_BEGIN_NIEBLOID(adjacent_remove_if)
/// \brief function \c adjacent_remove_if
///
/// range-based version of the \c adjacent_remove_if algorithm
///
/// \pre `Rng` is a model of the `forward_range` concept.
/// \pre `Pred` is a model of the `BinaryPredicate` concept.
template<typename I, typename S, typename Pred, typename Proj = identity>
auto RANGES_FUN_NIEBLOID(adjacent_remove_if)(
I first, S last, Pred pred = {}, Proj proj = {})
->CPP_ret(I)( //
requires permutable<I> && sentinel_for<S, I> &&
indirect_relation<Pred, projected<I, Proj>>)
{
first = adjacent_find(std::move(first), last, std::ref(pred), std::ref(proj));
if(first == last)
return first;
auto i = first;
for(auto j = ++i; ++j != last; ++i)
{
if(!invoke(pred, invoke(proj, *i), invoke(proj, *j)))
{
*first = iter_move(i);
++first;
}
}
*first = iter_move(i);
++first;
return first;
}
/// \overload
template<typename Rng, typename Pred, typename Proj = identity>
auto RANGES_FUN_NIEBLOID(adjacent_remove_if)(
Rng && rng, Pred pred, Proj proj = {}) //
->CPP_ret(safe_iterator_t<Rng>)( //
requires forward_range<Rng> &&
indirect_relation<Pred, projected<iterator_t<Rng>, Proj>> &&
permutable<iterator_t<Rng>>)
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_END_NIEBLOID(adjacent_remove_if)
namespace cpp20
{
using ranges::adjacent_remove_if;
}
/// @}
} // namespace ranges
#endif // RANGES_V3_ALGORITHM_ADJACENT_REMOVE_IF_HPP

View File

@ -1,67 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Andrew Sutton 2014
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ALGORITHM_ALL_OF_HPP
#define RANGES_V3_ALGORITHM_ALL_OF_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_BEGIN_NIEBLOID(all_of)
/// \brief function template \c all_of
template<typename I, typename S, typename F, typename P = identity>
auto RANGES_FUN_NIEBLOID(all_of)(I first, S last, F pred, P proj = P{}) //
->CPP_ret(bool)( //
requires input_iterator<I> && sentinel_for<S, I> &&
indirect_unary_predicate<F, projected<I, P>>)
{
for(; first != last; ++first)
if(!invoke(pred, invoke(proj, *first)))
break;
return first == last;
}
/// \overload
template<typename Rng, typename F, typename P = identity>
auto RANGES_FUN_NIEBLOID(all_of)(Rng && rng, F pred, P proj = P{}) //
->CPP_ret(bool)( //
requires input_range<Rng> &&
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>)
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_END_NIEBLOID(all_of)
namespace cpp20
{
using ranges::all_of;
}
/// @}
} // namespace ranges
#endif // include guard

View File

@ -1,68 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Andrew Sutton 2014
// Copyright Gonzalo Brito Gadeschi 2014
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ALGORITHM_ANY_OF_HPP
#define RANGES_V3_ALGORITHM_ANY_OF_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_BEGIN_NIEBLOID(any_of)
/// \brief function template \c any_of
template<typename I, typename S, typename F, typename P = identity>
auto RANGES_FUN_NIEBLOID(any_of)(I first, S last, F pred, P proj = P{}) //
->CPP_ret(bool)( //
requires input_iterator<I> && sentinel_for<S, I> &&
indirect_unary_predicate<F, projected<I, P>>)
{
for(; first != last; ++first)
if(invoke(pred, invoke(proj, *first)))
return true;
return false;
}
/// \overload
template<typename Rng, typename F, typename P = identity>
auto RANGES_FUN_NIEBLOID(any_of)(Rng && rng, F pred, P proj = P{}) //
->CPP_ret(bool)( //
requires input_range<Rng> &&
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>)
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_END_NIEBLOID(any_of)
namespace cpp20
{
using ranges::any_of;
}
/// @}
} // namespace ranges
#endif // include guard

View File

@ -1,84 +0,0 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ericniebler/range-v3
//
#ifndef RANGES_V3_ALGORITHM_AUX_EQUAL_RANGE_N_HPP
#define RANGES_V3_ALGORITHM_AUX_EQUAL_RANGE_N_HPP
#include <functional>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/aux_/lower_bound_n.hpp>
#include <range/v3/algorithm/aux_/upper_bound_n.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/view/subrange.hpp>
namespace ranges
{
namespace aux
{
struct equal_range_n_fn
{
template<typename I, typename V, typename R = less, typename P = identity>
auto operator()(I first, iter_difference_t<I> dist, V const & val,
R pred = R{}, P proj = P{}) const -> CPP_ret(subrange<I>)( //
requires forward_iterator<I> &&
indirect_strict_weak_order<R, V const *, projected<I, P>>)
{
if(0 < dist)
{
do
{
auto half = dist / 2;
auto middle = ranges::next(first, half);
auto && v = *middle;
auto && pv = invoke(proj, (decltype(v) &&)v);
if(invoke(pred, pv, val))
{
first = std::move(++middle);
dist -= half + 1;
}
else if(invoke(pred, val, pv))
{
dist = half;
}
else
{
return {lower_bound_n(std::move(first),
half,
val,
std::ref(pred),
std::ref(proj)),
upper_bound_n(ranges::next(middle),
dist - (half + 1),
val,
std::ref(pred),
std::ref(proj))};
}
} while(0 != dist);
}
return {first, first};
}
};
RANGES_INLINE_VARIABLE(equal_range_n_fn, equal_range_n)
} // namespace aux
} // namespace ranges
#endif // include guard

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