├── .appveyor.yml ├── .clang-format ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── README.md ├── Variadic Templates.pdf ├── include └── tao │ ├── seq │ ├── at_index.hpp │ ├── config.hpp │ ├── exclusive_scan.hpp │ ├── inclusive_scan.hpp │ ├── integer_sequence.hpp │ ├── is_all.hpp │ ├── make_integer_sequence.hpp │ ├── map.hpp │ ├── minus.hpp │ ├── partial_sum.hpp │ ├── plus.hpp │ ├── select.hpp │ ├── sum.hpp │ └── zip.hpp │ └── tuple │ └── tuple.hpp └── src └── test └── tuple ├── CMakeLists.txt ├── tuple_benchmark.cpp ├── tuple_cat.cpp └── tuple_main.cpp /.appveyor.yml: -------------------------------------------------------------------------------- 1 | version: '{branch}-{build}' 2 | 3 | os: 4 | - Visual Studio 2015 5 | 6 | configuration: 7 | - Release 8 | - Debug 9 | 10 | environment: 11 | matrix: 12 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 13 | GENERATOR: Visual Studio 15 2017 14 | 15 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 16 | GENERATOR: Visual Studio 15 2017 Win64 17 | 18 | - GENERATOR: MinGW Makefiles 19 | BINDIR: C:\MinGW\bin 20 | 21 | - GENERATOR: MinGW Makefiles 22 | COMPILER: MinGW 5 23 | BINDIR: C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin 24 | 25 | - GENERATOR: MinGW Makefiles 26 | COMPILER: MinGW 6 27 | BINDIR: C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin 28 | 29 | - GENERATOR: MinGW Makefiles 30 | COMPILER: MinGW 6 31 | BINDIR: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin 32 | 33 | init: [] 34 | 35 | install: [] 36 | 37 | before_build: 38 | - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" (del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets") 39 | - if defined BINDIR (set "PATH=%BINDIR%;%PATH:C:\Program Files\Git\usr\bin;=%") 40 | - md build 41 | - cd build 42 | - cmake -Wno-dev --config "%CONFIGURATION%" -G "%GENERATOR%" .. 43 | 44 | build_script: 45 | - cmake --build . --config "%CONFIGURATION%" 46 | 47 | test_script: 48 | - ctest -C "%CONFIGURATION%" --output-on-failure 49 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | # the official .clang-format style for https://github.com/taocpp 2 | # 3 | # clang-format -i -style=file $(find . -name '[^.]*.[hc]pp') 4 | 5 | Language: Cpp 6 | Standard: Cpp11 7 | 8 | AccessModifierOffset: -3 9 | AlignAfterOpenBracket: Align 10 | AlignConsecutiveAssignments: false 11 | AlignConsecutiveDeclarations: false 12 | AlignEscapedNewlinesLeft: false 13 | AlignOperands: true 14 | AlignTrailingComments: true 15 | AllowAllParametersOfDeclarationOnNextLine: true 16 | AllowShortBlocksOnASingleLine: false 17 | AllowShortCaseLabelsOnASingleLine: false 18 | AllowShortFunctionsOnASingleLine: Empty 19 | AllowShortIfStatementsOnASingleLine: false 20 | AllowShortLoopsOnASingleLine: false 21 | AlwaysBreakAfterReturnType: None 22 | AlwaysBreakBeforeMultilineStrings: false 23 | AlwaysBreakTemplateDeclarations: Yes 24 | BinPackArguments: false 25 | BinPackParameters: false 26 | BraceWrapping: 27 | AfterClass: true 28 | AfterControlStatement: false 29 | AfterEnum : true 30 | AfterFunction : true 31 | AfterNamespace : true 32 | AfterStruct : true 33 | AfterUnion : true 34 | AfterExternBlock: true 35 | BeforeCatch : true 36 | BeforeElse : true 37 | IndentBraces : false 38 | SplitEmptyFunction: false 39 | SplitEmptyRecord: false 40 | SplitEmptyNamespace: false 41 | BreakBeforeBinaryOperators: All 42 | BreakBeforeBraces: Custom 43 | BreakBeforeTernaryOperators: false 44 | BreakConstructorInitializers: BeforeColon 45 | BreakInheritanceList: BeforeColon 46 | BreakStringLiterals: false 47 | ColumnLimit: 0 48 | CompactNamespaces: false 49 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 50 | ConstructorInitializerIndentWidth: 3 51 | ContinuationIndentWidth: 3 52 | Cpp11BracedListStyle: false 53 | DerivePointerAlignment: false 54 | DisableFormat: false 55 | ExperimentalAutoDetectBinPacking: false 56 | FixNamespaceComments: true 57 | IncludeBlocks: Preserve 58 | IndentCaseLabels: true 59 | IndentPPDirectives: None 60 | IndentWidth: 3 61 | IndentWrappedFunctionNames: false 62 | KeepEmptyLinesAtTheStartOfBlocks: false 63 | MaxEmptyLinesToKeep: 1 64 | NamespaceIndentation: All 65 | PointerAlignment: Left 66 | ReflowComments: false 67 | SortIncludes: true 68 | SortUsingDeclarations: false 69 | SpaceAfterCStyleCast: false 70 | SpaceAfterTemplateKeyword: false 71 | SpaceBeforeAssignmentOperators: true 72 | SpaceBeforeCpp11BracedList: false 73 | SpaceBeforeCtorInitializerColon: true 74 | SpaceBeforeInheritanceColon: true 75 | SpaceBeforeParens: Never 76 | SpaceBeforeRangeBasedForLoopColon: true 77 | SpaceInEmptyParentheses: false 78 | SpacesBeforeTrailingComments: 2 79 | SpacesInAngles: true 80 | SpacesInCStyleCastParentheses: false 81 | SpacesInParentheses: true 82 | SpacesInSquareBrackets: true 83 | TabWidth: 8 84 | UseTab: Never 85 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | build 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: generic 2 | os: linux 3 | dist: xenial 4 | 5 | matrix: 6 | include: 7 | - compiler: gcc 8 | addons: 9 | apt: 10 | packages: ['g++-4.8'] 11 | env: 12 | - CXX=g++-4.8 13 | 14 | - compiler: gcc 15 | addons: 16 | apt: 17 | packages: ['g++-4.9'] 18 | env: 19 | - CXX=g++-4.9 20 | 21 | - compiler: gcc 22 | addons: 23 | apt: 24 | packages: ['g++-5'] 25 | env: 26 | - CXX=g++-5 27 | 28 | - compiler: gcc 29 | addons: 30 | apt: 31 | packages: ['g++-5'] 32 | env: 33 | - CXX=g++-5 34 | - CXXSTD=-std=c++14 35 | 36 | - compiler: gcc 37 | addons: 38 | apt: 39 | sources: ['ubuntu-toolchain-r-test'] 40 | packages: ['g++-6'] 41 | env: 42 | - CXX=g++-6 43 | 44 | - compiler: gcc 45 | addons: 46 | apt: 47 | sources: ['ubuntu-toolchain-r-test'] 48 | packages: ['g++-7'] 49 | env: 50 | - CXX=g++-7 51 | 52 | - compiler: gcc 53 | addons: 54 | apt: 55 | sources: ['ubuntu-toolchain-r-test'] 56 | packages: ['g++-7'] 57 | env: 58 | - CXX=g++-7 59 | - CXXSTD=-std=c++17 60 | 61 | - compiler: gcc 62 | addons: 63 | apt: 64 | sources: ['ubuntu-toolchain-r-test'] 65 | packages: ['g++-8'] 66 | env: 67 | - CXX=g++-8 68 | 69 | - compiler: gcc 70 | addons: 71 | apt: 72 | sources: ['ubuntu-toolchain-r-test'] 73 | packages: ['g++-9'] 74 | env: 75 | - CXX=g++-9 76 | 77 | - compiler: clang 78 | addons: 79 | apt: 80 | packages: ['clang-3.5'] 81 | env: 82 | - CXX=clang++-3.5 83 | 84 | - compiler: clang 85 | addons: 86 | apt: 87 | packages: ['clang-3.6'] 88 | env: 89 | - CXX=clang++-3.6 90 | 91 | - compiler: clang 92 | addons: 93 | apt: 94 | packages: ['clang-3.7'] 95 | env: 96 | - CXX=clang++-3.7 97 | 98 | - compiler: clang 99 | addons: 100 | apt: 101 | packages: ['clang-3.8'] 102 | env: 103 | - CXX=clang++-3.8 104 | 105 | - compiler: clang 106 | addons: 107 | apt: 108 | packages: ['clang-3.9'] 109 | env: 110 | - CXX=clang++-3.9 111 | 112 | - compiler: clang 113 | addons: 114 | apt: 115 | sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-xenial-4.0'] 116 | packages: ['clang-4.0'] 117 | env: 118 | - CXX=clang++-4.0 119 | 120 | - compiler: clang 121 | addons: 122 | apt: 123 | sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-xenial-5.0'] 124 | packages: ['clang-5.0'] 125 | env: 126 | - CXX=clang++-5.0 127 | 128 | - compiler: clang 129 | addons: 130 | apt: 131 | sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-xenial-6.0'] 132 | packages: ['clang-6.0'] 133 | env: 134 | - CXX=clang++-6.0 135 | 136 | - compiler: clang 137 | addons: 138 | apt: 139 | sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-xenial-7'] 140 | packages: ['clang-7'] 141 | env: 142 | - CXX=clang++-7 143 | 144 | - compiler: clang 145 | addons: 146 | apt: 147 | sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-xenial-8'] 148 | packages: ['clang-8'] 149 | env: 150 | - CXX=clang++-8 151 | 152 | - compiler: clang 153 | addons: 154 | apt: 155 | sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-xenial-8'] 156 | packages: ['clang-8'] 157 | env: 158 | - CXX=clang++-8 159 | - CPPFLAGS=-fms-extensions 160 | 161 | - os: osx 162 | osx_image: xcode6.4 163 | compiler: clang 164 | env: 165 | - CXX=clang++ 166 | 167 | - os: osx 168 | osx_image: xcode7.3 169 | compiler: clang 170 | env: 171 | - CXX=clang++ 172 | 173 | - os: osx 174 | osx_image: xcode8.3 175 | compiler: clang 176 | env: 177 | - CXX=clang++ 178 | 179 | - os: osx 180 | osx_image: xcode9.4 181 | compiler: clang 182 | env: 183 | - CXX=clang++ 184 | 185 | - os: osx 186 | osx_image: xcode10.1 187 | compiler: clang 188 | env: 189 | - CXX=clang++ 190 | 191 | - compiler: clang 192 | addons: 193 | apt: 194 | sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-xenial-8'] 195 | packages: ['clang-8', 'clang-tools-8'] 196 | env: 197 | - CXX=clang++-8 198 | script: 199 | - scan-build-8 make -kj3 200 | 201 | - compiler: gcc 202 | addons: 203 | apt: 204 | sources: ['ubuntu-toolchain-r-test'] 205 | packages: ['g++-6'] 206 | env: 207 | - CXX=g++-6 208 | script: 209 | - $CXX --version 210 | - mkdir build 211 | - cd build 212 | - cmake .. 213 | - cmake --build . 214 | - cmake --build . --target test 215 | 216 | script: 217 | - $CXX --version 218 | - make -kj3 219 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.2.0 FATAL_ERROR) 2 | 3 | project (taocpp-tuple VERSION 1.0.0 LANGUAGES CXX) 4 | 5 | # installation directories 6 | set (TAOCPP_TUPLE_INSTALL_INCLUDE_DIR "include" CACHE STRING "The installation include directory") 7 | set (TAOCPP_TUPLE_INSTALL_DOC_DIR "share/doc/tao/tuple" CACHE STRING "The installation doc directory") 8 | set (TAOCPP_TUPLE_INSTALL_CMAKE_DIR "share/taocpp-tuple/cmake" CACHE STRING "The installation cmake directory") 9 | 10 | # define a header-only library 11 | add_library (tuple INTERFACE) 12 | add_library (taocpp::tuple ALIAS tuple) 13 | target_include_directories (tuple INTERFACE 14 | $ 15 | $ 16 | ) 17 | 18 | # features used by taocpp/tuple 19 | target_compile_features (tuple INTERFACE 20 | cxx_constexpr 21 | cxx_noexcept 22 | cxx_rvalue_references 23 | ) 24 | 25 | # testing 26 | enable_testing () 27 | option (TAOCPP_TUPLE_BUILD_TESTS "Build test programs" ON) 28 | if (TAOCPP_TUPLE_BUILD_TESTS) 29 | add_subdirectory (src/test/tuple) 30 | endif () 31 | 32 | # install and export target 33 | install (TARGETS tuple EXPORT tuple-targets) 34 | 35 | install (EXPORT tuple-targets 36 | FILE taocpp-tuple-config.cmake 37 | NAMESPACE taocpp:: 38 | DESTINATION ${TAOCPP_TUPLE_INSTALL_CMAKE_DIR} 39 | ) 40 | 41 | install (DIRECTORY include/ DESTINATION ${TAOCPP_TUPLE_INSTALL_INCLUDE_DIR}) 42 | install (FILES LICENSE DESTINATION ${TAOCPP_TUPLE_INSTALL_DOC_DIR}) 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2020 Daniel Frey 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # The Art of C++ 2 | # Copyright (c) 2015-2020 Daniel Frey 3 | # Please see LICENSE for license or visit https://github.com/taocpp/tuple/ 4 | 5 | .SUFFIXES: 6 | .SECONDARY: 7 | 8 | ifeq ($(OS),Windows_NT) 9 | UNAME_S := $(OS) 10 | else 11 | UNAME_S := $(shell uname -s) 12 | endif 13 | 14 | # For Darwin (Mac OS X) we assume that the default compiler 15 | # clang++ is used; when $(CXX) is some version of g++, then 16 | # $(CXXSTD) has to be set to -std=c++11 (or newer) so 17 | # that -stdlib=libc++ is not automatically added. 18 | 19 | ifeq ($(CXXSTD),) 20 | CXXSTD := -std=c++11 21 | ifeq ($(UNAME_S),Darwin) 22 | CXXSTD += -stdlib=libc++ 23 | endif 24 | endif 25 | 26 | # Ensure strict standard compliance and no warnings, can be 27 | # changed if desired. 28 | 29 | CPPFLAGS ?= -pedantic 30 | CXXFLAGS ?= -Wall -Wextra -Wshadow -Werror -O3 31 | 32 | CLANG_TIDY ?= clang-tidy 33 | 34 | HEADERS := $(shell find include -name '*.hpp') 35 | SOURCES := $(shell find src -name '*.cpp') 36 | DEPENDS := $(SOURCES:%.cpp=build/%.d) 37 | BINARIES := $(SOURCES:%.cpp=build/%) 38 | 39 | UNIT_TESTS := $(filter build/src/test/%,$(BINARIES)) 40 | 41 | .PHONY: all 42 | all: compile check 43 | 44 | .PHONY: compile 45 | compile: $(BINARIES) 46 | 47 | .PHONY: check 48 | check: $(UNIT_TESTS) 49 | @set -e; for T in $(UNIT_TESTS); do echo $$T; $$T > /dev/null; done 50 | 51 | .PHONY: clean 52 | clean: 53 | @rm -rf build 54 | @find . -name '*~' -delete 55 | 56 | build/%.d: %.cpp Makefile 57 | @mkdir -p $(@D) 58 | $(CXX) $(CXXSTD) -Iinclude $(CPPFLAGS) -MM -MQ $@ $< -o $@ 59 | 60 | build/%: %.cpp build/%.d 61 | $(CXX) $(CXXSTD) -Iinclude $(CPPFLAGS) $(CXXFLAGS) $< -o $@ 62 | 63 | build/%.clang-tidy: % 64 | $(CLANG_TIDY) -extra-arg "-Iinclude" -extra-arg "-std=c++11" -checks=*,-fuchsia-*,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-misc-macro-parentheses,-hicpp-no-array-decay -warnings-as-errors=* $< 2>/dev/null 65 | @mkdir -p $(@D) 66 | @touch $@ 67 | 68 | .PHONY: clang-tidy 69 | clang-tidy: $(HEADERS:%=build/%.clang-tidy) $(SOURCES:%=build/%.clang-tidy) 70 | @echo "All $(words $(HEADERS) $(SOURCES)) clang-tidy tests passed." 71 | 72 | ifeq ($(findstring $(MAKECMDGOALS),clean),) 73 | -include $(DEPENDS) 74 | endif 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Art of C++ / Tuple 2 | 3 | [![Release](https://img.shields.io/github/release/taocpp/tuple.svg)](https://github.com/taocpp/tuple/releases/latest) 4 | [![Download](https://api.bintray.com/packages/conan/conan-center/taocpp-tuple%3A_/images/download.svg)](https://bintray.com/conan/conan-center/taocpp-tuple%3A_/_latestVersion) 5 | [![TravisCI](https://travis-ci.org/taocpp/tuple.svg)](https://travis-ci.org/taocpp/tuple) 6 | [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/taocpp/tuple?svg=true)](https://ci.appveyor.com/project/taocpp/tuple) 7 | 8 | [The Art of C++](https://taocpp.github.io/) / Tuple is a C++11 header-only proof-of-concept implementation of 9 | [`std::tuple`](http://en.cppreference.com/w/cpp/utility/tuple). 10 | 11 | ## Rationale 12 | 13 | Why another implementation of `std::tuple`? To provide a proof-of-concept that, 14 | when avoiding recursion, code can benefit in significant ways. I prepared a talk 15 | about it, including some benchmarks. 16 | 17 | [Download presentation](https://github.com/taocpp/tuple/blob/main/Variadic%20Templates.pdf) 18 | 19 | TL;DR: GCC 5 on Linux with libstdc++'s `std::tuple` requires 19.6s and an instantiation 20 | depth of at least 3.719 to compile an 21 | [example](https://github.com/taocpp/tuple/blob/main/src/test/tuple/tuple_benchmark.cpp) 22 | generating a tuple with 265 elements via `std::tuple_cat`. 23 | `tao::tuple` requires 1.2s and an instantiation depth of 26 on the same system. 24 | 25 | Apple LLVM 7.0 (~Clang 3.7) with libc++'s `std::tuple` requires 70s and an instantiation 26 | depth of 514 to compile the example. `tao::tuple` requires 1.7s and an instantiation depth 27 | of 15 on the same system. This case does *not* change `std::integer_sequence` or 28 | `std::make_integer_sequence`, all improvements are coming from all the *other* improvements 29 | from avoiding recursion. 30 | 31 | ## CUDA 32 | 33 | `tao::tuple` supports [CUDA](http://www.nvidia.com/object/cuda_home.html). 34 | 35 | ## Compatibility 36 | 37 | * Requires C++11 or newer. 38 | * Tested with GCC 4.8+, Clang 3.4+, and Visual Studio 2017. 39 | 40 | ## Package Managers 41 | 42 | You can download and install [The Art of C++](https://taocpp.github.io/) / Tuple using the [Conan](https://github.com/conan-io/conan) package manager: 43 | 44 | conan install taocpp-tuple/1.0.0@ 45 | 46 | The taocpp-tuple package in conan is kept up to date by Conan team members and community contributors. 47 | If the version is out-of-date, please [create an issue or pull request](https://github.com/conan-io/conan-center-index) on the Conan Center Index repository. 48 | 49 | ## Changelog 50 | 51 | ### 1.0.0 52 | 53 | Released 2018-08-01 54 | 55 | * Initial release. 56 | 57 | ## License 58 | 59 | The Art of C++ is certified [Open Source](http://www.opensource.org/docs/definition.html) software. It may be used for any purpose, including commercial purposes, at absolutely no cost. It is distributed under the terms of the [MIT license](http://www.opensource.org/licenses/mit-license.html) reproduced here. 60 | 61 | > Copyright (c) 2015-2020 Daniel Frey 62 | > 63 | > 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: 64 | > 65 | > The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 66 | > 67 | > 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. 68 | -------------------------------------------------------------------------------- /Variadic Templates.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taocpp/tuple/97618cee3ffe7738acea87871abdf5dddd415602/Variadic Templates.pdf -------------------------------------------------------------------------------- /include/tao/seq/at_index.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/sequences/ 3 | 4 | #ifndef TAO_SEQ_AT_INDEX_HPP 5 | #define TAO_SEQ_AT_INDEX_HPP 6 | 7 | #include 8 | 9 | #include "make_integer_sequence.hpp" 10 | 11 | namespace tao 12 | { 13 | namespace seq 14 | { 15 | // based on http://talesofcpp.fusionfenix.com/post-22/true-story-efficient-packing 16 | 17 | namespace impl 18 | { 19 | template< std::size_t, typename T > 20 | struct indexed 21 | { 22 | using type = T; 23 | }; 24 | 25 | template< typename, typename... Ts > 26 | struct indexer; 27 | 28 | template< std::size_t... Is, typename... Ts > 29 | struct indexer< index_sequence< Is... >, Ts... > 30 | : indexed< Is, Ts >... 31 | { 32 | }; 33 | 34 | template< std::size_t I, typename T > 35 | indexed< I, T > select( const indexed< I, T >& ); 36 | 37 | } // namespace impl 38 | 39 | template< std::size_t I, typename... Ts > 40 | using at_index = decltype( impl::select< I >( impl::indexer< index_sequence_for< Ts... >, Ts... >() ) ); 41 | 42 | #ifndef _MSC_VER 43 | template< std::size_t I, typename... Ts > 44 | using at_index_t = typename at_index< I, Ts... >::type; 45 | #else 46 | namespace impl 47 | { 48 | template< typename T > 49 | struct get_type 50 | { 51 | using type = typename T::type; 52 | }; 53 | 54 | } // namespace impl 55 | 56 | template< std::size_t I, typename... Ts > 57 | using at_index_t = typename impl::get_type< at_index< I, Ts... > >::type; 58 | #endif 59 | 60 | } // namespace seq 61 | 62 | } // namespace tao 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /include/tao/seq/config.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/sequences/ 3 | 4 | #ifndef TAO_SEQ_CONFIG_HPP 5 | #define TAO_SEQ_CONFIG_HPP 6 | 7 | #include 8 | 9 | #ifndef TAO_SEQ_USE_STD_INTEGER_SEQUENCE 10 | #if defined( __cpp_lib_integer_sequence ) 11 | #define TAO_SEQ_USE_STD_INTEGER_SEQUENCE 12 | #elif defined( _LIBCPP_VERSION ) && ( __cplusplus >= 201402L ) 13 | #define TAO_SEQ_USE_STD_INTEGER_SEQUENCE 14 | #elif defined( _MSC_VER ) 15 | #define TAO_SEQ_USE_STD_INTEGER_SEQUENCE 16 | #endif 17 | #endif 18 | 19 | #ifndef TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE 20 | #if defined( _GLIBCXX_RELEASE ) && ( _GLIBCXX_RELEASE >= 8 ) && ( __cplusplus >= 201402L ) 21 | #define TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE 22 | #elif defined( _LIBCPP_VERSION ) && ( __cplusplus >= 201402L ) 23 | #define TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE 24 | #elif defined( _MSC_VER ) && ( _MSC_FULL_VER >= 190023918 ) 25 | #define TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE 26 | #endif 27 | #endif 28 | 29 | #if defined( __cpp_fold_expressions ) && ( !defined( __GNUC__ ) || ( __GNUC__ >= 8 ) ) 30 | #define TAO_SEQ_FOLD_EXPRESSIONS 31 | #endif 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/tao/seq/exclusive_scan.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/sequences/ 3 | 4 | #ifndef TAO_SEQ_EXCLUSIVE_SCAN_HPP 5 | #define TAO_SEQ_EXCLUSIVE_SCAN_HPP 6 | 7 | #include 8 | 9 | #include "make_integer_sequence.hpp" 10 | #include "partial_sum.hpp" 11 | 12 | namespace tao 13 | { 14 | namespace seq 15 | { 16 | namespace impl 17 | { 18 | template< typename S, typename = make_index_sequence< S::size() > > 19 | struct exclusive_scan; 20 | 21 | template< typename S, std::size_t... Is > 22 | struct exclusive_scan< S, index_sequence< Is... > > 23 | { 24 | using type = integer_sequence< typename S::value_type, partial_sum< Is, S >::value... >; 25 | }; 26 | 27 | } // namespace impl 28 | 29 | template< typename T, T... Ns > 30 | struct exclusive_scan 31 | : impl::exclusive_scan< integer_sequence< T, Ns... > > 32 | { 33 | }; 34 | 35 | template< typename T, T... Ns > 36 | struct exclusive_scan< integer_sequence< T, Ns... > > 37 | : impl::exclusive_scan< integer_sequence< T, Ns... > > 38 | { 39 | }; 40 | 41 | template< typename T, T... Ns > 42 | using exclusive_scan_t = typename exclusive_scan< T, Ns... >::type; 43 | 44 | } // namespace seq 45 | 46 | } // namespace tao 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/tao/seq/inclusive_scan.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/sequences/ 3 | 4 | #ifndef TAO_SEQ_INCLUSIVE_SCAN_HPP 5 | #define TAO_SEQ_INCLUSIVE_SCAN_HPP 6 | 7 | #include 8 | 9 | #include "exclusive_scan.hpp" 10 | #include "integer_sequence.hpp" 11 | #include "plus.hpp" 12 | 13 | namespace tao 14 | { 15 | namespace seq 16 | { 17 | template< typename T, T... Ns > 18 | struct inclusive_scan 19 | : plus< exclusive_scan_t< T, Ns... >, integer_sequence< T, Ns... > > 20 | { 21 | }; 22 | 23 | template< typename T, T... Ns > 24 | struct inclusive_scan< integer_sequence< T, Ns... > > 25 | : plus< exclusive_scan_t< integer_sequence< T, Ns... > >, integer_sequence< T, Ns... > > 26 | { 27 | }; 28 | 29 | template< typename T, T... Ns > 30 | using inclusive_scan_t = typename inclusive_scan< T, Ns... >::type; 31 | 32 | } // namespace seq 33 | 34 | } // namespace tao 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /include/tao/seq/integer_sequence.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/sequences/ 3 | 4 | #ifndef TAO_SEQ_INTEGER_SEQUENCE_HPP 5 | #define TAO_SEQ_INTEGER_SEQUENCE_HPP 6 | 7 | #include 8 | #include 9 | 10 | #include "config.hpp" 11 | 12 | namespace tao 13 | { 14 | namespace seq 15 | { 16 | #ifdef TAO_SEQ_USE_STD_INTEGER_SEQUENCE 17 | 18 | using std::index_sequence; 19 | using std::integer_sequence; 20 | 21 | #else 22 | 23 | template< typename T, T... Ns > 24 | struct integer_sequence 25 | { 26 | using value_type = T; 27 | 28 | static constexpr std::size_t size() noexcept 29 | { 30 | return sizeof...( Ns ); 31 | } 32 | }; 33 | 34 | template< std::size_t... Ns > 35 | using index_sequence = integer_sequence< std::size_t, Ns... >; 36 | 37 | #endif 38 | 39 | } // namespace seq 40 | 41 | } // namespace tao 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /include/tao/seq/is_all.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/sequences/ 3 | 4 | #ifndef TAO_SEQ_IS_ALL_HPP 5 | #define TAO_SEQ_IS_ALL_HPP 6 | 7 | #include "config.hpp" 8 | 9 | #ifndef TAO_SEQ_FOLD_EXPRESSIONS 10 | #include "integer_sequence.hpp" 11 | #endif 12 | 13 | #include 14 | 15 | namespace tao 16 | { 17 | namespace seq 18 | { 19 | #ifdef TAO_SEQ_FOLD_EXPRESSIONS 20 | 21 | template< bool... Bs > 22 | using is_all = std::integral_constant< bool, ( Bs && ... ) >; 23 | 24 | #else 25 | 26 | template< bool... Bs > 27 | using is_all = std::is_same< integer_sequence< bool, true, Bs... >, integer_sequence< bool, Bs..., true > >; 28 | 29 | #endif 30 | 31 | } // namespace seq 32 | 33 | } // namespace tao 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /include/tao/seq/make_integer_sequence.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/sequences/ 3 | 4 | #ifndef TAO_SEQ_MAKE_INTEGER_SEQUENCE_HPP 5 | #define TAO_SEQ_MAKE_INTEGER_SEQUENCE_HPP 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "config.hpp" 12 | #include "integer_sequence.hpp" 13 | 14 | namespace tao 15 | { 16 | namespace seq 17 | { 18 | #ifdef TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE 19 | 20 | using std::index_sequence_for; 21 | using std::make_index_sequence; 22 | using std::make_integer_sequence; 23 | 24 | #else 25 | 26 | namespace impl 27 | { 28 | // we have four instantiations of generate_sequence<>, independent of T or N. 29 | // V is the current bit, E is the end marker - if true, this is the last step. 30 | template< bool V, bool E > 31 | struct generate_sequence; 32 | 33 | // last step: generate final integer sequence 34 | template<> 35 | struct generate_sequence< false, true > 36 | { 37 | template< typename T, T M, T N, std::size_t S, T... Ns > 38 | using f = integer_sequence< T, Ns... >; 39 | }; 40 | 41 | template<> 42 | struct generate_sequence< true, true > 43 | { 44 | template< typename T, T M, T N, std::size_t S, T... Ns > 45 | using f = integer_sequence< T, Ns..., S >; 46 | }; 47 | 48 | // intermediate step: double existing values, append one more if V is set. 49 | template<> 50 | struct generate_sequence< false, false > 51 | { 52 | template< typename T, T M, T N, std::size_t S, T... Ns > 53 | using f = typename generate_sequence< ( N & ( M / 2 ) ) != 0, ( M / 2 ) == 0 >::template f< T, M / 2, N, 2 * S, Ns..., ( Ns + S )... >; 54 | }; 55 | 56 | template<> 57 | struct generate_sequence< true, false > 58 | { 59 | template< typename T, T M, T N, std::size_t S, T... Ns > 60 | using f = typename generate_sequence< ( N & ( M / 2 ) ) != 0, ( M / 2 ) == 0 >::template f< T, M / 2, N, 2 * S + 1, Ns..., ( Ns + S )..., 2 * S >; 61 | }; 62 | 63 | // the final sequence per T/N should be memoized, it will probably be used multiple times. 64 | // also checks the limit and starts the above generator properly. 65 | template< typename T, T N > 66 | struct memoize_sequence 67 | { 68 | static_assert( N < T( 1 << 20 ), "N too large" ); 69 | // clang-format off 70 | using type = typename generate_sequence< false, false >::template f< T, ( N < T( 1 << 1 ) ) ? T( 1 << 1 ) : ( N < T( 1 << 2 ) ) ? T( 1 << 2 ) : ( N < T( 1 << 3 ) ) ? T( 1 << 3 ) : ( N < T( 1 << 4 ) ) ? T( 1 << 4 ) : ( N < T( 1 << 5 ) ) ? T( 1 << 5 ) : ( N < T( 1 << 6 ) ) ? T( 1 << 6 ) : ( N < T( 1 << 7 ) ) ? T( 1 << 7 ) : ( N < T( 1 << 8 ) ) ? T( 1 << 8 ) : ( N < T( 1 << 9 ) ) ? T( 1 << 9 ) : ( N < T( 1 << 10 ) ) ? T( 1 << 10 ) : T( 1 << 20 ), N, 0 >; 71 | // clang-format on 72 | }; 73 | 74 | } // namespace impl 75 | 76 | template< typename T, T N > 77 | using make_integer_sequence = typename impl::memoize_sequence< T, N >::type; 78 | 79 | template< std::size_t N > 80 | using make_index_sequence = make_integer_sequence< std::size_t, N >; 81 | 82 | template< typename... Ts > 83 | using index_sequence_for = make_index_sequence< sizeof...( Ts ) >; 84 | 85 | #endif 86 | 87 | } // namespace seq 88 | 89 | } // namespace tao 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /include/tao/seq/map.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/sequences/ 3 | 4 | #ifndef TAO_SEQ_MAP_HPP 5 | #define TAO_SEQ_MAP_HPP 6 | 7 | #include 8 | #include 9 | 10 | #include "integer_sequence.hpp" 11 | #include "select.hpp" 12 | 13 | namespace tao 14 | { 15 | namespace seq 16 | { 17 | template< typename, typename > 18 | struct map; 19 | 20 | template< std::size_t... Ns, typename M > 21 | struct map< index_sequence< Ns... >, M > 22 | { 23 | using type = integer_sequence< typename M::value_type, select< Ns, M >::value... >; 24 | }; 25 | 26 | template< typename S, typename M > 27 | using map_t = typename map< S, M >::type; 28 | 29 | } // namespace seq 30 | 31 | } // namespace tao 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/tao/seq/minus.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/sequences/ 3 | 4 | #ifndef TAO_SEQ_MINUS_HPP 5 | #define TAO_SEQ_MINUS_HPP 6 | 7 | #include 8 | 9 | #include "zip.hpp" 10 | 11 | namespace tao 12 | { 13 | namespace seq 14 | { 15 | namespace impl 16 | { 17 | struct minus 18 | { 19 | template< typename T, T A, T B > 20 | using apply = std::integral_constant< T, A - B >; 21 | }; 22 | 23 | } // namespace impl 24 | 25 | template< typename A, typename B > 26 | using minus = zip< impl::minus, A, B >; 27 | 28 | template< typename A, typename B > 29 | using minus_t = typename minus< A, B >::type; 30 | 31 | } // namespace seq 32 | 33 | } // namespace tao 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /include/tao/seq/partial_sum.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/sequences/ 3 | 4 | #ifndef TAO_SEQ_PARTIAL_SUM_HPP 5 | #define TAO_SEQ_PARTIAL_SUM_HPP 6 | 7 | #include 8 | #include 9 | 10 | #include "make_integer_sequence.hpp" 11 | #include "sum.hpp" 12 | 13 | namespace tao 14 | { 15 | namespace seq 16 | { 17 | namespace impl 18 | { 19 | template< std::size_t, typename S, typename = make_index_sequence< S::size() > > 20 | struct partial_sum; 21 | 22 | template< std::size_t I, typename T, T... Ns, std::size_t... Is > 23 | struct partial_sum< I, integer_sequence< T, Ns... >, index_sequence< Is... > > 24 | : seq::sum< T, ( ( Is < I ) ? Ns : 0 )... > 25 | { 26 | static_assert( I <= sizeof...( Is ), "tao::seq::partial_sum: I is out of range" ); 27 | }; 28 | 29 | } // namespace impl 30 | 31 | template< std::size_t I, typename T, T... Ns > 32 | struct partial_sum 33 | : impl::partial_sum< I, integer_sequence< T, Ns... > > 34 | { 35 | }; 36 | 37 | template< std::size_t I, typename T, T... Ns > 38 | struct partial_sum< I, integer_sequence< T, Ns... > > 39 | : impl::partial_sum< I, integer_sequence< T, Ns... > > 40 | { 41 | }; 42 | 43 | } // namespace seq 44 | 45 | } // namespace tao 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /include/tao/seq/plus.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/sequences/ 3 | 4 | #ifndef TAO_SEQ_PLUS_HPP 5 | #define TAO_SEQ_PLUS_HPP 6 | 7 | #include 8 | 9 | #include "zip.hpp" 10 | 11 | namespace tao 12 | { 13 | namespace seq 14 | { 15 | namespace impl 16 | { 17 | struct plus 18 | { 19 | template< typename T, T A, T B > 20 | using apply = std::integral_constant< T, A + B >; 21 | }; 22 | 23 | } // namespace impl 24 | 25 | template< typename A, typename B > 26 | using plus = zip< impl::plus, A, B >; 27 | 28 | template< typename A, typename B > 29 | using plus_t = typename plus< A, B >::type; 30 | 31 | } // namespace seq 32 | 33 | } // namespace tao 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /include/tao/seq/select.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/sequences/ 3 | 4 | #ifndef TAO_SEQ_SELECT_HPP 5 | #define TAO_SEQ_SELECT_HPP 6 | 7 | #include 8 | #include 9 | 10 | #include "at_index.hpp" 11 | #include "integer_sequence.hpp" 12 | 13 | namespace tao 14 | { 15 | namespace seq 16 | { 17 | template< std::size_t I, typename T, T... Ns > 18 | struct select 19 | : at_index_t< I, std::integral_constant< T, Ns >... > 20 | { 21 | }; 22 | 23 | template< std::size_t I, typename T, T... Ns > 24 | struct select< I, integer_sequence< T, Ns... > > 25 | : select< I, T, Ns... > 26 | { 27 | }; 28 | 29 | } // namespace seq 30 | 31 | } // namespace tao 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/tao/seq/sum.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/sequences/ 3 | 4 | #ifndef TAO_SEQ_SUM_HPP 5 | #define TAO_SEQ_SUM_HPP 6 | 7 | #include 8 | #include 9 | 10 | #include "config.hpp" 11 | #include "integer_sequence.hpp" 12 | 13 | #ifndef TAO_SEQ_FOLD_EXPRESSIONS 14 | #include "make_integer_sequence.hpp" 15 | #include 16 | #endif 17 | 18 | namespace tao 19 | { 20 | namespace seq 21 | { 22 | #ifdef TAO_SEQ_FOLD_EXPRESSIONS 23 | 24 | template< typename T, T... Ns > 25 | struct sum 26 | : std::integral_constant< T, ( Ns + ... + T( 0 ) ) > 27 | { 28 | }; 29 | 30 | #else 31 | 32 | namespace impl 33 | { 34 | template< std::size_t, std::size_t N > 35 | struct chars 36 | { 37 | char dummy[ N + 1 ]; 38 | }; 39 | 40 | template< typename, std::size_t... > 41 | struct collector; 42 | 43 | template< std::size_t... Is, std::size_t... Ns > 44 | struct collector< index_sequence< Is... >, Ns... > 45 | : chars< Is, Ns >... 46 | { 47 | }; 48 | 49 | template< bool, std::size_t N, typename T, T... Ns > 50 | struct sum; 51 | 52 | template< std::size_t N, typename T, T... Ns > 53 | struct sum< true, N, T, Ns... > 54 | { 55 | using type = std::integral_constant< T, T( sizeof( collector< make_index_sequence< N >, Ns... > ) - N ) >; 56 | }; 57 | 58 | template< bool, std::size_t N, typename T, T... Ns > 59 | struct sum 60 | { 61 | using positive = typename sum< true, N, T, ( ( Ns > 0 ) ? Ns : 0 )... >::type; 62 | using negative = typename sum< true, N, T, ( ( Ns < 0 ) ? -Ns : 0 )... >::type; 63 | using type = std::integral_constant< T, positive::value - negative::value >; 64 | }; 65 | 66 | } // namespace impl 67 | 68 | template< typename T, T... Ns > 69 | struct sum 70 | : impl::sum< std::is_unsigned< T >::value, sizeof...( Ns ) + 1, T, Ns..., 0 >::type 71 | { 72 | }; 73 | 74 | #endif 75 | 76 | template< typename T, T... Ns > 77 | struct sum< integer_sequence< T, Ns... > > 78 | : sum< T, Ns... > 79 | { 80 | }; 81 | 82 | } // namespace seq 83 | 84 | } // namespace tao 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /include/tao/seq/zip.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/sequences/ 3 | 4 | #ifndef TAO_SEQ_ZIP_HPP 5 | #define TAO_SEQ_ZIP_HPP 6 | 7 | #include 8 | 9 | #include "integer_sequence.hpp" 10 | 11 | namespace tao 12 | { 13 | namespace seq 14 | { 15 | template< typename, typename, typename > 16 | struct zip; 17 | 18 | template< typename OP, typename TA, TA... As, typename TB, TB... Bs > 19 | struct zip< OP, integer_sequence< TA, As... >, integer_sequence< TB, Bs... > > 20 | { 21 | using CT = typename std::common_type< TA, TB >::type; 22 | using type = integer_sequence< CT, OP::template apply< CT, As, Bs >::value... >; 23 | }; 24 | 25 | template< typename OP, typename A, typename B > 26 | using zip_t = typename zip< OP, A, B >::type; 27 | 28 | } // namespace seq 29 | 30 | } // namespace tao 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /include/tao/tuple/tuple.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/tuple/ 3 | 4 | #ifndef TAO_TUPLE_TUPLE_HPP 5 | #define TAO_TUPLE_TUPLE_HPP 6 | 7 | #include "../seq/at_index.hpp" 8 | #include "../seq/config.hpp" 9 | #include "../seq/exclusive_scan.hpp" 10 | #include "../seq/inclusive_scan.hpp" 11 | #include "../seq/integer_sequence.hpp" 12 | #include "../seq/is_all.hpp" 13 | #include "../seq/make_integer_sequence.hpp" 14 | #include "../seq/map.hpp" 15 | #include "../seq/minus.hpp" 16 | #include "../seq/sum.hpp" 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #if( __cplusplus >= 201402L ) 23 | #define TAO_TUPLE_CONSTEXPR constexpr 24 | #else 25 | #define TAO_TUPLE_CONSTEXPR 26 | #endif 27 | 28 | #ifndef TAO_TUPLE_CUDA_ANNOTATE_COMMON 29 | #ifdef __CUDACC__ 30 | #define TAO_TUPLE_CUDA_ANNOTATE_COMMON __host__ __device__ 31 | #else 32 | #define TAO_TUPLE_CUDA_ANNOTATE_COMMON 33 | #endif 34 | #endif 35 | 36 | // Ignore "calling a __host__ function from a __host__ _device__ function is not allowed" warnings 37 | #ifndef TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 38 | #ifdef __CUDACC__ 39 | #if __CUDAVER__ >= 75000 40 | #define TAO_TUPLE_SUPPRESS_NVCC_HD_WARN #pragma nv_exec_check_disable 41 | #else 42 | #define TAO_TUPLE_SUPPRESS_NVCC_HD_WARN #pragma hd_warning_disable 43 | #endif 44 | #else 45 | #define TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 46 | #endif 47 | #endif 48 | 49 | namespace tao 50 | { 51 | template< typename... Ts > 52 | struct tuple; 53 | } 54 | 55 | namespace std 56 | { 57 | // 20.4.2.8 Tuple traits [tuple.traits] 58 | 59 | template< typename... Ts, typename A > 60 | struct uses_allocator< tao::tuple< Ts... >, A > 61 | : true_type 62 | {}; 63 | 64 | } // namespace std 65 | 66 | namespace tao 67 | { 68 | template< std::size_t I, typename... Ts > 69 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON seq::at_index_t< I, Ts... >& get( tuple< Ts... >& ) noexcept; 70 | 71 | template< std::size_t I, typename... Ts > 72 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON seq::at_index_t< I, Ts... >&& get( tuple< Ts... >&& ) noexcept; 73 | 74 | template< std::size_t I, typename... Ts > 75 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON const seq::at_index_t< I, Ts... >& get( const tuple< Ts... >& ) noexcept; 76 | 77 | template< std::size_t I, typename... Ts > 78 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON const seq::at_index_t< I, Ts... >&& get( const tuple< Ts... >&& ) noexcept; 79 | 80 | namespace impl 81 | { 82 | // TODO: std::pair support 83 | // TODO: allocator support 84 | 85 | using swallow = bool[]; 86 | 87 | template< typename T, typename > 88 | struct dependent_type 89 | : T 90 | {}; 91 | 92 | template< bool B, typename T = void > 93 | using enable_if_t = typename std::enable_if< B, T >::type; 94 | 95 | // TODO: this is in namespace impl. is it harmless? 96 | using std::swap; 97 | 98 | template< typename T > 99 | using is_nothrow_swappable = std::integral_constant< bool, noexcept( swap( std::declval< T& >(), std::declval< T& >() ) ) >; 100 | 101 | #if __cplusplus >= 201402L 102 | template< typename T > 103 | using is_final = std::is_final< T >; 104 | #else 105 | template< typename T > 106 | using is_final = std::integral_constant< bool, __is_final( T ) >; 107 | #endif 108 | 109 | template< bool, bool > 110 | struct uses_alloc_ctor; 111 | 112 | template< typename T, typename A, typename... As > 113 | using uses_alloc_ctor_t = uses_alloc_ctor< std::uses_allocator< T, A >::value, std::is_constructible< T, std::allocator_arg_t, A, As... >::value >*; 114 | 115 | template< std::size_t I, typename T, bool = std::is_empty< T >::value && !is_final< T >::value > 116 | struct tuple_value 117 | { 118 | T value; 119 | 120 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 121 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 122 | constexpr tuple_value() noexcept( std::is_nothrow_default_constructible< T >::value ) 123 | : value() 124 | { 125 | static_assert( !std::is_reference< T >::value, "attempted to default construct a reference element in a tuple" ); 126 | } 127 | 128 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 129 | template< bool B, typename A > 130 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 131 | tuple_value( uses_alloc_ctor< false, B >*, const A& ) 132 | : value() 133 | { 134 | static_assert( !std::is_reference< T >::value, "attempted to default construct a reference element in a tuple" ); 135 | } 136 | 137 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 138 | template< typename A > 139 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 140 | tuple_value( uses_alloc_ctor< true, true >*, const A& a ) 141 | : value( std::allocator_arg_t(), a ) 142 | { 143 | static_assert( !std::is_reference< T >::value, "attempted to default construct a reference element in a tuple" ); 144 | } 145 | 146 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 147 | template< typename A > 148 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 149 | tuple_value( uses_alloc_ctor< true, false >*, const A& a ) 150 | : value( a ) 151 | { 152 | static_assert( !std::is_reference< T >::value, "attempted to default construct a reference element in a tuple" ); 153 | } 154 | 155 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 156 | template< typename U, 157 | typename = impl::enable_if_t< !std::is_same< typename std::decay< U >::type, tuple_value >::value >, 158 | typename = impl::enable_if_t< std::is_constructible< T, U >::value > > 159 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON explicit tuple_value( U&& v ) noexcept( std::is_nothrow_constructible< T, U >::value ) 160 | : value( std::forward< U >( v ) ) 161 | {} 162 | 163 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 164 | template< bool B, typename A, typename U > 165 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 166 | tuple_value( uses_alloc_ctor< false, B >*, const A&, U&& v ) 167 | : value( std::forward< U >( v ) ) 168 | { 169 | // TODO: Add check for rvalue to lvalue reference 170 | } 171 | 172 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 173 | template< typename A, typename U > 174 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 175 | tuple_value( uses_alloc_ctor< true, true >*, const A& a, U&& v ) 176 | : value( std::allocator_arg_t(), a, std::forward< U >( v ) ) 177 | { 178 | // TODO: Add check for rvalue to lvalue reference 179 | } 180 | 181 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 182 | template< typename A, typename U > 183 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 184 | tuple_value( uses_alloc_ctor< true, false >*, const A& a, U&& v ) 185 | : value( std::forward< U >( v ), a ) 186 | { 187 | // TODO: Add check for rvalue to lvalue reference 188 | } 189 | 190 | tuple_value( const tuple_value& ) = default; 191 | tuple_value( tuple_value&& ) = default; 192 | tuple_value& operator=( const tuple_value& ) = default; 193 | tuple_value& operator=( tuple_value&& ) = default; 194 | 195 | template< typename U > 196 | TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple_value& operator=( U&& v ) noexcept( std::is_nothrow_assignable< T&, U >::value ) 197 | { 198 | value = std::forward< U >( v ); 199 | return *this; 200 | } 201 | 202 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 203 | void swap( tuple_value& v ) noexcept( is_nothrow_swappable< T >::value ) 204 | { 205 | using std::swap; 206 | swap( value, v.value ); 207 | } 208 | 209 | TAO_TUPLE_CONSTEXPR 210 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 211 | T& get() noexcept 212 | { 213 | return value; 214 | } 215 | 216 | TAO_TUPLE_CONSTEXPR 217 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 218 | const T& get() const noexcept 219 | { 220 | return value; 221 | } 222 | }; 223 | 224 | template< std::size_t I, typename T > 225 | struct tuple_value< I, T, true > 226 | : private T 227 | { 228 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 229 | constexpr TAO_TUPLE_CUDA_ANNOTATE_COMMON 230 | tuple_value() noexcept( std::is_nothrow_default_constructible< T >::value ) 231 | : T() 232 | {} 233 | 234 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 235 | template< bool B, typename A > 236 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 237 | tuple_value( uses_alloc_ctor< false, B >*, const A& ) 238 | : T() 239 | {} 240 | 241 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 242 | template< typename A > 243 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 244 | tuple_value( uses_alloc_ctor< true, true >*, const A& a ) 245 | : T( std::allocator_arg_t(), a ) 246 | {} 247 | 248 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 249 | template< typename A > 250 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 251 | tuple_value( uses_alloc_ctor< true, false >*, const A& a ) 252 | : T( a ) 253 | {} 254 | 255 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 256 | template< typename U, 257 | typename = impl::enable_if_t< !std::is_same< typename std::decay< U >::type, tuple_value >::value >, 258 | typename = impl::enable_if_t< std::is_constructible< T, U >::value > > 259 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON explicit tuple_value( U&& v ) noexcept( std::is_nothrow_constructible< T, U >::value ) 260 | : T( std::forward< U >( v ) ) 261 | {} 262 | 263 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 264 | template< bool B, typename A, typename U > 265 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 266 | tuple_value( uses_alloc_ctor< false, B >*, const A&, U&& v ) 267 | : T( std::forward< U >( v ) ) 268 | {} 269 | 270 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 271 | template< typename A, typename U > 272 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 273 | tuple_value( uses_alloc_ctor< true, true >*, const A& a, U&& v ) 274 | : T( std::allocator_arg_t(), a, std::forward< U >( v ) ) 275 | {} 276 | 277 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 278 | template< typename A, typename U > 279 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 280 | tuple_value( uses_alloc_ctor< true, false >*, const A& a, U&& v ) 281 | : T( std::forward< U >( v ), a ) 282 | {} 283 | 284 | tuple_value( const tuple_value& ) = default; 285 | tuple_value( tuple_value&& ) = default; 286 | tuple_value& operator=( const tuple_value& ) = default; 287 | tuple_value& operator=( tuple_value&& ) = default; 288 | 289 | template< typename U > 290 | TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple_value& operator=( U&& v ) noexcept( std::is_nothrow_assignable< T&, U >::value ) 291 | { 292 | T::operator=( std::forward< U >( v ) ); 293 | return *this; 294 | } 295 | 296 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 297 | void swap( tuple_value& v ) noexcept( is_nothrow_swappable< T >::value ) 298 | { 299 | using std::swap; 300 | swap( *this, v ); 301 | } 302 | 303 | TAO_TUPLE_CONSTEXPR 304 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 305 | T& get() noexcept 306 | { 307 | return static_cast< T& >( *this ); 308 | } 309 | 310 | TAO_TUPLE_CONSTEXPR 311 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 312 | const T& get() const noexcept 313 | { 314 | return static_cast< const T& >( *this ); 315 | } 316 | }; 317 | 318 | template< typename, typename... > 319 | struct tuple_base; 320 | 321 | template< std::size_t... Is, typename... Ts > 322 | struct tuple_base< seq::index_sequence< Is... >, Ts... > 323 | : tuple_value< Is, Ts >... 324 | { 325 | constexpr tuple_base() = default; 326 | 327 | template< typename... Us > 328 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON explicit tuple_base( Us&&... us ) 329 | : tuple_value< Is, Ts >( std::forward< Us >( us ) )... 330 | {} 331 | 332 | template< typename A, typename... Us > 333 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple_base( std::allocator_arg_t, const A& a, Us&&... us ) 334 | : tuple_value< Is, Ts >( uses_alloc_ctor_t< Ts, A, Us >(), a, std::forward< Us >( us ) )... 335 | {} 336 | 337 | tuple_base( const tuple_base& ) = default; 338 | tuple_base( tuple_base&& ) = default; 339 | tuple_base& operator=( const tuple_base& v ) = default; 340 | tuple_base& operator=( tuple_base&& v ) = default; 341 | 342 | template< typename... Us > 343 | TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple_base& operator=( const tuple< Us... >& v ) noexcept( seq::is_all< std::is_nothrow_assignable< Ts&, const Us& >::value... >::value ) 344 | { 345 | #ifdef TAO_SEQ_FOLD_EXPRESSIONS 346 | ( tuple_value< Is, Ts >::operator=( get< Is >( v ) ), ... ); 347 | #else 348 | (void)swallow{ ( tuple_value< Is, Ts >::operator=( get< Is >( v ) ), true )..., true }; 349 | #endif 350 | return *this; 351 | } 352 | 353 | template< typename... Us > 354 | TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple_base& operator=( tuple< Us... >&& v ) noexcept( seq::is_all< std::is_nothrow_assignable< Ts&, Us&& >::value... >::value ) 355 | { 356 | #ifdef TAO_SEQ_FOLD_EXPRESSIONS 357 | ( tuple_value< Is, Ts >::operator=( get< Is >( std::move( v ) ) ), ... ); 358 | #else 359 | (void)swallow{ ( tuple_value< Is, Ts >::operator=( get< Is >( std::move( v ) ) ), true )..., true }; 360 | #endif 361 | return *this; 362 | } 363 | 364 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 365 | void swap( tuple_base& v ) noexcept( seq::is_all< impl::is_nothrow_swappable< Ts >::value... >::value ) 366 | { 367 | #ifdef TAO_SEQ_FOLD_EXPRESSIONS 368 | ( static_cast< tuple_value< Is, Ts >& >( *this ).swap( static_cast< tuple_value< Is, Ts >& >( v ) ), ... ); 369 | #else 370 | (void)swallow{ ( static_cast< tuple_value< Is, Ts >& >( *this ).swap( static_cast< tuple_value< Is, Ts >& >( v ) ), true )..., true }; 371 | #endif 372 | } 373 | }; 374 | 375 | } // namespace impl 376 | 377 | // 20.4.2 Class template tuple [tuple.tuple] 378 | 379 | // tuple 380 | template< typename... Ts > 381 | struct tuple 382 | { 383 | private: 384 | using base_t = impl::tuple_base< seq::index_sequence_for< Ts... >, Ts... >; 385 | base_t base; 386 | 387 | template< std::size_t I, typename... Us > 388 | friend TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON seq::at_index_t< I, Us... >& get( tuple< Us... >& ) noexcept; 389 | 390 | template< std::size_t I, typename... Us > 391 | friend TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON seq::at_index_t< I, Us... >&& get( tuple< Us... >&& ) noexcept; 392 | 393 | template< std::size_t I, typename... Us > 394 | friend TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON const seq::at_index_t< I, Us... >& get( const tuple< Us... >& ) noexcept; 395 | 396 | template< std::size_t I, typename... Us > 397 | friend TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON const seq::at_index_t< I, Us... >&& get( const tuple< Us... >&& ) noexcept; 398 | 399 | public: 400 | // 20.4.2.1 Construction [tuple.cnstr] 401 | 402 | // TODO: Move this templated condition to base? 403 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 404 | template< typename dummy = void, 405 | typename = impl::enable_if_t< seq::is_all< impl::dependent_type< std::is_default_constructible< Ts >, dummy >::value... >::value > > 406 | TAO_TUPLE_CUDA_ANNOTATE_COMMON constexpr tuple() noexcept( seq::is_all< std::is_nothrow_default_constructible< Ts >::value... >::value ) 407 | : base() 408 | {} 409 | 410 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 411 | template< typename dummy = void, 412 | typename = impl::enable_if_t< seq::is_all< impl::dependent_type< std::is_copy_constructible< Ts >, dummy >::value... >::value > > 413 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON explicit tuple( const Ts&... ts ) noexcept( seq::is_all< std::is_nothrow_copy_constructible< Ts >::value... >::value ) 414 | : base( ts... ) 415 | {} 416 | 417 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 418 | template< typename... Us, 419 | typename = impl::enable_if_t< sizeof...( Us ) == sizeof...( Ts ) >, 420 | typename = impl::enable_if_t< seq::is_all< std::is_constructible< Ts, Us&& >::value... >::value > > 421 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON explicit tuple( Us&&... us ) noexcept( seq::is_all< std::is_nothrow_constructible< Ts, Us&& >::value... >::value ) 422 | : base( std::forward< Us >( us )... ) 423 | {} 424 | 425 | tuple( const tuple& ) = default; 426 | tuple( tuple&& ) = default; 427 | tuple& operator=( const tuple& ) = default; 428 | tuple& operator=( tuple&& ) = default; 429 | 430 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 431 | template< typename... Us, 432 | typename = impl::enable_if_t< sizeof...( Us ) == sizeof...( Ts ) >, 433 | typename = impl::enable_if_t< seq::is_all< std::is_constructible< Ts, const Us& >::value... >::value > > 434 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON explicit tuple( const tuple< Us... >& v ) noexcept( seq::is_all< std::is_nothrow_constructible< Ts, const Us& >::value... >::value ) 435 | : base( v ) 436 | {} 437 | 438 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 439 | template< typename... Us, 440 | typename = impl::enable_if_t< sizeof...( Us ) == sizeof...( Ts ) >, 441 | typename = impl::enable_if_t< seq::is_all< std::is_constructible< Ts, Us&& >::value... >::value > > 442 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON explicit tuple( tuple< Us... >&& v ) noexcept( seq::is_all< std::is_nothrow_constructible< Ts, Us&& >::value... >::value ) 443 | : base( std::move( v ) ) 444 | {} 445 | 446 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 447 | template< typename A, 448 | typename dummy = void, 449 | typename = impl::enable_if_t< seq::is_all< impl::dependent_type< std::is_default_constructible< Ts >, dummy >::value... >::value > > 450 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 451 | tuple( std::allocator_arg_t, const A& a ) 452 | : base( std::allocator_arg_t(), a ) 453 | {} 454 | 455 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 456 | template< typename A, 457 | typename dummy = void, 458 | typename = impl::enable_if_t< seq::is_all< impl::dependent_type< std::is_copy_constructible< Ts >, dummy >::value... >::value > > 459 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 460 | tuple( std::allocator_arg_t, const A& a, const Ts&... ts ) 461 | : base( std::allocator_arg_t(), a, ts... ) 462 | {} 463 | 464 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 465 | template< typename A, 466 | typename... Us, 467 | typename = impl::enable_if_t< sizeof...( Us ) == sizeof...( Ts ) >, 468 | typename = impl::enable_if_t< seq::is_all< std::is_constructible< Ts, Us&& >::value... >::value > > 469 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 470 | tuple( std::allocator_arg_t, const A& a, Us&&... us ) 471 | : base( std::allocator_arg_t(), a, std::forward< Us >( us )... ) 472 | {} 473 | 474 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 475 | template< typename A > 476 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 477 | tuple( std::allocator_arg_t, const A& a, const tuple& v ) 478 | : base( std::allocator_arg_t(), a, v ) 479 | {} 480 | 481 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 482 | template< typename A > 483 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 484 | tuple( std::allocator_arg_t, const A& a, tuple&& v ) 485 | : base( std::allocator_arg_t(), a, std::move( v ) ) 486 | {} 487 | 488 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 489 | template< typename A, 490 | typename... Us, 491 | typename = impl::enable_if_t< sizeof...( Us ) == sizeof...( Ts ) >, 492 | typename = impl::enable_if_t< seq::is_all< std::is_constructible< Ts, const Us& >::value... >::value > > 493 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 494 | tuple( std::allocator_arg_t, const A& a, const tuple< Us... >& v ) 495 | : base( std::allocator_arg_t(), a, v ) 496 | {} 497 | 498 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 499 | template< typename A, 500 | typename... Us, 501 | typename = impl::enable_if_t< sizeof...( Us ) == sizeof...( Ts ) >, 502 | typename = impl::enable_if_t< seq::is_all< std::is_constructible< Ts, Us&& >::value... >::value > > 503 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 504 | tuple( std::allocator_arg_t, const A& a, tuple< Us... >&& v ) 505 | : base( std::allocator_arg_t(), a, std::move( v ) ) 506 | {} 507 | 508 | // 20.4.2.2 Assignment [tuple.assign] 509 | 510 | template< typename T, 511 | typename = impl::enable_if_t< std::is_assignable< base_t&, T >::value > > 512 | TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple& operator=( T&& v ) noexcept( std::is_nothrow_assignable< base_t&, T >::value ) 513 | { 514 | base = std::forward< T >( v ); 515 | return *this; 516 | } 517 | 518 | // 20.4.2.3 swap [tuple.swap] 519 | 520 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 521 | void swap( tuple& v ) noexcept( noexcept( base.swap( v.base ) ) ) 522 | { 523 | base.swap( v.base ); 524 | } 525 | }; 526 | 527 | template<> 528 | struct tuple<> 529 | { 530 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 531 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 532 | constexpr tuple() noexcept 533 | {} 534 | 535 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 536 | template< typename A > 537 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 538 | tuple( std::allocator_arg_t, const A& ) noexcept 539 | {} 540 | 541 | TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 542 | template< typename A > 543 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 544 | tuple( std::allocator_arg_t, const A&, const tuple& ) noexcept 545 | {} 546 | 547 | TAO_TUPLE_CUDA_ANNOTATE_COMMON 548 | void swap( tuple& ) noexcept 549 | {} 550 | }; 551 | 552 | // 20.4.2.4 Tuple creation functions [tuple.creation] 553 | 554 | // ignore helper 555 | namespace impl 556 | { 557 | struct ignore_t 558 | { 559 | template< typename U > 560 | TAO_TUPLE_CUDA_ANNOTATE_COMMON ignore_t& operator=( U&& ) 561 | { 562 | return *this; 563 | } 564 | }; 565 | 566 | } // namespace impl 567 | 568 | // ignore 569 | const impl::ignore_t ignore{}; 570 | 571 | // make_tuple helper 572 | namespace impl 573 | { 574 | template< typename T > 575 | struct make_tuple_return 576 | { 577 | using type = T; 578 | }; 579 | 580 | template< typename T > 581 | struct make_tuple_return< std::reference_wrapper< T > > 582 | { 583 | using type = T&; 584 | }; 585 | 586 | template< typename T > 587 | using make_tuple_return_t = typename make_tuple_return< T >::type; 588 | 589 | } // namespace impl 590 | 591 | // make_tuple 592 | template< typename... Ts, typename R = tuple< impl::make_tuple_return_t< typename std::decay< Ts >::type >... > > 593 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON R make_tuple( Ts&&... ts ) 594 | { 595 | return R( std::forward< Ts >( ts )... ); 596 | } 597 | 598 | // forward_as_tuple 599 | template< typename... Ts > 600 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple< Ts&&... > forward_as_tuple( Ts&&... ts ) noexcept 601 | { 602 | return tuple< Ts&&... >( std::forward< Ts >( ts )... ); 603 | } 604 | 605 | // tie 606 | template< typename... Ts > 607 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple< Ts&... > tie( Ts&... ts ) noexcept 608 | { 609 | return tuple< Ts&... >( ts... ); 610 | } 611 | 612 | // tuple_cat is found at the end, as it requires access to tuple_element_t and get 613 | 614 | // 20.4.2.5 Tuple helper classes [tuple.helper] 615 | 616 | // tuple_size 617 | template< typename T > 618 | struct tuple_size; 619 | 620 | template< typename T > 621 | struct tuple_size< const T > 622 | : tuple_size< T > 623 | {}; 624 | 625 | template< typename T > 626 | struct tuple_size< volatile T > 627 | : tuple_size< T > 628 | {}; 629 | 630 | template< typename T > 631 | struct tuple_size< const volatile T > 632 | : tuple_size< T > 633 | {}; 634 | 635 | template< typename... Ts > 636 | struct tuple_size< tuple< Ts... > > 637 | : std::integral_constant< std::size_t, sizeof...( Ts ) > 638 | {}; 639 | 640 | // tuple_element 641 | template< std::size_t I, typename T > 642 | struct tuple_element; 643 | 644 | template< std::size_t I, typename T > 645 | struct tuple_element< I, const T > 646 | : tuple_element< I, T > 647 | {}; 648 | 649 | template< std::size_t I, typename T > 650 | struct tuple_element< I, volatile T > 651 | : tuple_element< I, T > 652 | {}; 653 | 654 | template< std::size_t I, typename T > 655 | struct tuple_element< I, const volatile T > 656 | : tuple_element< I, T > 657 | {}; 658 | 659 | template< std::size_t I, typename... Ts > 660 | struct tuple_element< I, tuple< Ts... > > 661 | : seq::at_index< I, Ts... > 662 | {}; 663 | 664 | #if __cplusplus >= 201402L 665 | template< std::size_t I, typename T > 666 | using tuple_element_t = typename tuple_element< I, T >::type; 667 | #endif 668 | 669 | // 20.4.2.6 Element access [tuple.elem] 670 | 671 | // get 672 | template< std::size_t I, typename... Ts > 673 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON seq::at_index_t< I, Ts... >& get( tuple< Ts... >& v ) noexcept 674 | { 675 | return static_cast< impl::tuple_value< I, seq::at_index_t< I, Ts... > >& >( v.base ).get(); 676 | } 677 | 678 | template< std::size_t I, typename... Ts > 679 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON seq::at_index_t< I, Ts... >&& get( tuple< Ts... >&& v ) noexcept 680 | { 681 | using type = seq::at_index_t< I, Ts... >; 682 | return static_cast< type&& >( static_cast< impl::tuple_value< I, type >& >( v.base ).get() ); 683 | } 684 | 685 | template< std::size_t I, typename... Ts > 686 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON const seq::at_index_t< I, Ts... >& get( const tuple< Ts... >& v ) noexcept 687 | { 688 | return static_cast< const impl::tuple_value< I, seq::at_index_t< I, Ts... > >& >( v.base ).get(); 689 | } 690 | 691 | template< std::size_t I, typename... Ts > 692 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON const seq::at_index_t< I, Ts... >&& get( const tuple< Ts... >&& v ) noexcept 693 | { 694 | using type = seq::at_index_t< I, Ts... >; 695 | return static_cast< const type&& >( static_cast< const impl::tuple_value< I, type >& >( v.base ).get() ); 696 | } 697 | 698 | // get helper 699 | namespace impl 700 | { 701 | template< typename T, typename... Ts > 702 | using count_of = seq::sum< std::size_t, ( std::is_same< T, Ts >::value ? 1 : 0 )... >; 703 | 704 | template< typename, typename, typename... > 705 | struct index_of_impl; 706 | 707 | template< std::size_t... Is, typename T, typename... Ts > 708 | struct index_of_impl< seq::index_sequence< Is... >, T, Ts... > 709 | : seq::sum< std::size_t, ( std::is_same< T, Ts >::value ? Is : 0 )... > 710 | { 711 | static_assert( count_of< T, Ts... >::value > 0, "T not found within Ts..." ); 712 | static_assert( count_of< T, Ts... >::value < 2, "T must be unique within Ts..." ); 713 | }; 714 | 715 | template< typename T, typename... Ts > 716 | using index_of = index_of_impl< seq::index_sequence_for< Ts... >, T, Ts... >; 717 | 718 | } // namespace impl 719 | 720 | // get 721 | template< typename T, typename... Ts > 722 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON T& get( tuple< Ts... >& v ) noexcept 723 | { 724 | return get< impl::index_of< T, Ts... >::value >( v ); 725 | } 726 | 727 | template< typename T, typename... Ts > 728 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON T&& get( tuple< Ts... >&& v ) noexcept 729 | { 730 | return get< impl::index_of< T, Ts... >::value >( std::move( v ) ); 731 | } 732 | 733 | template< typename T, typename... Ts > 734 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON const T& get( const tuple< Ts... >& v ) noexcept 735 | { 736 | return get< impl::index_of< T, Ts... >::value >( v ); 737 | } 738 | 739 | template< typename T, typename... Ts > 740 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON const T&& get( const tuple< Ts... >&& v ) noexcept 741 | { 742 | return get< impl::index_of< T, Ts... >::value >( std::move( v ) ); 743 | } 744 | 745 | // 20.4.2.7 Relational operators [tuple.rel] 746 | 747 | // operators helper 748 | namespace impl 749 | { 750 | #ifdef __cpp_fold_expressions 751 | 752 | template< typename > 753 | struct tuple_equal; 754 | 755 | template< std::size_t... Is > 756 | struct tuple_equal< seq::index_sequence< Is... > > 757 | { 758 | template< typename T, typename U > 759 | static TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool apply( const T& lhs, const U& rhs ) noexcept( noexcept( ( static_cast< bool >( get< Is >( lhs ) == get< Is >( rhs ) ) && ... ) ) ) 760 | { 761 | return ( static_cast< bool >( get< Is >( lhs ) == get< Is >( rhs ) ) && ... ); 762 | } 763 | }; 764 | 765 | #else 766 | 767 | // here, recursion seems to be the better choice, especially wrt constexpr 768 | template< std::size_t I, std::size_t S > 769 | struct tuple_equal; 770 | 771 | template< std::size_t I > 772 | struct tuple_equal< I, I > 773 | { 774 | template< typename T, typename U > 775 | static TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool apply( const T&, const U& ) noexcept 776 | { 777 | return true; 778 | } 779 | }; 780 | 781 | template< std::size_t I, std::size_t S > 782 | struct tuple_equal 783 | { 784 | template< typename T, typename U > 785 | static TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool apply( const T& lhs, const U& rhs ) noexcept( noexcept( static_cast< bool >( get< I >( lhs ) == get< I >( rhs ) ) && tuple_equal< I + 1, S >::apply( lhs, rhs ) ) ) 786 | { 787 | return static_cast< bool >( get< I >( lhs ) == get< I >( rhs ) ) && tuple_equal< I + 1, S >::apply( lhs, rhs ); 788 | } 789 | }; 790 | 791 | #endif 792 | 793 | // here, recursion seems to be the better choice, especially wrt constexpr 794 | template< std::size_t I, std::size_t S > 795 | struct tuple_less; 796 | 797 | template< std::size_t I > 798 | struct tuple_less< I, I > 799 | { 800 | template< typename T, typename U > 801 | static TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool apply( const T&, const U& ) noexcept 802 | { 803 | return false; 804 | } 805 | }; 806 | 807 | template< std::size_t I, std::size_t S > 808 | struct tuple_less 809 | { 810 | template< typename T, typename U > 811 | static TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool apply( const T& lhs, const U& rhs ) noexcept( noexcept( static_cast< bool >( get< I >( lhs ) < get< I >( rhs ) ) || ( !static_cast< bool >( get< I >( rhs ) < get< I >( lhs ) ) && tuple_less< I + 1, S >::apply( lhs, rhs ) ) ) ) 812 | { 813 | return static_cast< bool >( get< I >( lhs ) < get< I >( rhs ) ) || ( !static_cast< bool >( get< I >( rhs ) < get< I >( lhs ) ) && tuple_less< I + 1, S >::apply( lhs, rhs ) ); 814 | } 815 | }; 816 | 817 | } // namespace impl 818 | 819 | // operators 820 | 821 | #ifdef __cpp_fold_expressions 822 | 823 | template< typename... Ts, typename... Us, typename = impl::enable_if_t< sizeof...( Ts ) == sizeof...( Us ) > > 824 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool operator==( const tuple< Ts... >& lhs, const tuple< Us... >& rhs ) noexcept( noexcept( impl::tuple_equal< seq::make_index_sequence< sizeof...( Ts ) > >::apply( lhs, rhs ) ) ) 825 | { 826 | return impl::tuple_equal< seq::make_index_sequence< sizeof...( Ts ) > >::apply( lhs, rhs ); 827 | } 828 | 829 | #else 830 | 831 | template< typename... Ts, typename... Us, typename = impl::enable_if_t< sizeof...( Ts ) == sizeof...( Us ) > > 832 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool operator==( const tuple< Ts... >& lhs, const tuple< Us... >& rhs ) noexcept( noexcept( impl::tuple_equal< 0, sizeof...( Ts ) >::apply( lhs, rhs ) ) ) 833 | { 834 | return impl::tuple_equal< 0, sizeof...( Ts ) >::apply( lhs, rhs ); 835 | } 836 | 837 | #endif 838 | 839 | template< typename... Ts, typename... Us > 840 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool operator!=( const tuple< Ts... >& lhs, const tuple< Us... >& rhs ) noexcept( noexcept( !( lhs == rhs ) ) ) 841 | { 842 | return !( lhs == rhs ); 843 | } 844 | 845 | template< typename... Ts, typename... Us, typename = impl::enable_if_t< sizeof...( Ts ) == sizeof...( Us ) > > 846 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool operator<( const tuple< Ts... >& lhs, const tuple< Us... >& rhs ) noexcept( noexcept( impl::tuple_less< 0, sizeof...( Ts ) >::apply( lhs, rhs ) ) ) 847 | { 848 | return impl::tuple_less< 0, sizeof...( Ts ) >::apply( lhs, rhs ); 849 | } 850 | 851 | template< typename... Ts, typename... Us > 852 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool operator>=( const tuple< Ts... >& lhs, const tuple< Us... >& rhs ) noexcept( noexcept( !( lhs < rhs ) ) ) 853 | { 854 | return !( lhs < rhs ); 855 | } 856 | 857 | template< typename... Ts, typename... Us > 858 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool operator>( const tuple< Ts... >& lhs, const tuple< Us... >& rhs ) noexcept( noexcept( rhs < lhs ) ) 859 | { 860 | return rhs < lhs; 861 | } 862 | 863 | template< typename... Ts, typename... Us > 864 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool operator<=( const tuple< Ts... >& lhs, const tuple< Us... >& rhs ) noexcept( noexcept( !( rhs < lhs ) ) ) 865 | { 866 | return !( rhs < lhs ); 867 | } 868 | 869 | // 20.4.2.9 Tuple specialized algorithms [tuple.special] 870 | 871 | // swap 872 | template< typename... Ts > 873 | TAO_TUPLE_CUDA_ANNOTATE_COMMON void swap( tuple< Ts... >& lhs, tuple< Ts... >& rhs ) noexcept( noexcept( lhs.swap( rhs ) ) ) 874 | { 875 | lhs.swap( rhs ); 876 | } 877 | 878 | // (continued:) 20.4.2.4 Tuple creation functions [tuple.creation] 879 | 880 | // tuple_cat helper 881 | namespace impl 882 | { 883 | template< std::size_t M, std::size_t... Ns > 884 | struct count_less_or_equal 885 | : seq::sum< std::size_t, ( ( Ns <= M ) ? 1 : 0 )... > 886 | {}; 887 | 888 | template< typename, typename > 889 | struct expand; 890 | 891 | template< std::size_t... Is, std::size_t... Ns > 892 | struct expand< seq::index_sequence< Is... >, seq::index_sequence< Ns... > > 893 | { 894 | template< std::size_t I > 895 | using cleq = count_less_or_equal< I, Ns... >; 896 | 897 | using type = seq::index_sequence< cleq< Is >::value... >; 898 | }; 899 | 900 | template< typename I, typename S > 901 | using expand_t = typename expand< I, S >::type; 902 | 903 | template< typename... > 904 | struct tuple_cat_result; 905 | 906 | template< std::size_t... Os, std::size_t... Is, typename... Ts > 907 | struct tuple_cat_result< seq::index_sequence< Os... >, seq::index_sequence< Is... >, Ts... > 908 | { 909 | using type = tuple< typename tuple_element< Is, seq::at_index_t< Os, Ts... > >::type... >; 910 | }; 911 | 912 | template< typename... Ts > 913 | using tuple_cat_result_t = typename tuple_cat_result< Ts... >::type; 914 | 915 | template< typename... Ts > 916 | struct tuple_cat_helper 917 | { 918 | using tuple_size_sequence = seq::index_sequence< tuple_size< Ts >::value... >; 919 | using result_index_sequence = seq::make_index_sequence< seq::sum< tuple_size_sequence >::value >; 920 | 921 | using outer_index_sequence = expand_t< result_index_sequence, seq::inclusive_scan_t< tuple_size_sequence > >; 922 | using inner_index_sequence = seq::minus_t< result_index_sequence, seq::map_t< outer_index_sequence, seq::exclusive_scan_t< tuple_size_sequence > > >; 923 | 924 | using result_type = tuple_cat_result_t< outer_index_sequence, inner_index_sequence, Ts... >; 925 | }; 926 | 927 | template< typename R, std::size_t... Os, std::size_t... Is, typename T > 928 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON R tuple_cat( seq::index_sequence< Os... >, seq::index_sequence< Is... >, T v ) 929 | { 930 | return R( get< Is >( get< Os >( v ) )... ); 931 | } 932 | 933 | } // namespace impl 934 | 935 | // tuple_cat 936 | template< typename... Ts, typename H = impl::tuple_cat_helper< typename std::remove_reference< Ts >::type... >, typename R = typename H::result_type > 937 | TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON R tuple_cat( Ts&&... ts ) 938 | { 939 | return impl::tuple_cat< R >( typename H::outer_index_sequence(), typename H::inner_index_sequence(), tao::forward_as_tuple( std::forward< Ts >( ts )... ) ); 940 | } 941 | 942 | } // namespace tao 943 | 944 | #undef TAO_TUPLE_CONSTEXPR 945 | #undef TAO_TUPLE_CUDA_ANNOTATE_COMMON 946 | #undef TAO_TUPLE_SUPPRESS_NVCC_HD_WARN 947 | 948 | #endif 949 | -------------------------------------------------------------------------------- /src/test/tuple/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.3.0 FATAL_ERROR) 2 | 3 | set (test_sources 4 | tuple_benchmark.cpp 5 | tuple_cat.cpp 6 | tuple_main.cpp 7 | ) 8 | 9 | # file (GLOB ...) is used to validate the above list of test_sources 10 | file (GLOB glob_test_sources RELATIVE ${CMAKE_CURRENT_LIST_DIR} *.cpp) 11 | 12 | foreach (testsourcefile ${test_sources}) 13 | if (${testsourcefile} IN_LIST glob_test_sources) 14 | list (REMOVE_ITEM glob_test_sources ${testsourcefile}) 15 | else () 16 | message (SEND_ERROR "File ${testsourcefile} is missing from src/test/tuple") 17 | endif () 18 | 19 | get_filename_component (exename ${testsourcefile} NAME_WE) 20 | set (exename "tao-tuple-test-${exename}") 21 | add_executable (${exename} ${testsourcefile}) 22 | target_link_libraries (${exename} PRIVATE taocpp::tuple) 23 | set_target_properties (${exename} PROPERTIES 24 | CXX_STANDARD 11 25 | CXX_STANDARD_REQUIRED ON 26 | CXX_EXTENSIONS OFF 27 | ) 28 | if (MSVC) 29 | target_compile_options (${exename} PRIVATE /W4 /WX /utf-8) 30 | else () 31 | target_compile_options (${exename} PRIVATE -pedantic -Wall -Wextra -Wshadow -Werror) 32 | endif () 33 | add_test (NAME ${exename} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../.. COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${exename}) 34 | endforeach (testsourcefile) 35 | 36 | if (glob_test_sources) 37 | foreach (ignored_source_file ${glob_test_sources}) 38 | message (SEND_ERROR "File ${ignored_source_file} in src/test/tuple is ignored") 39 | endforeach (ignored_source_file) 40 | endif () 41 | -------------------------------------------------------------------------------- /src/test/tuple/tuple_benchmark.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/tuple/ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | // To benchmark the standard library's version, enable this: 10 | // #define tao std 11 | 12 | int main() 13 | { 14 | auto t = tao::tuple_cat( tao::make_tuple( 1, true ), 15 | tao::make_tuple( 1.0 ), 16 | tao::make_tuple(), 17 | tao::make_tuple( 1UL, nullptr ) ); 18 | 19 | static_assert( std::is_same< decltype( t ), tao::tuple< int, bool, double, unsigned long, std::nullptr_t > >::value, "oops" ); 20 | 21 | auto t2 = tao::tuple_cat( t, tao::make_tuple( 1, true ), t, tao::make_tuple( 1.0 ), t, tao::make_tuple(), t, tao::make_tuple( 1UL, nullptr ) ); 22 | 23 | static_assert( tao::tuple_size< decltype( t2 ) >::value == 25, "oops" ); 24 | 25 | auto t3 = tao::tuple_cat( t2, tao::make_tuple( 1, true ), t2, tao::make_tuple( 1.0 ), t2, tao::make_tuple(), t2, tao::make_tuple( 1UL, nullptr ) ); 26 | 27 | static_assert( tao::tuple_size< decltype( t3 ) >::value == 105, "oops" ); 28 | 29 | auto t4 = tao::tuple_cat( t3, tao::make_tuple( 1, true ), t2, tao::make_tuple( 1.0 ), t3, tao::make_tuple(), t2, tao::make_tuple( 1UL, nullptr ) ); 30 | 31 | static_assert( tao::tuple_size< decltype( t4 ) >::value == 265, "oops" ); 32 | } 33 | -------------------------------------------------------------------------------- /src/test/tuple/tuple_cat.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/tuple/ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | using namespace tao; 12 | 13 | auto t = tuple_cat( make_tuple( 1, true ), 14 | make_tuple( 2.0 ), 15 | make_tuple(), 16 | make_tuple( 3UL, nullptr ) ); 17 | 18 | static_assert( tuple_size< decltype( t ) >::value == 5, "oops" ); 19 | static_assert( std::is_same< decltype( t ), tuple< int, bool, double, unsigned long, std::nullptr_t > >::value, "oops" ); 20 | 21 | assert( get< 0 >( t ) == 1 ); 22 | assert( get< 1 >( t ) == true ); 23 | assert( get< 2 >( t ) == 2.0 ); 24 | assert( get< 3 >( t ) == 3UL ); 25 | assert( get< 4 >( t ) == nullptr ); 26 | 27 | assert( get< int >( t ) == 1 ); 28 | assert( get< bool >( t ) == true ); 29 | assert( get< double >( t ) == 2.0 ); 30 | assert( get< unsigned long >( t ) == 3 ); 31 | assert( get< std::nullptr_t >( t ) == nullptr ); 32 | } 33 | -------------------------------------------------------------------------------- /src/test/tuple/tuple_main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2020 Daniel Frey 2 | // Please see LICENSE for license or visit https://github.com/taocpp/tuple/ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | using namespace tao; 12 | 13 | auto t = tuple< int, double, int >(); 14 | auto t2 = tuple< int, double, int >( 1, 2, 3 ); 15 | auto t3( t2 ); 16 | 17 | auto t4 = tuple< int, double, int >( 1, 2, 2 ); 18 | auto t5 = tuple< int, double, int >( 1, 2, 4 ); 19 | 20 | static_assert( tuple_size< decltype( t ) >::value == 3, "oops" ); 21 | static_assert( tuple_size< decltype( t2 ) >::value == 3, "oops" ); 22 | static_assert( tuple_size< decltype( t3 ) >::value == 3, "oops" ); 23 | #ifndef _MSC_VER // Known failure on Microsoft compiler 24 | static_assert( std::is_trivially_copyable< tuple< int > >::value, "" ); 25 | #endif 26 | static_assert( std::is_trivially_destructible< tuple< int > >::value, "" ); 27 | 28 | struct composite 29 | { 30 | tuple< int, double, int > inner; 31 | }; 32 | 33 | composite t6; 34 | composite t7; 35 | 36 | // Just check for the existence of these (if they exist they are compiler 37 | // generated and should work correctly) 38 | t6 = t7; 39 | t6 = std::move( t7 ); 40 | 41 | assert( get< 0 >( t2 ) == 1 ); 42 | assert( get< 1 >( t2 ) == 2 ); 43 | assert( get< 2 >( t2 ) == 3 ); 44 | 45 | assert( get< double >( t2 ) == 2 ); 46 | 47 | assert( get< 0 >( t3 ) == 1 ); 48 | assert( get< 1 >( t3 ) == 2 ); 49 | assert( get< 2 >( t3 ) == 3 ); 50 | 51 | assert( get< double >( t3 ) == 2 ); 52 | 53 | assert( t2 == t3 ); 54 | assert( t2 != t4 ); 55 | assert( t2 > t4 ); 56 | assert( t2 < t5 ); 57 | assert( t2 >= t3 ); 58 | assert( t2 <= t3 ); 59 | assert( t2 >= t4 ); 60 | assert( t2 <= t5 ); 61 | 62 | assert( tuple<>() == tuple<>() ); 63 | assert( !( tuple<>() < tuple<>() ) ); 64 | 65 | assert( make_tuple( 0 ) == make_tuple( 0 ) ); 66 | 67 | assert( make_tuple( 1, 2, 3 ) > make_tuple( 1, 2, 2 ) ); 68 | assert( make_tuple( 1, 2, 3 ) < make_tuple( 1, 2, 4 ) ); 69 | 70 | assert( ( tuple< int, int, int >( std::allocator_arg, 5, 1, 2, 3 ) < make_tuple( 1, 2, 4 ) ) ); 71 | 72 | #if( __cplusplus >= 201402L ) 73 | 74 | static_assert( tuple<>() == tuple<>(), "oops" ); 75 | static_assert( make_tuple() == make_tuple(), "oops" ); 76 | static_assert( make_tuple( 0 ) == make_tuple( 0 ), "oops" ); 77 | 78 | static_assert( make_tuple( 1, 2, 3 ) > make_tuple( 1, 2, 2 ), "oops" ); 79 | static_assert( make_tuple( 1, 2, 3 ) < make_tuple( 1, 2, 4 ), "oops" ); 80 | 81 | // TODO: More constexpr checks 82 | 83 | #endif 84 | } 85 | --------------------------------------------------------------------------------