├── .conan └── test_package │ ├── src │ └── main.cpp │ ├── conanfile.py │ └── CMakeLists.txt ├── doc ├── images │ ├── backport-logo.png │ └── backport-logo.svg ├── doxygen │ └── footer.html ├── legal.md ├── installing.md └── commit-standards.md ├── cmake ├── templates │ └── PackageConfig.cmake.in ├── AddSelfContainmentTest.cmake └── SourceGroup.cmake ├── .github ├── ISSUE_TEMPLATE │ ├── question.md │ ├── feature_request.md │ └── bug_report.md ├── FUNDING.yml ├── CODEOWNERS ├── workflows │ ├── deploy-conan.yml │ ├── analysis.yml │ ├── scan-build.yml │ ├── deploy-doxygen.yml │ ├── coverage.yml │ ├── build-macos.yml │ ├── build-windows.yml │ └── build-ubuntu.yml ├── PULL_REQUEST_TEMPLATE.md └── CONTRIBUTING.md ├── tools └── run-doxygen.py ├── LICENSE ├── test ├── src │ ├── main.cpp │ └── bpstd │ │ ├── iterator.test.cpp │ │ ├── exception.test.cpp │ │ ├── complex.test.cpp │ │ ├── memory.test.cpp │ │ ├── utility.test.cpp │ │ └── type_traits.test.cpp └── CMakeLists.txt ├── conanfile.py ├── include └── bpstd │ ├── detail │ ├── variant_fwds.hpp │ ├── nth_type.hpp │ ├── enable_overload.hpp │ ├── move.hpp │ ├── config.hpp │ ├── variant_traits.hpp │ ├── variant_visitors.hpp │ ├── invoke.hpp │ └── variant_base.hpp │ ├── string.hpp │ ├── complex.hpp │ ├── chrono.hpp │ ├── exception.hpp │ ├── memory.hpp │ ├── cstddef.hpp │ ├── iterator.hpp │ ├── tuple.hpp │ └── utility.hpp ├── CODE_OF_CONDUCT.md └── CMakeLists.txt /.conan/test_package/src/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | int main() 5 | { 6 | return 0; 7 | } -------------------------------------------------------------------------------- /doc/images/backport-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwizeshift/BackportCpp/HEAD/doc/images/backport-logo.png -------------------------------------------------------------------------------- /cmake/templates/PackageConfig.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | if (NOT TARGET Backport::Backport) 4 | include("${CMAKE_CURRENT_LIST_DIR}/BackportTargets.cmake") 5 | endif () -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Ask a question to the maintainers 4 | 5 | --- 6 | 7 | ### Checklist 8 | 9 | - [ ] This question has not yet been asked in the Github Issues section. 10 | 11 | ---------- 12 | 13 | ### Description 14 | 17 | -------------------------------------------------------------------------------- /doc/doxygen/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | -------------------------------------------------------------------------------- /.conan/test_package/conanfile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from conans import ConanFile, CMake 3 | 4 | class BackportConanTest(ConanFile): 5 | settings = "os", "compiler", "arch", "build_type" 6 | generators = "cmake" 7 | 8 | def build(self): 9 | cmake = CMake(self) 10 | cmake.configure() 11 | cmake.build() 12 | 13 | def imports(self): 14 | pass 15 | 16 | def test(self): 17 | pass 18 | -------------------------------------------------------------------------------- /.conan/test_package/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | 3 | project(Backport.ConanTestPackage) 4 | 5 | include("${CMAKE_BINARY_DIR}/conanbuildinfo.cmake") 6 | conan_set_find_paths() 7 | 8 | find_package(Backport REQUIRED) 9 | 10 | set(source_files 11 | src/main.cpp 12 | ) 13 | 14 | add_executable(${PROJECT_NAME} 15 | ${source_files} 16 | ) 17 | target_link_libraries(${PROJECT_NAME} 18 | PRIVATE Backport::Backport 19 | ) -------------------------------------------------------------------------------- /tools/run-doxygen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Script for generating doxygen output 4 | """ 5 | 6 | def root_path(): 7 | import os 8 | 9 | path = os.path.realpath(__file__) # ./tools/run-doxygen.py 10 | path = os.path.dirname(path) # ./tools/ 11 | path = os.path.dirname(path) # ./ 12 | 13 | return path 14 | 15 | 16 | if __name__ == "__main__": 17 | 18 | import subprocess 19 | import os 20 | 21 | doxyfile_path = os.path.join(root_path(),".codedocs") 22 | 23 | subprocess.run(["doxygen", doxyfile_path], 24 | cwd=root_path(), 25 | check=True) -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [bitwizeshift] 4 | patreon: bitwizeshift 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: https://www.buymeacoffee.com/dsq3XCcBE 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Request a standard library type that is absent from this project 4 | 5 | --- 6 | 7 | ### Checklist 8 | 9 | - [ ] I did not find a duplicate of this feature request in the Github Issues section. 10 | 11 | ---------- 12 | 13 | ### Description 14 | 26 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | #============================================================================== 2 | # CODEOWNERS 3 | #------------------------------------------------------------------------------ 4 | # This file outlines the owners of the various code sections within this 5 | # project 6 | #============================================================================== 7 | 8 | #------------------------------------------------------------------------------ 9 | # Global Owners 10 | #------------------------------------------------------------------------------ 11 | 12 | * @bitwizeshift 13 | 14 | #------------------------------------------------------------------------------ 15 | # Subsystem Owners 16 | #------------------------------------------------------------------------------ 17 | 18 | # ... 19 | 20 | #------------------------------------------------------------------------------ 21 | # File Owners 22 | #------------------------------------------------------------------------------ 23 | 24 | # ... -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | ### Checklist 8 | 9 | - [ ] I did not find a duplicate of this bug in the Github Issues section. 10 | 11 | ---------- 12 | 13 | ### Description 14 | 17 | 18 | 19 | ### Steps to reproduce 20 | 26 | 27 | #### Expected Behavior 28 | 31 | 32 | #### Actual Behavior 33 | 36 | 37 | ### Extra information 38 | 41 | * Library version: **X.Y.Z** 42 | * Operating System: **** 43 | * Compiler: **** 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Matthew Rodusek 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 | -------------------------------------------------------------------------------- /test/src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #define CATCH_CONFIG_MAIN 26 | #include 27 | -------------------------------------------------------------------------------- /conanfile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from conans import ConanFile, CMake 4 | 5 | class BackportConan(ConanFile): 6 | 7 | # Package Info 8 | name = "Backport" 9 | version = "1.2.0" 10 | description = "Modern C++ backported to C++11" 11 | url = "https://github.com/bitwizeshift/bpstd" 12 | author = "Matthew Rodusek " 13 | license = "MIT" 14 | generators = "cmake" 15 | 16 | # Sources 17 | exports = ("LICENSE") 18 | exports_sources = ("cmake/*", 19 | "include/*", 20 | "test/*", 21 | "CMakeLists.txt", 22 | "LICENSE") 23 | 24 | # Settings 25 | options = {} 26 | default_options = {} 27 | build_requires = ("Catch2/2.7.1@catchorg/stable") 28 | 29 | def source(self): 30 | pass 31 | 32 | def build(self): 33 | pass 34 | 35 | def test(self): 36 | pass 37 | 38 | def package(self): 39 | cmake = CMake(self) 40 | cmake.definitions["BACKPORT_COMPILE_UNIT_TESTS"] = "ON" 41 | cmake.configure() 42 | 43 | # Compile and run the unit tests 44 | cmake.build() 45 | cmake.build(target="test") 46 | 47 | cmake.install() 48 | 49 | self.copy(pattern="LICENSE", dst="licenses") 50 | return 51 | 52 | def package_id(self): 53 | self.info.header_only() 54 | return 55 | -------------------------------------------------------------------------------- /.github/workflows/deploy-conan.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Conan 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | deploy: 9 | name: Deployment Agent 10 | runs-on: ubuntu-20.04 11 | steps: 12 | - name: Checkout Repository 13 | uses: actions/checkout@v2 14 | 15 | - name: Set up Python 16 | uses: actions/setup-python@v1 17 | with: 18 | python-version: 3.7 19 | 20 | - name: Install Dependencies 21 | run: | 22 | python -m pip install --upgrade pip 23 | pip install conan 24 | conan --version 25 | 26 | - name: Prepare Conan Environment 27 | run: | 28 | conan remote add bintray ${{ secrets.BINTRAY_REMOTE_URL }} 29 | conan user -p ${{ secrets.BINTRAY_API_KEY }} -r bintray ${{ secrets.BINTRAY_USERNAME }} 30 | version=$(conan inspect $(pwd) --attribute version | sed 's@version: @@g') 31 | echo "CONAN_PACKAGE_PATH=Backport/${version}@backport/stable" >> ${GITHUB_ENV} 32 | 33 | - name: Package 34 | run: | 35 | conan create . "backport/stable" 36 | 37 | - name: Test Package 38 | run: | 39 | conan test $(pwd)/.conan/test_package "${CONAN_PACKAGE_PATH}" 40 | 41 | - name: Deploy 42 | run: | 43 | conan upload "${CONAN_PACKAGE_PATH}" -r bintray --all 44 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | find_package(Catch2 REQUIRED) 3 | 4 | set(source_files 5 | "src/main.cpp" 6 | "src/bpstd/functional.test.cpp" 7 | "src/bpstd/complex.test.cpp" 8 | "src/bpstd/tuple.test.cpp" 9 | "src/bpstd/any.test.cpp" 10 | "src/bpstd/exception.test.cpp" 11 | "src/bpstd/string_view.test.cpp" 12 | "src/bpstd/optional.test.cpp" 13 | "src/bpstd/span.test.cpp" 14 | "src/bpstd/memory.test.cpp" 15 | "src/bpstd/type_traits.test.cpp" 16 | "src/bpstd/iterator.test.cpp" 17 | "src/bpstd/utility.test.cpp" 18 | "src/bpstd/variant.test.cpp" 19 | ) 20 | 21 | add_executable(${PROJECT_NAME}.test 22 | ${source_files} 23 | ) 24 | add_executable(${PROJECT_NAME}::test ALIAS ${PROJECT_NAME}.test) 25 | 26 | target_link_libraries(${PROJECT_NAME}.test 27 | PRIVATE ${PROJECT_NAME}::${PROJECT_NAME} 28 | PRIVATE Catch2::Catch2 29 | ) 30 | 31 | set_target_properties(${UNITTEST_TARGET_NAME} PROPERTIES 32 | CXX_STANDARD 11 33 | CXX_STANDARD_REQUIRED ON 34 | CXX_EXTENSIONS OFF 35 | COMPILE_DEFINITIONS "$<$:_SCL_SECURE_NO_WARNINGS>" 36 | COMPILE_OPTIONS "$<$:/EHsc;$<$:/Od>>" 37 | ) 38 | 39 | ############################################################################## 40 | # CTest 41 | ############################################################################## 42 | 43 | include(Catch) 44 | catch_discover_tests(${PROJECT_NAME}.test) 45 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Checklist 2 | 5 | - [ ] I have read the [CONTRIBUTING](CONTRIBUTING.md) guidelines 6 | - [ ] The coding style is consistent with the rest of the library 7 | - [ ] My branch's history is clean and coherent. This could be done through 8 | at least one of the following practices: 9 | * Rebasing my branch off of the branch being merged to 10 | * Squashing commits to create a more cohesive history 11 | - [ ] If relevant, I have included unit-tests (for new code/bugfixes) 12 | 13 | ---------- 14 | 15 | ### Description 16 | 17 | 22 | 23 | ## GitHub Issues 24 | 36 | -------------------------------------------------------------------------------- /doc/legal.md: -------------------------------------------------------------------------------- 1 | # Legal 2 | 3 | 4 | 5 | **Backport** is licensed under the [MIT License](../LICENSE), 6 | which is an open-source initiative approved license. 7 | 8 | Under this license, you may use **Backport** for any purpose you wish 9 | _WITHOUT ANY WARRANTY_, and modify it as you see fit -- subject to the one 10 | condition: 11 | 12 | > The above copyright notice and this permission notice shall be included in 13 | > all copies or substantial portions of the software 14 | 15 | ## Simplified 16 | 17 | In non legal terms, this means that whenever an application built with 18 | **Backport** is distributed -- either as source code, or as a binary package, 19 | the [license text](../LICENSE) must also accompany the distribution in some 20 | form. 21 | This may be in the form of a printed documentation, a digital list of 22 | credits distributed with the application, or even as acknowledgement 23 | from within the application itself (e.g. in credits, 'about', etc). 24 | 25 | Similarly, if the the **Backport** project is used as the basis to a new 26 | library or distribution, attribution must be made for any substantially copied 27 | portions (algorithms, designs, etc.). 28 | 29 | ## Endorsement 30 | 31 | At no point is **Backport** or any of its contributors to be misrepresented as 32 | endorsing a project that uses this engine without prior written 33 | acknowledgement from the maintainers. -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | ## Did you find a bug? 4 | 5 | * Ensure the bug was not already reported by searching on Github under 6 | Issues. 7 | * If you're unable to find an open issue addressing the problem, open a new 8 | one. Be sure to include a title and clear description, as much relevant 9 | information as possible, and a code sample or an executable test case 10 | demonstrating the expected behavior that is not occurring. 11 | * If possible, use the relevant bug report template to create the issue. 12 | 13 | ## Did you fix a bug? 14 | 15 | * Open a new Github pull-request with the patch. 16 | * Ensure the PR description clearly describes the problem and solution. 17 | Include the relevant issue number if applicable. 18 | 19 | ## Do you intend to add a new feature, or change an existing one? 20 | 21 | * Open an issue on Github to get a discussion going first before 22 | proceeding. 23 | * Open individual issues for each suggested feature, and individual 24 | pull-requests for each one. 25 | * New features being introduce should include unit tests and 26 | documentation where necessary. 27 | 28 | ## Are you opening a pull-request? 29 | 30 | * The pull request should have a useful title 31 | * Please make sure your commits follow **Backport**'s 32 | [commit standards](../doc/commit-standards.md) 33 | * Please follow the existing conventions of the library for new contributions 34 | * Keep descriptions short and simple, but descriptive. 35 | * Start the description with a capital and end with a full stop/period. 36 | * Check your spelling and grammar. 37 | * Make sure your text editor is set to remove trailing whitespace. 38 | 39 | ## Do you have any questions about the library? 40 | 41 | * Open a Github issue with a title indicating the question. 42 | -------------------------------------------------------------------------------- /.github/workflows/analysis.yml: -------------------------------------------------------------------------------- 1 | name: "Code Scanning" 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths: 7 | - 'include/**.hpp' 8 | - 'test/**.cpp' 9 | - '**.cmake' 10 | - 'conanfile.py' 11 | - 'CMakeLists.txt' 12 | - 'test/CMakeLists.txt' 13 | - '.github/workflows/analysis.yml' 14 | pull_request: 15 | branches: [master] 16 | paths: 17 | - 'include/**.hpp' 18 | - 'test/**.cpp' 19 | - '**.cmake' 20 | - 'conanfile.py' 21 | - 'CMakeLists.txt' 22 | - 'test/CMakeLists.txt' 23 | - '.github/workflows/analysis.yml' 24 | 25 | jobs: 26 | analysis: 27 | name: CodeQL Analysis 28 | runs-on: ubuntu-20.04 29 | 30 | env: 31 | build-directory: build 32 | 33 | strategy: 34 | matrix: 35 | language: ['cpp'] 36 | 37 | steps: 38 | - name: Checkout repository 39 | uses: actions/checkout@v2 40 | 41 | - name: Set up Python 42 | uses: actions/setup-python@v1 43 | with: 44 | python-version: 3.7 45 | 46 | - name: Prepare Environment 47 | run: | 48 | python -m pip install --upgrade pip 49 | pip install conan 50 | cmake -E make_directory ${{env.build-directory}} 51 | cmake -E chdir ${{env.build-directory}} conan install .. 52 | 53 | - name: Initialize CodeQL 54 | uses: github/codeql-action/init@v1 55 | 56 | - name: Configure 57 | working-directory: ${{env.build-directory}} 58 | run: cmake .. -DCMAKE_BUILD_TYPE=Debug -DBACKPORT_COMPILE_UNIT_TESTS=On 59 | 60 | - name: Build 61 | working-directory: ${{env.build-directory}} 62 | run: cmake --build . 63 | 64 | - name: Perform CodeQL Analysis 65 | uses: github/codeql-action/analyze@v1 66 | -------------------------------------------------------------------------------- /.github/workflows/scan-build.yml: -------------------------------------------------------------------------------- 1 | name: "Scan Build" 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths: 7 | - 'include/**.hpp' 8 | - 'test/**.cpp' 9 | - '**.cmake' 10 | - 'conanfile.py' 11 | - 'CMakeLists.txt' 12 | - 'test/CMakeLists.txt' 13 | - '.github/workflows/scan-build.yml' 14 | pull_request: 15 | branches: [master] 16 | paths: 17 | - 'include/**.hpp' 18 | - 'test/**.cpp' 19 | - '**.cmake' 20 | - 'conanfile.py' 21 | - 'CMakeLists.txt' 22 | - 'test/CMakeLists.txt' 23 | - '.github/workflows/scan-build.yml' 24 | 25 | jobs: 26 | scan: 27 | runs-on: ubuntu-20.04 28 | 29 | env: 30 | build-directory: build 31 | artifact-directory: scan-result 32 | 33 | steps: 34 | - name: Clone 35 | uses: actions/checkout@v2 36 | 37 | - name: Set up Python 38 | uses: actions/setup-python@v1 39 | with: 40 | python-version: 3.7 41 | 42 | - name: Prepare Environment 43 | run: | 44 | sudo apt-get update 45 | sudo apt-get install -y clang clang-tools g++-multilib 46 | python -m pip install --upgrade pip 47 | pip install conan cpp-coveralls 48 | cmake -E make_directory ${{env.build-directory}} 49 | cmake -E chdir ${{env.build-directory}} conan install .. 50 | 51 | - name: Configure 52 | working-directory: ${{env.build-directory}} 53 | run: | 54 | scan-build -o ../${{env.artifact-directory}} cmake .. \ 55 | -DCMAKE_BUILD_TYPE=Debug \ 56 | -DBACKPORT_COMPILE_UNIT_TESTS=On 57 | 58 | - name: Scan 59 | working-directory: ${{env.build-directory}} 60 | run: | 61 | scan-build -o ../${{env.artifact-directory}} cmake --build . 62 | 63 | - uses: actions/upload-artifact@v2 64 | with: 65 | name: Scan Results 66 | path: ${{env.artifact-directory}}/ 67 | -------------------------------------------------------------------------------- /include/bpstd/detail/variant_fwds.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * \file variant_fwds.hpp 3 | * 4 | * \brief This internal header provides forward declarations of various 5 | * variant types used internally 6 | *****************************************************************************/ 7 | 8 | /* 9 | The MIT License (MIT) 10 | 11 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in 21 | all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | SOFTWARE. 30 | */ 31 | #ifndef BPSTD_DETAIL_VARIANT_FWDS_HPP 32 | #define BPSTD_DETAIL_VARIANT_FWDS_HPP 33 | 34 | namespace bpstd { 35 | namespace detail { 36 | 37 | template 38 | union variant_union; 39 | 40 | template 41 | class variant_base; 42 | 43 | } // namespace detail 44 | 45 | template 46 | class variant; 47 | 48 | } // namespace bpstd 49 | 50 | #endif /* BPSTD_DETAIL_VARIANT_FWDS_HPP */ 51 | -------------------------------------------------------------------------------- /test/src/bpstd/iterator.test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | // MSVC 2015 seems to emit an error that __forceinline'd functions may not be 32 | // __forceinline'd at the *end of the translation unit* using it, for some 33 | // stupid reason. 34 | #if defined(_MSC_VER) 35 | # pragma warning(disable:4714) 36 | #endif 37 | 38 | TEST_CASE("make_reverse_iterator(...)", "[iterator]") 39 | { 40 | const auto input = std::vector{1,2,3,4,5}; 41 | const auto expected = std::vector{5,4,3,2,1}; 42 | 43 | SECTION("Reverses range") 44 | { 45 | const auto begin = bpstd::make_reverse_iterator(input.end()); 46 | const auto end = bpstd::make_reverse_iterator(input.begin()); 47 | 48 | REQUIRE(std::equal(begin, end, expected.begin())); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /.github/workflows/deploy-doxygen.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Doxygen (Latest) 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths: 7 | - 'include/**.hpp' 8 | - 'README.md' 9 | - 'doc/**.md' 10 | - '.codedocs' 11 | release: 12 | types: [published] 13 | 14 | jobs: 15 | ci: 16 | name: Deployment Agent 17 | runs-on: ubuntu-20.04 18 | steps: 19 | - name: Checkout Repository 20 | uses: actions/checkout@v2 21 | 22 | - name: Install 23 | run: | 24 | sudo apt-get update 25 | sudo apt-get install -y doxygen 26 | doxygen --version 27 | 28 | - name: Generate Documentation 29 | run: | 30 | mkdir -p "$(pwd)/build/doc" 31 | doxygen "$(pwd)/.codedocs" 32 | 33 | - name: Prepare Pages 34 | run: | 35 | if [ ${{ github.event_name }} == "release" ]; then 36 | version="v$(conan inspect . --attribute version | sed 's@version: @@g')" 37 | echo "API_DOC_PATH=$(pwd)/dist/api/${version}" >> $GITHUB_ENV 38 | else 39 | echo "API_DOC_PATH=$(pwd)/dist/api/latest" >> $GITHUB_ENV 40 | fi 41 | 42 | # Clone a git repo for doxygen 43 | git config --global user.email "action@github.com" 44 | git config --global user.name "GitHub Action" 45 | git clone --single-branch -b gh-pages "https://github.com/${GITHUB_REPOSITORY}" "dist" 46 | git config --global push.default simple 47 | 48 | - name: Update Pages 49 | run: | 50 | # Add a .nojekyll file 51 | touch "dist/.nojekyll" 52 | 53 | rm -rf "${API_DOC_PATH}" 54 | mkdir -p "${API_DOC_PATH}" 55 | mv $(pwd)/build/doc/html/* "${API_DOC_PATH}" 56 | 57 | cd "dist" 58 | git add --all 59 | 60 | if ! git diff-index --quiet HEAD --; then 61 | git commit \ 62 | -m "📖 Deploy codedocs to Github Pages" \ 63 | -m "Documentation updated by build ${{ github.run_number }}." \ 64 | -m "Commit: '${{ github.sha }}'" \ 65 | --author "GitHub Action " \ 66 | --no-gpg-sign 67 | fi 68 | cd .. 69 | 70 | - name: Publish Pages 71 | uses: ad-m/github-push-action@master 72 | with: 73 | github_token: ${{ secrets.GITHUB_TOKEN }} 74 | branch: gh-pages 75 | directory: dist 76 | -------------------------------------------------------------------------------- /include/bpstd/detail/nth_type.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * \file nth_type.hpp 3 | * 4 | * \brief This internal header provides the definition of the INVOKE overload 5 | *****************************************************************************/ 6 | 7 | /* 8 | The MIT License (MIT) 9 | 10 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | #ifndef BPSTD_DETAIL_NTH_TYPE_HPP 31 | #define BPSTD_DETAIL_NTH_TYPE_HPP 32 | 33 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) 34 | # pragma once 35 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 36 | 37 | #include // std::size_t 38 | 39 | namespace bpstd { 40 | namespace detail { 41 | 42 | /// \brief Gets the nth type from a variadic pack of arguments 43 | /// 44 | /// \tparam N the argument to retrieve 45 | /// \tparam Args the arguments to extract from 46 | template 47 | struct nth_type; 48 | 49 | template 50 | struct nth_type : nth_type{}; 51 | 52 | template 53 | struct nth_type<0,Arg0,Args...> 54 | { 55 | using type = Arg0; 56 | }; 57 | 58 | template 59 | using nth_type_t = typename nth_type::type; 60 | 61 | } // namespace detail 62 | } // namespace bpstd 63 | 64 | #endif /* BPSTD_DETAIL_NTH_TYPE_HPP */ 65 | -------------------------------------------------------------------------------- /test/src/bpstd/exception.test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | // MSVC 2015 seems to emit an error that __forceinline'd functions may not be 30 | // __forceinline'd at the *end of the translation unit* using it, for some 31 | // stupid reason. 32 | #if defined(_MSC_VER) 33 | # pragma warning(disable:4714) 34 | #endif 35 | 36 | namespace { 37 | template 38 | struct require_exception_in_dtor 39 | { 40 | ~require_exception_in_dtor() 41 | { 42 | REQUIRE(bpstd::uncaught_exceptions() == Count); 43 | } 44 | }; 45 | 46 | template 47 | struct require_nested_exception 48 | { 49 | ~require_nested_exception() 50 | { 51 | try { 52 | require_exception_in_dtor requirement{}; 53 | 54 | throw std::exception{}; 55 | } catch (...){} 56 | } 57 | }; 58 | } 59 | 60 | TEST_CASE("uncaught_exceptions()", "[utility]") 61 | { 62 | SECTION("No exceptions in flight") 63 | { 64 | REQUIRE(bpstd::uncaught_exceptions() == 0); 65 | } 66 | SECTION("One exception in flight") 67 | { 68 | try { 69 | require_exception_in_dtor<1> requirement{}; 70 | 71 | throw std::exception{}; 72 | } catch (...) {} 73 | } 74 | # if !defined(BPSTD_UNCAUGHT_EXCEPTIONS_EMULATED) 75 | SECTION("Two exceptions in flight") 76 | { 77 | try { 78 | require_nested_exception<2> requirement{}; 79 | 80 | throw std::exception{}; 81 | } catch (...) {} 82 | } 83 | # endif 84 | } 85 | -------------------------------------------------------------------------------- /doc/images/backport-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Backport 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /doc/installing.md: -------------------------------------------------------------------------------- 1 | # Installing 2 | 3 | **Backport** is a header-only library, which makes consuming this in outside 4 | project quite simple. The simple requirement is that the compiler have the 5 | header search-path be updated to contain the path to the `include` directory 6 | for this library. 7 | 8 | You can easily do this manually, if desired, by copying the `include` directory 9 | wherever you like into your project, `git submodule` this repository in, 10 | install it with your favorite package manager, etc. 11 | 12 | However, if you are using either [`conan`](#conan) or [`CMake`](#cmake) 13 | (or both), you can also follow the additional instructions below for simple 14 | integration: 15 | 16 | ## Conan 17 | 18 | This project provides a `conanfile.py` and public hosting on 19 | [bintray](https://bintray.com/bitwizeshift/public-conan/Backport%3Abackport) for packages. 20 | 21 | Just follow the instructions in the bintray link for setting up this 22 | source as a conan repository, and add 23 | `Backport/@backport/stable` as a dependency in your 24 | `conanfile.py`, and you can install this into your project. 25 | 26 | ## CMake 27 | 28 | This project is written with idiomatic & "modern" `CMake` (3.4+) and 29 | provides the target `Backport::Backport` which can be used as a dependency 30 | in your cmake build. 31 | 32 | You can either [add this project via `add_subdirectory`](#via-subdirectory) 33 | or [pull this project in with a `find_package`](#via-installation) 34 | call after installing it. 35 | 36 | ### Via subdirectory 37 | 38 | If you have added this repo as a `git submodule`, or as a subtree, 39 | or just straight-up copied directly into your repo, you can add this 40 | project via `add_subdirectory` call before your target so that you can 41 | use the `Backport::Backport` target. 42 | 43 | For example: 44 | 45 | ```cmake 46 | # Add the 'Backport' repo sometime before you depend on the target 47 | add_subdirectory("external/Backport") 48 | 49 | # ... 50 | 51 | add_library(MyLibrary ...) 52 | target_link_libraries(MyLibrary 53 | PRIVATE Backport::Backport # 'PRIVATE" assuming private dependency... 54 | ) 55 | ``` 56 | 57 | And in your implementation of `MyLibrary`, you can easily include 58 | files from the project (e.g. `#include `) 59 | 60 | ### Via installation 61 | 62 | You can also create an installation package of **Backport** and 63 | share with other users, or just use locally on your system. 64 | 65 | Then, to consume this package you just need to find it with 66 | `find_package`. For example: 67 | 68 | ```cmake 69 | find_package(Backport REQUIRED) 70 | 71 | # ... 72 | 73 | add_library(MyLibrary ...) 74 | target_link_libraries(MyLibrary 75 | PRIVATE Backport::Backport # 'PRIVATE" assuming private dependency... 76 | ) 77 | ``` 78 | 79 | And in your implementation of `MyLibrary`, you can easily include 80 | files from the project (e.g. `#include `) 81 | -------------------------------------------------------------------------------- /include/bpstd/detail/enable_overload.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// \file enable_overload.hpp 3 | /// 4 | /// \brief This internal header provides the definition of a SFINAE utility 5 | /// for conditionally enabling overloads 6 | //////////////////////////////////////////////////////////////////////////////// 7 | 8 | /* 9 | The MIT License (MIT) 10 | 11 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in 21 | all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | SOFTWARE. 30 | */ 31 | #ifndef BPSTD_DETAIL_ENABLE_OVERLOAD_HPP 32 | #define BPSTD_DETAIL_ENABLE_OVERLOAD_HPP 33 | 34 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) 35 | # pragma once 36 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 37 | 38 | namespace bpstd { 39 | namespace detail { 40 | 41 | /// \brief Similar to enable_if, but doesn't sfinae-away a type; instead 42 | /// produces an uninstantiable unique type when true 43 | /// 44 | /// This is used to selectively disable constructors, since sfinae doesn't 45 | /// work for copy/move constructors 46 | template 47 | struct enable_overload_if 48 | { 49 | using type = T; 50 | }; 51 | 52 | template 53 | struct enable_overload_if 54 | { 55 | class type{ type() = delete; ~type() = delete; }; 56 | }; 57 | 58 | template 59 | using enable_overload_if_t = typename enable_overload_if::type; 60 | 61 | /// \brief Inverse of enable_overload_if 62 | template 63 | using disable_overload_if = enable_overload_if; 64 | 65 | /// \brief Convenience alias to retrieve the ::type member of 66 | /// disable_overload_if 67 | template 68 | using disable_overload_if_t = typename disable_overload_if::type; 69 | 70 | } // namespace detail 71 | } // namespace bpstd 72 | 73 | #endif /* BPSTD_DETAIL_ENABLE_OVERLOAD_HPP */ 74 | -------------------------------------------------------------------------------- /include/bpstd/string.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// \file string.hpp 3 | /// 4 | /// \brief This header provides definitions from the C++ header 5 | //////////////////////////////////////////////////////////////////////////////// 6 | 7 | /* 8 | The MIT License (MIT) 9 | 10 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | #ifndef BPSTD_STRING_HPP 31 | #define BPSTD_STRING_HPP 32 | 33 | #include "detail/config.hpp" 34 | 35 | #include 36 | 37 | BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 38 | 39 | namespace bpstd { 40 | 41 | inline namespace literals { 42 | inline namespace string_literals { 43 | 44 | std::string operator""_s(const char* s, std::size_t len); 45 | std::u16string operator""_s(const char16_t* s, std::size_t len); 46 | std::u32string operator""_s(const char32_t* s, std::size_t len); 47 | std::wstring operator""_s(const wchar_t* s, std::size_t len); 48 | 49 | } // inline namespace string_literals 50 | } // inline namespace literals 51 | 52 | } // namespace bpstd 53 | 54 | inline BPSTD_INLINE_VISIBILITY 55 | std::string 56 | bpstd::literals::string_literals::operator""_s(const char* s, std::size_t len) 57 | { 58 | return std::string{s, len}; 59 | } 60 | 61 | inline BPSTD_INLINE_VISIBILITY 62 | std::u16string 63 | bpstd::literals::string_literals::operator""_s(const char16_t* s, std::size_t len) 64 | { 65 | return std::u16string{s, len}; 66 | } 67 | 68 | inline BPSTD_INLINE_VISIBILITY 69 | std::u32string 70 | bpstd::literals::string_literals::operator""_s(const char32_t* s, std::size_t len) 71 | { 72 | return std::u32string{s, len}; 73 | } 74 | 75 | inline BPSTD_INLINE_VISIBILITY 76 | std::wstring 77 | bpstd::literals::string_literals::operator""_s(const wchar_t* s, std::size_t len) 78 | { 79 | return std::wstring{s, len}; 80 | } 81 | 82 | BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 83 | 84 | #endif /* BPSTD_STRING_HPP */ 85 | -------------------------------------------------------------------------------- /test/src/bpstd/complex.test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | 29 | // MSVC 2015 seems to emit an error that __forceinline'd functions may not be 30 | // __forceinline'd at the *end of the translation unit* using it, for some 31 | // stupid reason. 32 | #if defined(_MSC_VER) 33 | # pragma warning(disable:4714) 34 | #endif 35 | 36 | TEST_CASE("operator\"\"_il(long double)", "[literal]") 37 | { 38 | using bpstd::literals::complex_literals::operator""_il; 39 | 40 | SECTION("Constructs underlying complex from literal") 41 | { 42 | REQUIRE(4.0_il == bpstd::complex{0, 4.0}); 43 | } 44 | } 45 | 46 | TEST_CASE("operator\"\"_il(unsigned long long)", "[literal]") 47 | { 48 | using bpstd::literals::complex_literals::operator""_il; 49 | 50 | SECTION("Constructs underlying complex from literal") 51 | { 52 | REQUIRE(42_il == bpstd::complex{0, 42}); 53 | } 54 | } 55 | 56 | TEST_CASE("operator\"\"_i(long double)", "[literal]") 57 | { 58 | using bpstd::literals::complex_literals::operator""_i; 59 | 60 | SECTION("Constructs underlying complex from literal") 61 | { 62 | REQUIRE(4.0_i == bpstd::complex{0, 4.0}); 63 | } 64 | } 65 | 66 | TEST_CASE("operator\"\"_i(unsigned long long)", "[literal]") 67 | { 68 | using bpstd::literals::complex_literals::operator""_i; 69 | 70 | SECTION("Constructs underlying complex from literal") 71 | { 72 | REQUIRE(42_i == bpstd::complex{0, 42}); 73 | } 74 | } 75 | 76 | TEST_CASE("operator\"\"_if(long double)", "[literal]") 77 | { 78 | using bpstd::literals::complex_literals::operator""_if; 79 | 80 | SECTION("Constructs underlying complex from literal") 81 | { 82 | REQUIRE(4.0_if == bpstd::complex{0, 4.0f}); 83 | } 84 | } 85 | 86 | TEST_CASE("operator\"\"_if(unsigned long long)", "[literal]") 87 | { 88 | using bpstd::literals::complex_literals::operator""_if; 89 | 90 | SECTION("Constructs underlying complex from literal") 91 | { 92 | REQUIRE(42_if == bpstd::complex{0, 42}); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /test/src/bpstd/memory.test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | // MSVC 2015 seems to emit an error that __forceinline'd functions may not be 31 | // __forceinline'd at the *end of the translation unit* using it, for some 32 | // stupid reason. 33 | #if defined(_MSC_VER) 34 | # pragma warning(disable:4714) 35 | #endif 36 | 37 | //------------------------------------------------------------------------------ 38 | // make_unique 39 | //------------------------------------------------------------------------------ 40 | 41 | TEST_CASE("make_unique(...)", "[memory]") 42 | { 43 | auto p = bpstd::make_unique(42); 44 | 45 | SECTION("Pointer is not null") 46 | { 47 | REQUIRE( p != nullptr ); 48 | } 49 | } 50 | 51 | TEST_CASE("make_unique(...)", "[memory]") 52 | { 53 | auto p = bpstd::make_unique(5u); 54 | 55 | SECTION("Pointer is not null") 56 | { 57 | REQUIRE( p != nullptr ); 58 | } 59 | } 60 | 61 | //------------------------------------------------------------------------------ 62 | // make_unique_for_overwrite 63 | //------------------------------------------------------------------------------ 64 | 65 | TEST_CASE("make_unique_for_overwrite(...)", "[memory]") 66 | { 67 | auto p = bpstd::make_unique_for_overwrite(); 68 | 69 | SECTION("Pointer is not null") 70 | { 71 | REQUIRE( p != nullptr ); 72 | } 73 | } 74 | 75 | TEST_CASE("make_unique_for_overwrite(...)", "[memory]") 76 | { 77 | auto p = bpstd::make_unique_for_overwrite(42); 78 | 79 | SECTION("Pointer is not null") 80 | { 81 | REQUIRE( p != nullptr ); 82 | } 83 | } 84 | 85 | //------------------------------------------------------------------------------ 86 | // to_address 87 | //------------------------------------------------------------------------------ 88 | 89 | TEST_CASE("to_address(...)", "[memory]") 90 | { 91 | auto vec = std::vector{{1,2,3,4}}; 92 | 93 | auto* p = bpstd::to_address(vec.begin()); 94 | 95 | SECTION("Pointer points to start of range") 96 | { 97 | REQUIRE( p == vec.data() ); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at [INSERT EMAIL ADDRESS]. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | -------------------------------------------------------------------------------- /doc/commit-standards.md: -------------------------------------------------------------------------------- 1 | # Commit Standards 2 | 3 | The **Backport** project has some some requirements on how git commit 4 | messages are formed. 5 | 6 | **General:** 7 | 8 | * Commits should be small, granular, and easy to follow and revert. Ideally, 9 | the same SoC practices that would be applied to software development should 10 | be applied to commits; each commit identifies a separtion of concerns. 11 | 12 | **Commit titles:** 13 | 14 | * must be in imperitive, present-tense 15 | 16 | * must be no longer than 50 characters 17 | 18 | * must be prefixed by an [emoji key](#emoji-key) to indicate what the change 19 | is, followed by a space 20 | 21 | * If a commit may use more than one emoji to identify the change, it might 22 | indicate that the change is _not granular enough_, and you may be a 23 | candidate to be broken down into smaller commits for easier consumption 24 | 25 | **Commit messages:** 26 | 27 | * Must not exceed 72-character wide 28 | 29 | * Exceptions are made if a message contains a link or other figure that 30 | exceeds the 72 character rule by nature (e.g. code, compile message, etc) 31 | 32 | * Must indicate the rationale for the change, what was changed, and why 33 | 34 | * In general, more details are always better to help identify the cause of 35 | changes in a repository 36 | 37 | ## Emoji Key 38 | 39 | Emojis are used to prefix commit titles in order to simplify categorization 40 | of git log messages. 41 | 42 | Use the table below to identify which prefixes should be used for the 43 | respective change: 44 | 45 | | Emoji | Reason | 46 | |---|-------------------------------------------------------------------------| 47 | | 🔖 | Version Tag | 48 | | 📖 | Documentation / Textual Changes | 49 | | 📇 | Metadata (README, LICENSE, repo docs, etc) | 50 | | 🚦 | Continuous Integration | 51 | | ✨ | New Feature | 52 | | ✏ | Rename | 53 | | 🔨 | Refactor | 54 | | ⚠ | Deprecation | 55 | | 🗑️ | Removal | 56 | | 🎨 | Cosmetic | 57 | | 🩹 | Bug fix | 58 | | 🧹 | Code Cleanup (includes moving types/files around) | 59 | | ⏱ | Tuning / Performance | 60 | | 🎯 | Testing (unit, benchmark, integration, etc) | 61 | | 🔧 | Tooling | 62 | | 🔐 | Security | 63 | | ♿ | Accessibility | 64 | | 🌐 | Localization / Internationalization | 65 | | 🚧 | WIP | 66 | 67 | **Note:** This list may be incomplete, and not cover all possible areas that 68 | would be needed. Please feel free to start a discussion if new tags would be 69 | more appropriate. Similarly, if there are more appropriate emojis to use as 70 | tags, feel free to provide suggestions! -------------------------------------------------------------------------------- /cmake/AddSelfContainmentTest.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | #.rst: 4 | # AddelfContainmentTest 5 | # --------- 6 | # 7 | # Creates a C or C++ library that includes each specified header file 8 | # independently to ensure that each header carries no expected ordering. 9 | # 10 | # This is used to avoid accidental dependencies based on the order of 11 | # inclusion. 12 | # 13 | # :: 14 | # 15 | # add_self_containment_test( 16 | # 17 | # TARGET 18 | # [EXTENSION ext] 19 | # HEADERS [headers]... 20 | # ) 21 | # 22 | # - The name of the target to create 23 | # [C|CXX] - The language check. By default, this is CXX 24 | # [headers]... - List of headers to compile 25 | # 26 | function(add_self_containment_test name) 27 | 28 | ############################### Setup output ############################### 29 | 30 | cmake_parse_arguments("CONTAINMENT" "" "TARGET;EXTENSION;DESTINATION" "HEADERS" ${ARGN}) 31 | 32 | if( TARGET "${name}" ) 33 | message(FATAL_ERROR "Specified target name already exists as a valid CMake target.") 34 | endif() 35 | 36 | if( CONTAINMENT_HEADERS ) 37 | set(header_files ${CONTAINMENT_HEADERS}) 38 | else() 39 | message(FATAL_ERROR "No HEADERS specified") 40 | endif() 41 | 42 | if( CONTAINMENT_EXTENSION ) 43 | set(extension "${CONTAINMENT_EXTENSION}" ) 44 | else() 45 | set(extension "cpp") 46 | endif() 47 | 48 | if( CONTAINMENT_DESTINATION ) 49 | set(output_dir "${CONTAINMENT_DESTINATION}") 50 | else() 51 | set(output_dir "${CMAKE_CURRENT_BINARY_DIR}/${name}") 52 | endif() 53 | 54 | if( NOT "${CONTAINMENT_TARGET}" STREQUAL "" AND TARGET "${CONTAINMENT_TARGET}") 55 | set(target "${CONTAINMENT_TARGET}") 56 | elseif( NOT TARGET "${CONTAINMENT_TARGET}" ) 57 | message(FATAL_ERROR "Specified TARGET is not a valid CMake target") 58 | elseif( "${CONTAINMENT_TARGET}" NOT STREQUAL "" ) 59 | message(FATAL_ERROR "TARGET not specified") 60 | endif() 61 | 62 | ############################### Create files ############################### 63 | 64 | set(source_files) 65 | foreach( header ${header_files} ) 66 | 67 | get_filename_component(path_segment "${header}" PATH) 68 | get_filename_component(absolute_header "${header}" ABSOLUTE) 69 | file(RELATIVE_PATH relative_header "${output_dir}/${path_segment}" "${absolute_header}") 70 | 71 | set(output_path "${output_dir}/${header}.${extension}") 72 | 73 | if( NOT EXISTS "${output_path}" OR "${absolute_header}" IS_NEWER_THAN "${output_path}" ) 74 | 75 | file(WRITE "${output_path}" "#include \"${relative_header}\" // IWYU pragma: keep\n") 76 | 77 | endif() 78 | 79 | set_property( DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${output_path}") 80 | set_property( DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${output_path}") 81 | 82 | list(APPEND source_files "${output_path}") 83 | 84 | endforeach() 85 | 86 | ###################### Create self-containment Target ###################### 87 | 88 | add_library("${name}" OBJECT 89 | ${source_files} 90 | ${header_files} 91 | ) 92 | 93 | # Iterate over the various CMake target properties, and propagate them 94 | # manually 95 | set(properties 96 | INCLUDE_DIRECTORIES 97 | SYSTEM_INCLUDE_DIRECTORIES 98 | LINK_LIBRARIES 99 | COMPILE_OPTIONS 100 | COMPILE_FEATURES 101 | COMPILE_DEFINITIONS 102 | ) 103 | 104 | # Append each property as a generator-expression 105 | foreach( property ${properties} ) 106 | set_property( 107 | TARGET "${name}" 108 | APPEND PROPERTY "${property}" 109 | "$" 110 | ) 111 | endforeach() 112 | 113 | endfunction() 114 | -------------------------------------------------------------------------------- /cmake/SourceGroup.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) Matthew Rodusek 2 | # Distributed under the OSI-approved MIT License. See accompanying 3 | # file LICENSE.txt or https://opensource.org/licenses/MIT for details. 4 | 5 | #.rst: 6 | # SourceGroup 7 | # ----------- 8 | # 9 | # This module defines additional source_group functionality that is 10 | # compatible with older versions of CMake 11 | 12 | if (CMAKE_VERSION VERSION_LESS 3.5.0) 13 | include(CMakeParseArguments) 14 | endif () 15 | 16 | #.rst 17 | # .. command:: source_group_tree 18 | # 19 | # This command defines a grouping for source files in IDE project 20 | # generation. 21 | # 22 | # This function is not supported in CMake 3.7 or before, and is 23 | # added here for compatibility. 24 | # 25 | # If this is executed in CMake 3.8 or later, it defaults to 26 | # source_group(TREE ...) instead to preserve functionality. 27 | # 28 | # .. code-block:: cmake 29 | # 30 | # source_group_tree( [PREFIX ] [FILES ]) 31 | # 32 | # Creates groups recursively based on the specified ```` 33 | # along with their relative paths to the given source files. 34 | # 35 | # The options are: 36 | # 37 | # ``PREFIX`` 38 | # Source group and files located directly in path, will 39 | # be placed in source groups. 40 | # 41 | # ``FILES`` 42 | # Any source file specified explicitly will be placed in group 43 | # made up of the relative path between ```` and the file. 44 | # Relative paths are interpreted with respect to the 45 | # current source directory. 46 | # It is an error if any ```` is not prefixed by ```` 47 | function(source_group_tree root) 48 | 49 | cmake_parse_arguments( 50 | SOURCE_GROUP_TREE # Prefix 51 | "" # Option args 52 | PREFIX # Single args 53 | FILES # Multi args 54 | ${ARGN} 55 | ) 56 | 57 | if (SOURCE_GROUP_TREE_UNPARSED_ARGUMENTS) 58 | message(FATAL_ERROR "source_group: Unknown arguments specified: ${SOURCE_GROUP_TREE_UNPARSED_ARGUMENTS}") 59 | endif () 60 | 61 | if (IS_ABSOLUTE "${root}") 62 | set(root_path "${root}") 63 | else () 64 | set(root_path "${CMAKE_CURRENT_SOURCE_DIR}/${root}") 65 | get_filename_component(root_path "${root_path}" ABSOLUTE) 66 | endif () 67 | 68 | # source_group(TREE ...) introduced in 3.8 69 | if (CMAKE_VERSION VERSION_GREATER 3.8) 70 | set(args) 71 | if (SOURCE_GROUP_TREE_PREFIX) 72 | set(args PREFIX "${SOURCE_GROUP_TREE_PREFIX}" ${args}) 73 | endif () 74 | if (SOURCE_GROUP_TREE_FILES) 75 | set(args FILES "${SOURCE_GROUP_TREE_FILES}" ${args}) 76 | endif () 77 | source_group( TREE "${root_path}" ${args} ) 78 | else () 79 | foreach (file IN LISTS SOURCE_GROUP_TREE_FILES) 80 | if (SOURCE_GROUP_TREE_PREFIX) 81 | set(group "${SOURCE_GROUP_TREE_PREFIX}") 82 | else () 83 | set(group) 84 | endif () 85 | 86 | if (IS_ABSOLUTE "${file}") 87 | set(absolute_file "${file}") 88 | else () 89 | # All relative paths should be relative to the source directory 90 | set(absolute_file "${CMAKE_CURRENT_SOURCE_DIR}/${file}") 91 | get_filename_component(absolute_file "${absolute_file}" ABSOLUTE) 92 | endif () 93 | 94 | file(RELATIVE_PATH group_suffix "${root_path}" "${absolute_file}") 95 | if (group_suffix MATCHES "(\\.\\.).*") 96 | message(FATAL_ERROR "source_group ROOT: ${root_path} is not a prefix of file ${absolute_file}") 97 | endif () 98 | get_filename_component(group_suffix "${group_suffix}" DIRECTORY) 99 | string(REPLACE "/" "\\" group_suffix "${group_suffix}") 100 | 101 | if (group AND group_suffix) 102 | set(group "${SOURCE_GROUP_TREE_PREFIX}\\${group_suffix}") 103 | elseif (group_suffix) 104 | set(group "${group_suffix}") 105 | endif () 106 | source_group("${group}" FILES "${absolute_file}") 107 | endforeach () 108 | endif () 109 | endfunction() 110 | -------------------------------------------------------------------------------- /include/bpstd/detail/move.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// \file move.hpp 3 | /// 4 | /// \brief This internal header provides the definition of the move and forward 5 | //////////////////////////////////////////////////////////////////////////////// 6 | 7 | /* 8 | The MIT License (MIT) 9 | 10 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | #ifndef BPSTD_DETAIL_MOVE_HPP 31 | #define BPSTD_DETAIL_MOVE_HPP 32 | 33 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) 34 | # pragma once 35 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 36 | 37 | #include "config.hpp" 38 | 39 | #include 40 | 41 | BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 42 | 43 | namespace bpstd { 44 | 45 | //---------------------------------------------------------------------------- 46 | // Utilities 47 | //---------------------------------------------------------------------------- 48 | 49 | /// \{ 50 | /// \brief Forwards a reference \p t 51 | /// 52 | /// \tparam T the type to forward 53 | /// \param t the reference 54 | /// \return the forwarded reference 55 | template 56 | constexpr T&& forward(typename std::remove_reference::type& t) noexcept; 57 | template 58 | constexpr T&& forward(typename std::remove_reference::type&& t) noexcept; 59 | /// \} 60 | 61 | /// \brief Casts \p x to an rvalue 62 | /// 63 | /// \param x the parameter to move 64 | /// \return rvalue reference to \p x 65 | template 66 | constexpr T&& move(T& x) noexcept; 67 | 68 | /// \brief Casts \p x to an rvalue 69 | /// 70 | /// \param x the parameter to move 71 | /// \return rvalue reference to \p x 72 | template 73 | constexpr typename std::remove_reference::type&& move(T&& x) noexcept; 74 | 75 | } // namespace bpstd 76 | 77 | //------------------------------------------------------------------------------ 78 | // Utilities 79 | //------------------------------------------------------------------------------ 80 | 81 | template 82 | inline BPSTD_INLINE_VISIBILITY constexpr 83 | T&& bpstd::forward(typename std::remove_reference::type& t) 84 | noexcept 85 | { 86 | return static_cast(t); 87 | } 88 | 89 | template 90 | inline BPSTD_INLINE_VISIBILITY constexpr 91 | T&& bpstd::forward(typename std::remove_reference::type&& t) 92 | noexcept 93 | { 94 | return static_cast(t); 95 | } 96 | 97 | template 98 | inline BPSTD_INLINE_VISIBILITY constexpr 99 | T&& bpstd::move(T& x) 100 | noexcept 101 | { 102 | return static_cast(x); 103 | } 104 | 105 | template 106 | inline BPSTD_INLINE_VISIBILITY constexpr 107 | typename std::remove_reference::type&& bpstd::move(T&& x) 108 | noexcept 109 | { 110 | return static_cast(x); 111 | } 112 | 113 | BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 114 | 115 | #endif /* BPSTD_DETAIL_MOVE_HPP */ 116 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: "Code Coverage" 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'include/**.hpp' 7 | - 'test/**.cpp' 8 | - '**.cmake' 9 | - 'conanfile.py' 10 | - 'CMakeLists.txt' 11 | - 'test/CMakeLists.txt' 12 | - '.github/workflows/coverage.yml' 13 | pull_request: 14 | paths: 15 | - 'include/**.hpp' 16 | - 'test/**.cpp' 17 | - '**.cmake' 18 | - 'conanfile.py' 19 | - 'CMakeLists.txt' 20 | - 'test/CMakeLists.txt' 21 | - '.github/workflows/coverage.yml' 22 | 23 | jobs: 24 | coverage: 25 | name: Ubuntu ${{matrix.compiler.cc}} Coverage 26 | runs-on: ubuntu-20.04 27 | 28 | env: 29 | build-directory: build 30 | 31 | strategy: 32 | matrix: 33 | compiler: 34 | - { cc: gcc, cxx: g++, version: "10" } 35 | - { cc: clang, cxx: clang++, version: "10" } 36 | 37 | steps: 38 | - name: Checkout repository 39 | uses: actions/checkout@v2 40 | 41 | - name: Set up Python 42 | uses: actions/setup-python@v1 43 | with: 44 | python-version: 3.7 45 | 46 | - name: Prepare Environment 47 | run: | 48 | sudo apt-get install -y ${{matrix.compiler.cxx}}-${{matrix.compiler.version}} 49 | if [["${{matrix.compiler.cc}}" = "clang"]]; then 50 | sudo apt-get install -y llvm-${{matrix.compiler.version}} 51 | fi 52 | sudo apt-get install lcov 53 | python -m pip install --upgrade pip 54 | pip install conan 55 | cmake -E make_directory ${{env.build-directory}} 56 | cmake -E chdir ${{env.build-directory}} conan install .. 57 | 58 | - name: Configure 59 | working-directory: ${{env.build-directory}} 60 | env: 61 | CC: ${{matrix.compiler.cc}}-${{matrix.compiler.version}} 62 | CXX: ${{matrix.compiler.cxx}}-${{matrix.compiler.version}} 63 | run: | 64 | cmake .. -DCMAKE_BUILD_TYPE=Debug \ 65 | -DBACKPORT_COMPILE_UNIT_TESTS=On \ 66 | -DCMAKE_CXX_FLAGS="--coverage -DBPSTD_INLINE_VISIBILITY=" \ 67 | 68 | - name: Build 69 | working-directory: ${{env.build-directory}} 70 | run: cmake --build . 71 | 72 | - name: Test 73 | working-directory: ${{env.build-directory}} 74 | run: ctest --output-on-failure 75 | 76 | - name: Process Coverage Data 77 | working-directory: ${{env.build-directory}} 78 | run: | 79 | # Create a script for which gcov to use (needed for lcov) 80 | echo "#!/bin/bash" > gcov-executable.sh 81 | if [[ "${{matrix.compiler.cc}}" =~ "gcc" ]]; then 82 | echo 'gcov $@' >> gcov-executable.sh 83 | else 84 | echo 'llvm-cov-${{matrix.compiler.version}} gcov $@' >> gcov-executable.sh 85 | fi 86 | chmod +x gcov-executable.sh 87 | ./gcov-executable.sh $(find $(pwd) -name '*.o' -type f) 88 | 89 | # Generate coverage information 90 | lcov --capture \ 91 | --gcov-tool $(pwd)/gcov-executable.sh \ 92 | --directory . \ 93 | --output-file coverage_unfiltered.info 94 | 95 | # Strip symbols from 'test' directory 96 | lcov --remove coverage_unfiltered.info -o coverage.info \ 97 | --gcov-tool $(pwd)/gcov-executable.sh \ 98 | "$(cd ..; pwd)/test/*" \ 99 | "${HOME}/.conan/*" \ 100 | "/usr/*" \ 101 | 102 | - name: Generate Coverage 103 | uses: coverallsapp/github-action@v1.1.2 104 | with: 105 | github-token: ${{secrets.GITHUB_TOKEN}} 106 | path-to-lcov: ${{env.build-directory}}/coverage.info 107 | -------------------------------------------------------------------------------- /include/bpstd/detail/config.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// \file config.hpp 3 | /// 4 | /// \brief This header provides configuration data for the bpstd library 5 | //////////////////////////////////////////////////////////////////////////////// 6 | 7 | /* 8 | The MIT License (MIT) 9 | 10 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | #ifndef BPSTD_DETAIL_CONFIG_HPP 31 | #define BPSTD_DETAIL_CONFIG_HPP 32 | 33 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) 34 | # pragma once 35 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 36 | 37 | #if !defined(__cplusplus) 38 | # error This library requires a C++ compiler 39 | #endif 40 | 41 | // _MSC_VER check is due to MSVC not defining __cplusplus to be 201103L 42 | #if !defined(_MSC_VER) && __cplusplus < 201103L 43 | # error This library must be compiled with C++11 support 44 | #endif 45 | 46 | #if defined(__cplusplus) && __cplusplus >= 201402L 47 | # define BPSTD_CPP14_CONSTEXPR constexpr 48 | # define BPSTD_HAS_TEMPLATE_VARIABLES 1 49 | #else 50 | # define BPSTD_CPP14_CONSTEXPR 51 | # define BPSTD_HAS_TEMPLATE_VARIABLES 0 52 | #endif 53 | 54 | #if defined(__cplusplus) && __cplusplus >= 201703L 55 | # define BPSTD_CPP17_CONSTEXPR constexpr 56 | # define BPSTD_CPP17_INLINE inline 57 | # define BPSTD_HAS_INLINE_VARIABLES 1 58 | #else 59 | # define BPSTD_CPP17_CONSTEXPR 60 | # define BPSTD_CPP17_INLINE 61 | # define BPSTD_HAS_INLINE_VARIABLES 0 62 | #endif 63 | 64 | #define BPSTD_UNUSED(x) static_cast(x) 65 | 66 | // Use __may_alias__ attribute on gcc and clang 67 | #if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 5) 68 | # define BPSTD_MAY_ALIAS __attribute__((__may_alias__)) 69 | #else // defined(__clang__) || defined __GNUC__ 70 | # define BPSTD_MAY_ALIAS 71 | #endif // defined __clang__ || defined __GNUC__ 72 | 73 | #if !defined(BPSTD_INLINE_VISIBILITY) 74 | // When using 'clang-cl', don't forceinline -- since it results in code generation 75 | // failures in 'variant' 76 | # if defined(__clang__) && defined(_MSC_VER) 77 | # define BPSTD_INLINE_VISIBILITY __attribute__((visibility("hidden"), no_instrument_function)) 78 | # elif defined(__clang__) || defined(__GNUC__) 79 | # define BPSTD_INLINE_VISIBILITY __attribute__((visibility("hidden"), always_inline, no_instrument_function)) 80 | # elif defined(_MSC_VER) 81 | # define BPSTD_INLINE_VISIBILITY __forceinline 82 | # else 83 | # define BPSTD_INLINE_VISIBILITY 84 | # endif 85 | #endif // !defined(BPSTD_INLINE_VISIBILITY) 86 | 87 | #if defined(_MSC_VER) 88 | # define BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE \ 89 | __pragma(warning(push)) \ 90 | __pragma(warning(disable:4714)) \ 91 | __pragma(warning(disable:4100)) 92 | #else 93 | # define BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 94 | #endif 95 | 96 | #if defined(_MSC_VER) 97 | # define BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE \ 98 | __pragma(warning(pop)) 99 | #else 100 | # define BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 101 | #endif 102 | 103 | #endif /* BPSTD_DETAIL_CONFIG_HPP */ 104 | -------------------------------------------------------------------------------- /include/bpstd/detail/variant_traits.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * \file variant_traits.hpp 3 | * 4 | * \brief This internal header provides forward declarations of various 5 | * variant traits 6 | *****************************************************************************/ 7 | 8 | /* 9 | The MIT License (MIT) 10 | 11 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in 21 | all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | SOFTWARE. 30 | */ 31 | #ifndef BPSTD_DETAIL_VARIANT_TRAITS_HPP 32 | #define BPSTD_DETAIL_VARIANT_TRAITS_HPP 33 | 34 | #include "config.hpp" 35 | #include "variant_fwds.hpp" 36 | #include "invoke.hpp" // invoke_result 37 | 38 | BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 39 | 40 | namespace bpstd { 41 | namespace detail { 42 | 43 | template 44 | struct variant_first_type; 45 | 46 | template 47 | struct variant_first_type> 48 | { 49 | using type = Type0; 50 | }; 51 | 52 | template 53 | struct variant_first_type> 54 | { 55 | using type = Type0; 56 | }; 57 | 58 | template 59 | struct variant_first_type> 60 | { 61 | using type = Type0; 62 | }; 63 | 64 | template 65 | struct variant_first_type 66 | { 67 | using type = typename variant_first_type::type&; 68 | }; 69 | 70 | template 71 | struct variant_first_type 72 | { 73 | using type = typename variant_first_type::type&&; 74 | }; 75 | 76 | template 77 | struct variant_first_type 78 | { 79 | using type = const typename variant_first_type::type; 80 | }; 81 | 82 | template 83 | struct variant_first_type 84 | { 85 | using type = const typename variant_first_type::type&; 86 | }; 87 | 88 | template 89 | struct variant_first_type 90 | { 91 | using type = const typename variant_first_type::type&&; 92 | }; 93 | 94 | template 95 | using variant_first_type_t = typename variant_first_type::type; 96 | 97 | //-------------------------------------------------------------------------- 98 | 99 | template 100 | struct variant_visitor_invoke_result 101 | : invoke_result...>{}; 102 | 103 | template 104 | using variant_visitor_invoke_result_t 105 | = typename variant_visitor_invoke_result::type; 106 | 107 | } // namespace detail 108 | } // namespace bpstd 109 | 110 | BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 111 | 112 | #endif /* BPSTD_DETAIL_VARIANT_TRAITS_HPP */ 113 | -------------------------------------------------------------------------------- /.github/workflows/build-macos.yml: -------------------------------------------------------------------------------- 1 | name: macOS 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'include/**.hpp' 7 | - 'test/**.cpp' 8 | - '**.cmake' 9 | - 'conanfile.py' 10 | - 'CMakeLists.txt' 11 | - 'test/CMakeLists.txt' 12 | - '.github/workflows/build-macos.yml' 13 | pull_request: 14 | paths: 15 | - 'include/**.hpp' 16 | - 'test/**.cpp' 17 | - '**.cmake' 18 | - 'conanfile.py' 19 | - 'CMakeLists.txt' 20 | - 'test/CMakeLists.txt' 21 | - '.github/workflows/build-macos.yml' 22 | 23 | jobs: 24 | test: 25 | name: macOS Xcode ${{matrix.compiler.version}} 26 | runs-on: macos-latest 27 | 28 | env: 29 | build-directory: build 30 | 31 | strategy: 32 | fail-fast: false 33 | matrix: 34 | compiler: 35 | # Xcode Versions 36 | - { name: "xcode", version: "10.3" } 37 | - { name: "xcode", version: "11.2" } 38 | - { name: "xcode", version: "11.3" } 39 | - { name: "xcode", version: "12.3" } 40 | 41 | steps: 42 | - name: Clone 43 | uses: actions/checkout@v2 44 | 45 | - name: Set up Python 46 | uses: actions/setup-python@v1 47 | with: 48 | python-version: 3.7 49 | 50 | - name: Prepare Environment 51 | run: | 52 | ls -ls /Applications/ 53 | sudo xcode-select -switch /Applications/Xcode_${{ matrix.compiler.version }}.app 54 | 55 | python -m pip install --upgrade pip 56 | pip install conan 57 | cmake -E make_directory ${{env.build-directory}} 58 | cmake -E chdir ${{env.build-directory}} conan install .. 59 | 60 | # Debug Configuration 61 | 62 | - name: Configure (Debug) 63 | working-directory: ${{env.build-directory}} 64 | env: 65 | CC: clang 66 | CXX: clang++ 67 | run: cmake .. -DCMAKE_BUILD_TYPE=Debug -DBACKPORT_COMPILE_UNIT_TESTS=On 68 | 69 | - name: Build (Debug) 70 | working-directory: ${{env.build-directory}} 71 | run: cmake --build . 72 | 73 | - name: Test (Debug) 74 | working-directory: ${{env.build-directory}} 75 | run: ctest --output-on-failure 76 | 77 | # Release Configuration 78 | 79 | - name: Configure (Release) 80 | working-directory: ${{env.build-directory}} 81 | run: cmake .. -DCMAKE_BUILD_TYPE=Release 82 | 83 | - name: Build (Release) 84 | working-directory: ${{env.build-directory}} 85 | run: cmake --build . 86 | 87 | - name: Test (Release) 88 | working-directory: ${{env.build-directory}} 89 | run: ctest --output-on-failure 90 | 91 | sanitize: 92 | name: macOS Xcode ${{matrix.compiler.version}} '${{matrix.sanitizer}}' sanitizer 93 | runs-on: macos-latest 94 | needs: test 95 | 96 | env: 97 | build-directory: build 98 | 99 | strategy: 100 | matrix: 101 | sanitizer: [address, undefined] 102 | 103 | steps: 104 | - name: Clone 105 | uses: actions/checkout@v2 106 | 107 | - name: Set up Python 108 | uses: actions/setup-python@v1 109 | with: 110 | python-version: 3.7 111 | 112 | - name: Prepare Environment 113 | run: | 114 | python -m pip install --upgrade pip 115 | pip install conan 116 | cmake -E make_directory ${{env.build-directory}} 117 | cmake -E chdir ${{env.build-directory}} conan install .. 118 | 119 | - name: Configure 120 | working-directory: ${{env.build-directory}} 121 | env: 122 | CC: clang 123 | CXX: clang++ 124 | run: | 125 | cmake .. \ 126 | -DCMAKE_BUILD_TYPE=Debug \ 127 | -DBACKPORT_COMPILE_UNIT_TESTS=On \ 128 | -DCMAKE_CXX_FLAGS="-fsanitize=${{matrix.sanitizer}}" 129 | 130 | - name: Build 131 | working-directory: ${{env.build-directory}} 132 | run: cmake --build . 133 | 134 | - name: Test (Sanitize) 135 | working-directory: ${{env.build-directory}} 136 | run: ctest --output-on-failure 137 | -------------------------------------------------------------------------------- /test/src/bpstd/utility.test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | 29 | // MSVC 2015 seems to emit an error that __forceinline'd functions may not be 30 | // __forceinline'd at the *end of the translation unit* using it, for some 31 | // stupid reason. 32 | #if defined(_MSC_VER) 33 | # pragma warning(disable:4714) 34 | #endif 35 | 36 | TEST_CASE("get(pair&)", "[utility]") 37 | { 38 | auto sut = bpstd::pair{1,3.14f}; 39 | 40 | SECTION("T is first type") 41 | { 42 | SECTION("Gets reference to first element") 43 | { 44 | auto& lhs = bpstd::get(sut); 45 | auto& rhs = bpstd::get<0>(sut); 46 | 47 | REQUIRE(&lhs == &rhs); 48 | } 49 | } 50 | 51 | SECTION("T is second type") 52 | { 53 | SECTION("Gets reference to second element") 54 | { 55 | auto& lhs = bpstd::get(sut); 56 | auto& rhs = bpstd::get<1>(sut); 57 | 58 | REQUIRE(&lhs == &rhs); 59 | } 60 | } 61 | } 62 | 63 | TEST_CASE("get(pair&&)", "[utility]") 64 | { 65 | auto sut = bpstd::pair{1,3.14f}; 66 | 67 | SECTION("T is first type") 68 | { 69 | SECTION("Gets reference to first element") 70 | { 71 | auto&& lhs = bpstd::get(bpstd::move(sut)); 72 | auto&& rhs = bpstd::get<0>(bpstd::move(sut)); 73 | 74 | REQUIRE(&lhs == &rhs); 75 | } 76 | } 77 | 78 | SECTION("T is second type") 79 | { 80 | SECTION("Gets reference to second element") 81 | { 82 | auto&& lhs = bpstd::get(bpstd::move(sut)); 83 | auto&& rhs = bpstd::get<1>(bpstd::move(sut)); 84 | 85 | REQUIRE(&lhs == &rhs); 86 | } 87 | } 88 | } 89 | 90 | TEST_CASE("get(const pair&)", "[utility]") 91 | { 92 | const auto sut = bpstd::pair{1,3.14f}; 93 | 94 | SECTION("T is first type") 95 | { 96 | SECTION("Gets reference to first element") 97 | { 98 | const auto& lhs = bpstd::get(sut); 99 | const auto& rhs = bpstd::get<0>(sut); 100 | 101 | REQUIRE(&lhs == &rhs); 102 | } 103 | } 104 | 105 | SECTION("T is second type") 106 | { 107 | SECTION("Gets reference to second element") 108 | { 109 | const auto& lhs = bpstd::get(sut); 110 | const auto& rhs = bpstd::get<1>(sut); 111 | 112 | REQUIRE(&lhs == &rhs); 113 | } 114 | } 115 | } 116 | 117 | TEST_CASE("get(const pair&&)", "[utility]") 118 | { 119 | const auto sut = bpstd::pair{1,3.14f}; 120 | 121 | SECTION("T is first type") 122 | { 123 | SECTION("Gets reference to first element") 124 | { 125 | const auto&& lhs = bpstd::get(bpstd::move(sut)); 126 | const auto&& rhs = bpstd::get<0>(bpstd::move(sut)); 127 | 128 | REQUIRE(&lhs == &rhs); 129 | } 130 | } 131 | 132 | SECTION("T is second type") 133 | { 134 | SECTION("Gets reference to second element") 135 | { 136 | const auto&& lhs = bpstd::get(bpstd::move(sut)); 137 | const auto&& rhs = bpstd::get<1>(bpstd::move(sut)); 138 | 139 | REQUIRE(&lhs == &rhs); 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /include/bpstd/complex.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// \file complex.hpp 3 | /// 4 | /// \brief This header provides definitions from the C++ header 5 | //////////////////////////////////////////////////////////////////////////////// 6 | 7 | /* 8 | The MIT License (MIT) 9 | 10 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | #ifndef BPSTD_COMPLEX_HPP 31 | #define BPSTD_COMPLEX_HPP 32 | 33 | #include "detail/config.hpp" 34 | 35 | #include 36 | 37 | BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 38 | 39 | namespace bpstd { 40 | 41 | //============================================================================ 42 | // class : complex 43 | //============================================================================ 44 | 45 | template 46 | using complex = std::complex; 47 | 48 | //============================================================================ 49 | // literals : class : complex 50 | //============================================================================ 51 | 52 | inline namespace literals { 53 | inline namespace complex_literals { 54 | 55 | constexpr complex operator""_il(long double i) noexcept; 56 | constexpr complex operator""_il(unsigned long long i) noexcept; 57 | 58 | constexpr complex operator""_i(long double i) noexcept; 59 | constexpr complex operator""_i(unsigned long long i) noexcept; 60 | 61 | constexpr complex operator""_if(long double i) noexcept; 62 | constexpr complex operator""_if(unsigned long long i) noexcept; 63 | 64 | } // namespace complex_literals 65 | } // namespace literals 66 | } // namespace bpstd 67 | 68 | //============================================================================== 69 | // literals : class : complex 70 | //============================================================================== 71 | 72 | inline BPSTD_INLINE_VISIBILITY constexpr 73 | bpstd::complex 74 | bpstd::literals::complex_literals::operator""_il(long double i) 75 | noexcept 76 | { 77 | return complex{0, i}; 78 | } 79 | 80 | inline BPSTD_INLINE_VISIBILITY constexpr 81 | bpstd::complex 82 | bpstd::literals::complex_literals::operator""_il(unsigned long long i) 83 | noexcept 84 | { 85 | return complex{0, static_cast(i)}; 86 | } 87 | 88 | inline BPSTD_INLINE_VISIBILITY constexpr 89 | bpstd::complex 90 | bpstd::literals::complex_literals::operator""_i(long double i) 91 | noexcept 92 | { 93 | return complex{0, static_cast(i)}; 94 | } 95 | 96 | inline BPSTD_INLINE_VISIBILITY constexpr 97 | bpstd::complex 98 | bpstd::literals::complex_literals::operator""_i(unsigned long long i) 99 | noexcept 100 | { 101 | return complex{0, static_cast(i)}; 102 | } 103 | 104 | inline BPSTD_INLINE_VISIBILITY constexpr 105 | bpstd::complex 106 | bpstd::literals::complex_literals::operator""_if(long double i) 107 | noexcept 108 | { 109 | return complex{0, static_cast(i)}; 110 | } 111 | 112 | inline BPSTD_INLINE_VISIBILITY constexpr 113 | bpstd::complex 114 | bpstd::literals::complex_literals::operator""_if(unsigned long long i) 115 | noexcept 116 | { 117 | return complex{0, static_cast(i)}; 118 | } 119 | 120 | BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 121 | 122 | #endif /* BPSTD_COMPLEX_HPP */ 123 | -------------------------------------------------------------------------------- /.github/workflows/build-windows.yml: -------------------------------------------------------------------------------- 1 | name: Windows 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'include/**.hpp' 7 | - 'test/**.cpp' 8 | - '**.cmake' 9 | - 'conanfile.py' 10 | - 'CMakeLists.txt' 11 | - 'test/CMakeLists.txt' 12 | - '.github/workflows/build-windows.yml' 13 | pull_request: 14 | paths: 15 | - 'include/**.hpp' 16 | - 'test/**.cpp' 17 | - '**.cmake' 18 | - 'conanfile.py' 19 | - 'CMakeLists.txt' 20 | - 'test/CMakeLists.txt' 21 | - '.github/workflows/build-windows.yml' 22 | 23 | jobs: 24 | test: 25 | name: Windows ${{matrix.compiler.name}} ${{matrix.compiler.version}} (${{matrix.arch}}) 26 | runs-on: windows-latest 27 | 28 | env: 29 | build-directory: build 30 | 31 | strategy: 32 | fail-fast: false 33 | matrix: 34 | compiler: 35 | # Xcode Versions 36 | - { name: "gcc", version: "latest", cc: gcc, cxx: g++ } 37 | - { name: "clang", version: "10", cc: clang, cxx: clang++ } 38 | - { name: "clang-cl", version: "latest", cc: clang-cl, cxx: clang-cl } 39 | - { name: "cl", version: "14.0", toolset_version: "140", cc: cl, cxx: cl } 40 | - { name: "cl", version: "14.16", toolset_version: "141", cc: cl, cxx: cl } 41 | - { name: "cl", version: "14.28", toolset_version: "142", cc: cl, cxx: cl } 42 | arch: [x86, x86_64] 43 | 44 | # Visual Studios specifies strange terminology for x86/x86_64 45 | include: 46 | - arch: x86 47 | vs_arch: Win32 48 | - arch: x86_64 49 | vs_arch: x64 50 | 51 | # GCC fails to compile 32-bit correctly with Github's Windows runner 52 | # configuration. 53 | exclude: 54 | - arch: x86 55 | compiler: { name: "gcc", cc: gcc, cxx: g++ } 56 | 57 | steps: 58 | - name: Clone 59 | uses: actions/checkout@v2 60 | 61 | - name: Set up Python 62 | uses: actions/setup-python@v1 63 | with: 64 | python-version: 3.7 65 | 66 | - name: Prepare Environment 67 | shell: bash 68 | run: | 69 | if [[ ${{matrix.compiler.name}} == 'clang' ]]; then 70 | curl -fsSL -o LLVM${{matrix.compiler.version}}.exe https://github.com/llvm/llvm-project/releases/download/llvmorg-${{matrix.compiler.version}}.0.0/LLVM-${{matrix.compiler.version}}.0.0-win64.exe 71 | 7z x LLVM${{matrix.compiler.version}}.exe -y -o"C:/Program Files/LLVM" 72 | fi 73 | 74 | python -m pip install --upgrade pip 75 | pip install conan 76 | cmake -E make_directory ${{env.build-directory}} 77 | cmake -E chdir ${{env.build-directory}} conan install .. 78 | 79 | - name: Prepare Architecture 80 | if: matrix.compiler.name == 'clang' && matrix.arch == 'x86' 81 | shell: bash 82 | run: echo "CXXFLAGS=${CXXFLAGS} -m32" >> ${GITHUB_ENV} 83 | 84 | - name: Configure (gcc) 85 | working-directory: ${{env.build-directory}} 86 | if: ${{matrix.compiler.name == 'gcc'}} 87 | env: 88 | CC: gcc 89 | CXX: g++ 90 | run: cmake .. -DBACKPORT_COMPILE_UNIT_TESTS=On -G"MinGW Makefiles" 91 | 92 | - name: Configure (clang) 93 | working-directory: ${{env.build-directory}} 94 | if: ${{matrix.compiler.name == 'clang'}} 95 | run: | 96 | cmake .. -G"MinGW Makefiles" ` 97 | -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" ` 98 | -DBACKPORT_COMPILE_UNIT_TESTS=On 99 | 100 | - name: Configure (clang-cl) 101 | working-directory: ${{env.build-directory}} 102 | if: ${{matrix.compiler.name == 'clang-cl'}} 103 | run: | 104 | cmake .. -G "Visual Studio 16 2019" -A ${{matrix.vs_arch}} ` 105 | -T ClangCL ` 106 | -DBACKPORT_COMPILE_UNIT_TESTS=On 107 | 108 | - name: Configure (MSVC) 109 | working-directory: ${{env.build-directory}} 110 | if: ${{matrix.compiler.name == 'cl'}} 111 | run: | 112 | cmake .. -G "Visual Studio 16 2019" -A ${{matrix.vs_arch}} ` 113 | -T v${{matrix.compiler.toolset_version}} ` 114 | -DBACKPORT_COMPILE_UNIT_TESTS=On ` 115 | 116 | # Debug Configuration 117 | 118 | - name: Configure (Debug) 119 | working-directory: ${{env.build-directory}} 120 | if: ${{matrix.compiler.name == 'clang' || matrix.compiler.name == 'gcc'}} 121 | run: cmake . -DCMAKE_BUILD_TYPE=Debug 122 | 123 | - name: Build (Debug) 124 | working-directory: ${{env.build-directory}} 125 | run: cmake --build . --config Debug 126 | 127 | - name: Test (Debug) 128 | working-directory: ${{env.build-directory}} 129 | run: ctest -C Debug --output-on-failure 130 | 131 | # Release Configuration 132 | 133 | - name: Configure (Release) 134 | working-directory: ${{env.build-directory}} 135 | if: ${{matrix.compiler.name == 'clang' || matrix.compiler.name == 'gcc'}} 136 | run: cmake . -DCMAKE_BUILD_TYPE=Release 137 | 138 | - name: Build (Release) 139 | working-directory: ${{env.build-directory}} 140 | run: cmake --build . --config Release 141 | 142 | - name: Test (Release) 143 | working-directory: ${{env.build-directory}} 144 | run: ctest -C Release --output-on-failure 145 | -------------------------------------------------------------------------------- /test/src/bpstd/type_traits.test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | 29 | #if defined(__clang__) 30 | # pragma clang diagnostic push 31 | # pragma clang diagnostic ignored "-Wunneeded-internal-declaration" 32 | # pragma clang diagnostic ignored "-Wunused-member-function" 33 | # pragma clang diagnostic ignored "-Wunused-function" 34 | #elif defined(__GNUC__) 35 | # pragma GCC diagnostic ignored "-Wunused-function" 36 | #endif 37 | 38 | //============================================================================== 39 | // is_nothrow_convertible 40 | //============================================================================== 41 | 42 | static_assert( 43 | bpstd::is_nothrow_convertible::value, 44 | "long -> int conversions are non-throwing" 45 | ); 46 | static_assert( 47 | bpstd::is_convertible::value, 48 | "Sanity check that const char* is considered convertible to std::string" 49 | ); 50 | static_assert( 51 | !bpstd::is_nothrow_convertible::value, 52 | "C-strings to std::string is a possibly throwing conversion" 53 | ); 54 | 55 | //============================================================================== 56 | // is_invocable_r 57 | //============================================================================== 58 | 59 | namespace { 60 | 61 | bool invocable_test(int) { return false; } 62 | 63 | struct nothrow_invocable 64 | { 65 | const char* operator()() noexcept { return "hello world"; } 66 | }; 67 | 68 | static_assert( 69 | bpstd::is_invocable::value, 70 | "invocable_test should be invocable with int" 71 | ); 72 | static_assert( 73 | bpstd::is_invocable::value, 74 | "invocable_test should be invocable with floats due to implicit conversion to int" 75 | ); 76 | static_assert( 77 | !bpstd::is_invocable::value, 78 | "invocable_test should not be invocable without an argument" 79 | ); 80 | static_assert( 81 | bpstd::is_invocable_r::value, 82 | "invocable_test returns a 'bool'" 83 | ); 84 | static_assert( 85 | bpstd::is_invocable_r::value, 86 | "invocable_test returns a 'bool', which is convertible to 'int'" 87 | ); 88 | 89 | // C++11 and C++14 don't encode 'noexcept' in the type, so we can't test for 90 | // noexcept status on function or member function pointers.. So test with a 91 | // functor instead 92 | 93 | static_assert( 94 | bpstd::is_nothrow_invocable::value, 95 | "nothrow_invocable should be nothrow invocable" 96 | ); 97 | static_assert( 98 | bpstd::is_nothrow_invocable_r::value, 99 | "nothrow_invocable returns a type convertible to std::string" 100 | ); 101 | static_assert( 102 | !bpstd::is_nothrow_invocable_r::value, 103 | "invocable_test is not noexcept, does not check type conversion" 104 | ); 105 | 106 | } // anonymous namespace 107 | 108 | 109 | //============================================================================== 110 | // is_swappable_with 111 | //============================================================================== 112 | 113 | namespace { 114 | struct example{ 115 | example() = default; 116 | example(example&&) = delete; 117 | example(const example&) = delete; 118 | example& operator=(example&&) = delete; 119 | example& operator=(const example&) = delete; 120 | }; 121 | 122 | void swap(example&,example&) noexcept; 123 | } // namespace 124 | static_assert( 125 | bpstd::is_swappable::value, "" 126 | ); 127 | #if !defined(_MSC_FULL_VER) || _MSC_FULL_VER >= 191426428 128 | static_assert( 129 | bpstd::is_swappable::value, "" 130 | ); 131 | #endif 132 | 133 | static_assert( 134 | bpstd::detail::is_nothrow_swappable_with::value, "" 135 | ); 136 | #if !defined(_MSC_FULL_VER) || _MSC_FULL_VER >= 191426428 137 | static_assert( 138 | bpstd::is_nothrow_swappable::value, "" 139 | ); 140 | #endif 141 | static_assert( 142 | !bpstd::is_swappable_with::value, "" 143 | ); 144 | static_assert( 145 | !bpstd::is_swappable_with::value, "" 146 | ); 147 | 148 | //============================================================================= 149 | // underlying_type sfinae test 150 | //============================================================================= 151 | 152 | namespace { 153 | 154 | template 155 | typename bpstd::underlying_type::type to_int(Enum e) 156 | { 157 | return static_cast::type>(e); 158 | } 159 | template ::value>> 160 | T to_int(T t) 161 | { 162 | return t; 163 | } 164 | 165 | enum class example_enum{}; 166 | 167 | // Make sure the calls are well-formed and properly triggers SFINAE 168 | void underlying_type_sfinae_test() 169 | { 170 | to_int(5); 171 | to_int(example_enum{}); 172 | } 173 | 174 | } 175 | 176 | #if defined(__clang__) 177 | # pragma clang diagnostic pop 178 | #endif 179 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | # Disable defaulting the warning flags for MSVC 4 | # this isn't bad, it's just inconvenient 5 | cmake_policy(SET CMP0092 NEW) 6 | 7 | if (PROJECT_NAME) 8 | set(IS_SUBPROJECT TRUE) 9 | endif () 10 | 11 | set(BACKPORT_CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") 12 | set(BACKPORT_CMAKE_TEMPLATE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/templates") 13 | 14 | set(CMAKE_MODULE_PATH "${BACKPORT_CMAKE_MODULE_PATH}" "${CMAKE_MODULE_PATH}") 15 | 16 | option(BACKPORT_COMPILE_UNIT_TESTS "Compile and run the unit tests for this library" OFF) 17 | 18 | if (NOT CMAKE_TESTING_ENABLED AND BACKPORT_COMPILE_UNIT_TESTS) 19 | enable_testing() 20 | endif () 21 | 22 | project(Backport 23 | VERSION "1.2.0" 24 | LANGUAGES CXX 25 | ) 26 | 27 | set(BACKPORT_VERSION_MAJOR ${PROJECT_VERSION_MAJOR} CACHE INTERNAL "Major version of Backport") 28 | set(BACKPORT_VERSION_MINOR ${PROJECT_VERSION_MINOR} CACHE INTERNAL "Minor version of Backport") 29 | set(BACKPORT_VERSION_PATCH ${PROJECT_VERSION_PATCH} CACHE INTERNAL "Patch version of Backport") 30 | set(BACKPORT_VERSION ${PROJECT_VERSION} CACHE INTERNAL "Version of Backport") 31 | 32 | # If using conan, only set the find paths. This project is trying to be 33 | # fully CMake 34 | if (EXISTS "${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake") 35 | include("${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake") 36 | conan_set_find_paths() 37 | endif () 38 | 39 | ############################################################################## 40 | # Targets 41 | ############################################################################## 42 | 43 | set(CMAKE_CXX_STANDARD 11) 44 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 45 | set(CMAKE_CXX_EXTENSIONS OFF) 46 | 47 | set(header_files 48 | "include/bpstd/detail/nth_type.hpp" 49 | "include/bpstd/detail/variant_fwds.hpp" 50 | "include/bpstd/detail/variant_union.hpp" 51 | "include/bpstd/detail/variant_base.hpp" 52 | "include/bpstd/detail/variant_traits.hpp" 53 | "include/bpstd/detail/variant_visitors.hpp" 54 | "include/bpstd/detail/move.hpp" 55 | "include/bpstd/detail/invoke.hpp" 56 | "include/bpstd/detail/proxy_iterator.hpp" 57 | "include/bpstd/detail/config.hpp" 58 | "include/bpstd/type_traits.hpp" 59 | "include/bpstd/complex.hpp" 60 | "include/bpstd/exception.hpp" 61 | "include/bpstd/functional.hpp" 62 | "include/bpstd/memory.hpp" 63 | "include/bpstd/utility.hpp" 64 | "include/bpstd/tuple.hpp" 65 | "include/bpstd/any.hpp" 66 | "include/bpstd/cstddef.hpp" 67 | "include/bpstd/string_view.hpp" 68 | "include/bpstd/optional.hpp" 69 | "include/bpstd/iterator.hpp" 70 | "include/bpstd/span.hpp" 71 | "include/bpstd/chrono.hpp" 72 | "include/bpstd/string.hpp" 73 | "include/bpstd/variant.hpp" 74 | ) 75 | 76 | include(SourceGroup) 77 | source_group_tree("include" PREFIX "Header Files" FILES ${header_files}) 78 | 79 | add_library(${PROJECT_NAME} INTERFACE) 80 | add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) 81 | 82 | target_include_directories(${PROJECT_NAME} 83 | INTERFACE $ 84 | INTERFACE $ 85 | ) 86 | 87 | if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND 88 | "${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC") 89 | # clang-cl does not appear to implement '-pedantic' or 'pedantic-errors', 90 | # so this case needs to be handled specifically 91 | add_compile_options(-Wall -Werror -Wextra) 92 | 93 | # Disable the ridiculous compatibility warnings, since it fails on files not 94 | # ending in newlines 95 | add_compile_options(-Wno-c++98-compat -Wno-c++98-compat-pedantic) 96 | 97 | # This gives an unbelievable amount of false-positives spuriously. Ignore it. 98 | add_compile_options(-Wno-unneeded-member-function) 99 | elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR 100 | "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) 101 | add_compile_options(-Wall -Werror -Wextra -pedantic -pedantic-errors) 102 | elseif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) 103 | add_compile_options(/W4 /WX) 104 | endif () 105 | 106 | # Header Self-Containment Tests 107 | 108 | include(AddSelfContainmentTest) 109 | 110 | if (BACKPORT_COMPILE_UNIT_TESTS) 111 | add_self_containment_test(${PROJECT_NAME}.SelfContainmentTest 112 | TARGET ${PROJECT_NAME} 113 | HEADERS ${header_files} 114 | ) 115 | 116 | add_subdirectory("test") 117 | endif () 118 | 119 | ############################################################################## 120 | # Installation 121 | ############################################################################## 122 | 123 | if (IS_SUBPROJECT) 124 | return() 125 | endif () 126 | 127 | include(CMakePackageConfigHelpers) 128 | 129 | # The generated ConfigVersion is tied to the architecture it's generated on, 130 | # denoted by the size of the pointer. Since this is a header-only library, 131 | # this is an unnecessary and constricting check -- but CMake does not allow us 132 | # to customize it. 133 | # 134 | # A simple workaround is to simply set the CMAKE_SIZEOF_VOID_P to an empty 135 | # string in CMake so that the generated file does not fail to work on different 136 | # architectures. This gets reset after we generate the file 137 | set(TEMP_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P}) 138 | set(CMAKE_SIZEOF_VOID_P "") 139 | write_basic_package_version_file( 140 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" 141 | COMPATIBILITY 142 | SameMajorVersion 143 | ) 144 | set(CMAKE_SIZEOF_VOID_P ${TEMP_CMAKE_SIZEOF_VOID_P}) 145 | 146 | configure_file( 147 | "${BACKPORT_CMAKE_TEMPLATE_PATH}/PackageConfig.cmake.in" 148 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 149 | @ONLY 150 | ) 151 | 152 | #----------------------------------------------------------------------------- 153 | 154 | include(GNUInstallDirs) 155 | 156 | set(BACKPORT_CMAKE_CONFIG_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") 157 | 158 | # Includes 159 | install( 160 | DIRECTORY "include/" 161 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" 162 | ) 163 | 164 | # Targets 165 | install( 166 | TARGETS ${PROJECT_NAME} 167 | EXPORT ${PROJECT_NAME}Targets 168 | DESTINATION "${CMAKE_INSTALL_LIBDIR}" 169 | ) 170 | install( 171 | EXPORT ${PROJECT_NAME}Targets 172 | NAMESPACE "Backport::" 173 | DESTINATION "${BACKPORT_CMAKE_CONFIG_DESTINATION}" 174 | ) 175 | install( 176 | FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" 177 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 178 | DESTINATION "${BACKPORT_CMAKE_CONFIG_DESTINATION}" 179 | ) 180 | -------------------------------------------------------------------------------- /.github/workflows/build-ubuntu.yml: -------------------------------------------------------------------------------- 1 | name: Ubuntu 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'include/**.hpp' 7 | - 'test/**.cpp' 8 | - '**.cmake' 9 | - 'conanfile.py' 10 | - 'CMakeLists.txt' 11 | - 'test/CMakeLists.txt' 12 | - '.github/workflows/build-ubuntu.yml' 13 | pull_request: 14 | paths: 15 | - 'include/**.hpp' 16 | - 'test/**.cpp' 17 | - '**.cmake' 18 | - 'conanfile.py' 19 | - 'CMakeLists.txt' 20 | - 'test/CMakeLists.txt' 21 | - '.github/workflows/build-ubuntu.yml' 22 | 23 | jobs: 24 | test: 25 | name: Ubuntu ${{matrix.compiler.cc}} (${{matrix.arch}}) 26 | runs-on: ubuntu-20.04 27 | 28 | env: 29 | build-directory: build 30 | 31 | strategy: 32 | fail-fast: false 33 | matrix: 34 | compiler: 35 | # GCC Versions 36 | - { cc: gcc-5, cxx: g++-5 } 37 | - { cc: gcc-6, cxx: g++-6 } 38 | - { cc: gcc-7, cxx: g++-7 } 39 | - { cc: gcc-8, cxx: g++-8 } 40 | - { cc: gcc-9, cxx: g++-9 } 41 | - { cc: gcc-10, cxx: g++-10 } 42 | 43 | # Clang Versions 44 | - { cc: clang-3.5, cxx: clang++-3.5 } 45 | - { cc: clang-3.6, cxx: clang++-3.6 } 46 | - { cc: clang-3.7, cxx: clang++-3.7 } 47 | - { cc: clang-3.8, cxx: clang++-3.8 } 48 | - { cc: clang-3.9, cxx: clang++-3.9 } 49 | - { cc: clang-4.0, cxx: clang++-4.0 } 50 | - { cc: clang-5.0, cxx: clang++-5.0 } 51 | - { cc: clang-6.0, cxx: clang++-6.0 } 52 | - { cc: clang-7, cxx: clang++-7 } 53 | - { cc: clang-8, cxx: clang++-8 } 54 | - { cc: clang-9, cxx: clang++-9 } 55 | - { cc: clang-10, cxx: clang++-10 } 56 | arch: [x86, x86_64] 57 | 58 | # clang 3.5 through 3.8 fail to compiler for 32-bit 59 | # Disable these builds for time being 60 | exclude: 61 | - arch: x86 62 | compiler: { cc: clang-3.5, cxx: clang++-3.5 } 63 | - arch: x86 64 | compiler: { cc: clang-3.6, cxx: clang++-3.6 } 65 | - arch: x86 66 | compiler: { cc: clang-3.7, cxx: clang++-3.7 } 67 | - arch: x86 68 | compiler: { cc: clang-3.8, cxx: clang++-3.8 } 69 | 70 | steps: 71 | - name: Clone 72 | uses: actions/checkout@v2 73 | 74 | - name: Set up Python 75 | uses: actions/setup-python@v1 76 | with: 77 | python-version: 3.7 78 | 79 | - name: Prepare Environment 80 | run: | 81 | if [[ "${{matrix.arch}}" == "x86" ]]; then 82 | sudo dpkg --add-architecture i386 83 | fi 84 | sudo apt-get update 85 | # Older versions of clang and gcc are not available on Ubuntu 20.04; so 86 | # we need to add the repos manually first. 87 | sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ bionic main universe" 88 | sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial main universe" 89 | sudo apt-get update 90 | 91 | if [[ "${{matrix.compiler.cc}}" =~ "gcc" ]]; then 92 | sudo apt-get install -y ${{matrix.compiler.cxx}} ${{matrix.compiler.cxx}}-multilib 93 | else 94 | sudo apt-get install -y ${{matrix.compiler.cc}} g++-multilib 95 | 96 | # g++5 needed for clang 32-bit builds 97 | if [[ "${{matrix.arch}}" == "x86" ]]; then 98 | sudo apt-get install -y g++-5 99 | fi 100 | fi 101 | 102 | python -m pip install --upgrade pip 103 | pip install conan 104 | cmake -E make_directory ${{env.build-directory}} 105 | cmake -E chdir ${{env.build-directory}} conan install .. 106 | 107 | - name: Prepare Architecture 108 | run: | 109 | if [[ "${{matrix.arch}}" = "x86" ]]; then 110 | echo "CXXFLAGS=${CXXFLAGS} -m32" >> ${GITHUB_ENV} 111 | fi 112 | 113 | # Debug Configuration 114 | 115 | - name: Configure (Debug) 116 | working-directory: ${{env.build-directory}} 117 | env: 118 | CC: ${{matrix.compiler.cc}} 119 | CXX: ${{matrix.compiler.cxx}} 120 | run: cmake .. -DCMAKE_BUILD_TYPE=Debug -DBACKPORT_COMPILE_UNIT_TESTS=On 121 | 122 | - name: Build 123 | working-directory: ${{env.build-directory}} 124 | run: cmake --build . 125 | 126 | - name: Test 127 | working-directory: ${{env.build-directory}} 128 | run: ctest --output-on-failure 129 | 130 | # Release Configuration 131 | 132 | - name: Configure (Release) 133 | working-directory: ${{env.build-directory}} 134 | run: cmake .. -DCMAKE_BUILD_TYPE=Release 135 | 136 | - name: Build (Release) 137 | working-directory: ${{env.build-directory}} 138 | run: cmake --build . 139 | 140 | - name: Test (Release) 141 | working-directory: ${{env.build-directory}} 142 | run: ctest --output-on-failure 143 | 144 | sanitize: 145 | name: Ubuntu ${{matrix.compiler.cc}} '${{matrix.sanitizer}}' sanitizer 146 | runs-on: ubuntu-20.04 147 | needs: test 148 | 149 | env: 150 | build-directory: build 151 | 152 | strategy: 153 | matrix: 154 | compiler: 155 | - { cc: gcc, cxx: g++ } 156 | - { cc: clang, cxx: clang++ } 157 | sanitizer: [address, undefined] 158 | 159 | steps: 160 | - name: Clone 161 | uses: actions/checkout@v2 162 | 163 | - name: Set up Python 164 | uses: actions/setup-python@v1 165 | with: 166 | python-version: 3.7 167 | 168 | - name: Prepare Environment 169 | run: | 170 | python -m pip install --upgrade pip 171 | pip install conan 172 | cmake -E make_directory ${{env.build-directory}} 173 | cmake -E chdir ${{env.build-directory}} conan install .. 174 | 175 | - name: Configure 176 | working-directory: ${{env.build-directory}} 177 | env: 178 | CC: ${{matrix.compiler.cc}} 179 | CXX: ${{matrix.compiler.cxx}} 180 | run: | 181 | cmake .. \ 182 | -DCMAKE_BUILD_TYPE=Debug \ 183 | -DBACKPORT_COMPILE_UNIT_TESTS=On \ 184 | -DCMAKE_CXX_FLAGS="-fsanitize=${{matrix.sanitizer}}" 185 | 186 | - name: Build 187 | working-directory: ${{env.build-directory}} 188 | run: cmake --build . 189 | 190 | - name: Test (Sanitize) 191 | working-directory: ${{env.build-directory}} 192 | run: ctest --output-on-failure 193 | -------------------------------------------------------------------------------- /include/bpstd/detail/variant_visitors.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * \file variant_visitors.hpp 3 | * 4 | * \brief This internal header provides the definition of various visitors for 5 | * the variant. 6 | * 7 | * These variants are used internally to construct a variant. 8 | *****************************************************************************/ 9 | 10 | /* 11 | The MIT License (MIT) 12 | 13 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy 16 | of this software and associated documentation files (the "Software"), to deal 17 | in the Software without restriction, including without limitation the rights 18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | copies of the Software, and to permit persons to whom the Software is 20 | furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in 23 | all copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | */ 33 | #ifndef BPSTD_DETAIL_VARIANT_VISITORS_HPP 34 | #define BPSTD_DETAIL_VARIANT_VISITORS_HPP 35 | 36 | #include "config.hpp" 37 | #include "move.hpp" 38 | #include "../tuple.hpp" // get 39 | #include "../utility.hpp" // index_sequence 40 | 41 | #include // placement new 42 | #include // std::swap 43 | 44 | BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 45 | 46 | namespace bpstd { 47 | namespace detail { 48 | 49 | //////////////////////////////////////////////////////////////////////////// 50 | /// \brief A visitor for copy-constructing an underlying variant from the 51 | /// same active type from the other variant 52 | //////////////////////////////////////////////////////////////////////////// 53 | struct variant_copy_construct_visitor 54 | { 55 | template 56 | inline BPSTD_INLINE_VISIBILITY 57 | void operator()(T& self, const T& other) const 58 | { 59 | new (&self) T(other); 60 | } 61 | }; 62 | 63 | //////////////////////////////////////////////////////////////////////////// 64 | /// \brief A visitor for copy-assigning an underlying variant from the 65 | /// same active type from the other variant 66 | //////////////////////////////////////////////////////////////////////////// 67 | struct variant_copy_assign_visitor 68 | { 69 | template 70 | inline BPSTD_INLINE_VISIBILITY 71 | void operator()(T& self, const T& other) const 72 | { 73 | self = other; 74 | } 75 | }; 76 | 77 | //////////////////////////////////////////////////////////////////////////// 78 | /// \brief A visitor for move-constructing an underlying variant from the 79 | /// same active type from the other variant 80 | //////////////////////////////////////////////////////////////////////////// 81 | struct variant_move_construct_visitor 82 | { 83 | template 84 | inline BPSTD_INLINE_VISIBILITY 85 | void operator()(T& self, U&& other) const 86 | { 87 | new (&self) T(bpstd::forward(other)); 88 | } 89 | }; 90 | 91 | //////////////////////////////////////////////////////////////////////////// 92 | /// \brief A visitor for move-assign an underlying variant from the 93 | /// same active type from the other variant 94 | //////////////////////////////////////////////////////////////////////////// 95 | struct variant_move_assign_visitor 96 | { 97 | template 98 | inline BPSTD_INLINE_VISIBILITY 99 | void operator()(T& self, U&& other) const 100 | { 101 | self = bpstd::forward(other); 102 | } 103 | }; 104 | 105 | //////////////////////////////////////////////////////////////////////////// 106 | /// \brief A visitor for swapping the underlying elements of a variant 107 | //////////////////////////////////////////////////////////////////////////// 108 | struct variant_swap_visitor 109 | { 110 | template 111 | inline BPSTD_INLINE_VISIBILITY 112 | void operator()(T& lhs, T& rhs) const 113 | { 114 | using std::swap; 115 | swap(lhs,rhs); 116 | } 117 | }; 118 | 119 | //////////////////////////////////////////////////////////////////////////// 120 | /// \brief A visitor for assigning an element from T to the underlying 121 | /// active variant alternative 122 | //////////////////////////////////////////////////////////////////////////// 123 | template 124 | struct variant_assign_visitor 125 | { 126 | Arg m_value; 127 | 128 | template 129 | inline BPSTD_INLINE_VISIBILITY 130 | variant_assign_visitor(UArg&& u) 131 | : m_value(bpstd::forward(u)) 132 | { 133 | 134 | } 135 | 136 | template 137 | inline BPSTD_INLINE_VISIBILITY 138 | void operator()(U&) 139 | { 140 | } 141 | 142 | inline BPSTD_INLINE_VISIBILITY 143 | void operator()(T& x) 144 | { 145 | x = static_cast(m_value); 146 | } 147 | }; 148 | 149 | //////////////////////////////////////////////////////////////////////////// 150 | /// \brief A visitor for emplacing elements into a variant 151 | //////////////////////////////////////////////////////////////////////////// 152 | template 153 | struct variant_emplace_visitor 154 | { 155 | Tuple m_tuple; 156 | 157 | template 158 | inline BPSTD_INLINE_VISIBILITY 159 | variant_emplace_visitor(UTuple&& tuple) 160 | : m_tuple{bpstd::forward(tuple)} 161 | { 162 | 163 | } 164 | 165 | template 166 | inline BPSTD_INLINE_VISIBILITY 167 | void operator()(U&) 168 | { 169 | } 170 | 171 | inline BPSTD_INLINE_VISIBILITY 172 | void operator()(T& x) 173 | { 174 | emplace_from_tuple( 175 | &x, 176 | bpstd::move(m_tuple), 177 | make_index_sequence::value>{} 178 | ); 179 | } 180 | 181 | template 182 | inline BPSTD_INLINE_VISIBILITY 183 | static void emplace_from_tuple(void* p, UTuple&& tuple, index_sequence) 184 | { 185 | new(p) T(std::get(bpstd::forward(tuple))...); 186 | } 187 | 188 | }; 189 | 190 | } // namespace detail 191 | } // namespace bpstd 192 | 193 | BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 194 | 195 | #endif /* BPSTD_DETAIL_VARIANT_VISITORS_HPP */ 196 | -------------------------------------------------------------------------------- /include/bpstd/chrono.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// \file chrono.hpp 3 | /// 4 | /// \brief This header provides definitions from the C++ header 5 | //////////////////////////////////////////////////////////////////////////////// 6 | 7 | /* 8 | The MIT License (MIT) 9 | 10 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | #ifndef BPSTD_CHRONO_HPP 31 | #define BPSTD_CHRONO_HPP 32 | 33 | #include "detail/config.hpp" 34 | 35 | #include // std::chrono::duration, std::chrono::system_clock, etc 36 | #include // std::int32_t 37 | 38 | BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 39 | 40 | namespace bpstd { 41 | namespace chrono { 42 | 43 | template > 44 | using duration = std::chrono::duration; 45 | 46 | template 47 | using time_point = std::chrono::time_point; 48 | 49 | using nanoseconds = std::chrono::nanoseconds; 50 | using microseconds = std::chrono::microseconds; 51 | using milliseconds = std::chrono::milliseconds; 52 | using seconds = std::chrono::seconds; 53 | using minutes = std::chrono::minutes; 54 | using hours = std::chrono::hours; 55 | using days = std::chrono::duration>; 56 | using weeks = std::chrono::duration>; 57 | using months = std::chrono::duration>; 58 | using years = std::chrono::duration>; 59 | 60 | using steady_clock = std::chrono::steady_clock; 61 | using system_clock = std::chrono::system_clock; 62 | 63 | template 64 | using sys_time = time_point; 65 | using sys_seconds = sys_time; 66 | using sys_days = sys_time; 67 | 68 | 69 | } // namespace chrono 70 | 71 | //============================================================================ 72 | // non-member functions 73 | //============================================================================ 74 | 75 | //---------------------------------------------------------------------------- 76 | // Literals 77 | //---------------------------------------------------------------------------- 78 | 79 | inline namespace literals { 80 | inline namespace chrono_literals { 81 | 82 | constexpr std::chrono::hours operator""_h(unsigned long long x); 83 | constexpr std::chrono::duration> operator""_h(long double x); 84 | 85 | constexpr chrono::minutes operator""_min(unsigned long long x); 86 | constexpr chrono::duration> operator""_min(long double x); 87 | 88 | constexpr chrono::seconds operator""_s(unsigned long long x); 89 | constexpr chrono::duration operator""_s(long double x); 90 | 91 | constexpr chrono::milliseconds operator""_ms(unsigned long long x); 92 | constexpr chrono::duration operator""_ms(long double x); 93 | 94 | constexpr chrono::microseconds operator""_us(unsigned long long x); 95 | constexpr chrono::duration operator""_us(long double x); 96 | 97 | constexpr chrono::nanoseconds operator""_ns(unsigned long long x); 98 | constexpr chrono::duration operator""_ns(long double x); 99 | 100 | } // inline namespace chrono_literals 101 | } // inline namespace chrono 102 | } // namespace bpstd 103 | 104 | inline BPSTD_INLINE_VISIBILITY constexpr 105 | std::chrono::hours 106 | bpstd::literals::chrono_literals::operator""_h(unsigned long long x) 107 | { 108 | return chrono::hours{x}; 109 | } 110 | 111 | inline BPSTD_INLINE_VISIBILITY constexpr 112 | std::chrono::duration> 113 | bpstd::literals::chrono_literals::operator""_h(long double x) 114 | { 115 | return chrono::duration>{x}; 116 | } 117 | 118 | inline BPSTD_INLINE_VISIBILITY constexpr 119 | bpstd::chrono::minutes 120 | bpstd::literals::chrono_literals::operator""_min(unsigned long long x) 121 | { 122 | return chrono::minutes{x}; 123 | } 124 | inline BPSTD_INLINE_VISIBILITY constexpr 125 | bpstd::chrono::duration> 126 | bpstd::literals::chrono_literals::operator""_min(long double x) 127 | { 128 | return chrono::duration>{x}; 129 | } 130 | 131 | inline BPSTD_INLINE_VISIBILITY constexpr 132 | bpstd::chrono::seconds 133 | bpstd::literals::chrono_literals::operator""_s(unsigned long long x) 134 | { 135 | return chrono::seconds{x}; 136 | } 137 | 138 | inline BPSTD_INLINE_VISIBILITY constexpr 139 | bpstd::chrono::duration 140 | bpstd::literals::chrono_literals::operator""_s(long double x) 141 | { 142 | return chrono::duration{x}; 143 | } 144 | 145 | inline BPSTD_INLINE_VISIBILITY constexpr 146 | bpstd::chrono::milliseconds 147 | bpstd::literals::chrono_literals::operator""_ms(unsigned long long x) 148 | { 149 | return chrono::milliseconds{x}; 150 | } 151 | 152 | inline BPSTD_INLINE_VISIBILITY constexpr 153 | bpstd::chrono::duration 154 | bpstd::literals::chrono_literals::operator""_ms(long double x) 155 | { 156 | return chrono::duration{x}; 157 | } 158 | 159 | inline BPSTD_INLINE_VISIBILITY constexpr 160 | bpstd::chrono::microseconds 161 | bpstd::literals::chrono_literals::operator ""_us(unsigned long long x) 162 | { 163 | return chrono::microseconds{x}; 164 | } 165 | 166 | inline BPSTD_INLINE_VISIBILITY constexpr 167 | bpstd::chrono::duration 168 | bpstd::literals::chrono_literals::operator""_us(long double x) 169 | { 170 | return chrono::duration{x}; 171 | } 172 | 173 | inline BPSTD_INLINE_VISIBILITY constexpr 174 | bpstd::chrono::nanoseconds 175 | bpstd::literals::chrono_literals::operator""_ns(unsigned long long x) 176 | { 177 | return chrono::nanoseconds{x}; 178 | } 179 | 180 | inline BPSTD_INLINE_VISIBILITY constexpr 181 | bpstd::chrono::duration 182 | bpstd::literals::chrono_literals::operator""_ns(long double x) 183 | { 184 | return chrono::duration{x}; 185 | } 186 | 187 | BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 188 | 189 | #endif /* BPSTD_CHRONO_HPP */ 190 | -------------------------------------------------------------------------------- /include/bpstd/detail/invoke.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// \file invoke.hpp 3 | /// 4 | /// \brief This internal header provides the definition of the INVOKE overload 5 | //////////////////////////////////////////////////////////////////////////////// 6 | 7 | /* 8 | The MIT License (MIT) 9 | 10 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | #ifndef BPSTD_DETAIL_INVOKE_HPP 31 | #define BPSTD_DETAIL_INVOKE_HPP 32 | 33 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) 34 | # pragma once 35 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 36 | 37 | #include "config.hpp" // BPSTD_INLINE_VISIBILITY 38 | #include "move.hpp" // forward 39 | #include // std::true_type, std::false_type, etc 40 | #include // std::reference_wrapper 41 | 42 | #include 43 | 44 | BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 45 | 46 | namespace bpstd { 47 | namespace detail { 48 | 49 | template 50 | struct is_reference_wrapper : std::false_type {}; 51 | 52 | template 53 | struct is_reference_wrapper> : std::true_type {}; 54 | 55 | template 56 | inline BPSTD_INLINE_VISIBILITY constexpr 57 | auto INVOKE(T Base::*pmf, Derived&& ref, Args&&... args) 58 | noexcept(noexcept((::bpstd::forward(ref).*pmf)(::bpstd::forward(args)...))) 59 | -> typename std::enable_if::value && 60 | std::is_base_of::type>::value, 61 | decltype((::bpstd::forward(ref).*pmf)(::bpstd::forward(args)...))>::type 62 | { 63 | return (bpstd::forward(ref).*pmf)(bpstd::forward(args)...); 64 | } 65 | 66 | template 67 | inline BPSTD_INLINE_VISIBILITY constexpr 68 | auto INVOKE(T Base::*pmf, RefWrap&& ref, Args&&... args) 69 | noexcept(noexcept((ref.get().*pmf)(std::forward(args)...))) 70 | -> typename std::enable_if::value && 71 | is_reference_wrapper::type>::value, 72 | decltype((ref.get().*pmf)(::bpstd::forward(args)...))>::type 73 | { 74 | return (ref.get().*pmf)(bpstd::forward(args)...); 75 | } 76 | 77 | template 78 | inline BPSTD_INLINE_VISIBILITY constexpr 79 | auto INVOKE(T Base::*pmf, Pointer&& ptr, Args&&... args) 80 | noexcept(noexcept(((*std::forward(ptr)).*pmf)(std::forward(args)...))) 81 | -> typename std::enable_if::value && 82 | !is_reference_wrapper::type>::value && 83 | !std::is_base_of::type>::value, 84 | decltype(((*::bpstd::forward(ptr)).*pmf)(::bpstd::forward(args)...))>::type 85 | { 86 | return ((*bpstd::forward(ptr)).*pmf)(bpstd::forward(args)...); 87 | } 88 | 89 | template 90 | inline BPSTD_INLINE_VISIBILITY constexpr 91 | auto INVOKE(T Base::*pmd, Derived&& ref) 92 | noexcept(noexcept(std::forward(ref).*pmd)) 93 | -> typename std::enable_if::value && 94 | std::is_base_of::type>::value, 95 | decltype(::bpstd::forward(ref).*pmd)>::type 96 | { 97 | return bpstd::forward(ref).*pmd; 98 | } 99 | 100 | template 101 | inline BPSTD_INLINE_VISIBILITY constexpr 102 | auto INVOKE(T Base::*pmd, RefWrap&& ref) 103 | noexcept(noexcept(ref.get().*pmd)) 104 | -> typename std::enable_if::value && 105 | is_reference_wrapper::type>::value, 106 | decltype(ref.get().*pmd)>::type 107 | { 108 | return ref.get().*pmd; 109 | } 110 | 111 | template 112 | inline BPSTD_INLINE_VISIBILITY constexpr 113 | auto INVOKE(T Base::*pmd, Pointer&& ptr) 114 | noexcept(noexcept((*std::forward(ptr)).*pmd)) 115 | -> typename std::enable_if::value && 116 | !is_reference_wrapper::type>::value && 117 | !std::is_base_of::type>::value, 118 | decltype((*::bpstd::forward(ptr)).*pmd)>::type 119 | { 120 | return (*bpstd::forward(ptr)).*pmd; 121 | } 122 | 123 | template 124 | inline BPSTD_INLINE_VISIBILITY constexpr 125 | auto INVOKE(F&& f, Args&&... args) 126 | noexcept(noexcept(std::forward(f)(std::forward(args)...))) 127 | -> typename std::enable_if::type>::value, 128 | decltype(::bpstd::forward(f)(::bpstd::forward(args)...))>::type 129 | { 130 | return bpstd::forward(f)(bpstd::forward(args)...); 131 | } 132 | 133 | //========================================================================== 134 | // is_nothrow_invocable 135 | //========================================================================== 136 | 137 | template 138 | struct is_nothrow_invocable 139 | { 140 | template 141 | static auto test( Fn2&&, Args2&&... ) 142 | -> decltype(INVOKE(std::declval(), std::declval()...), 143 | std::integral_constant(), std::declval()...))>{}); 144 | 145 | static auto test(...) 146 | -> std::false_type; 147 | 148 | using type = decltype(test(std::declval(), std::declval()...)); 149 | static constexpr bool value = type::value; 150 | }; 151 | 152 | //========================================================================== 153 | // is_invocable 154 | //========================================================================== 155 | 156 | template 157 | struct is_invocable 158 | { 159 | template 160 | static auto test( Fn2&&, Args2&&... ) 161 | -> decltype(INVOKE(std::declval(), std::declval()...), std::true_type{}); 162 | 163 | static auto test(...) 164 | -> std::false_type; 165 | 166 | using type = decltype(test(std::declval(), std::declval()...)); 167 | static constexpr bool value = type::value; 168 | }; 169 | 170 | // Used to SFINAE away non-invocable types 171 | template 172 | struct invoke_result_impl{}; 173 | 174 | template 175 | struct invoke_result_impl{ 176 | using type = decltype(INVOKE(std::declval(), std::declval()...)); 177 | }; 178 | 179 | template 180 | struct invoke_result 181 | : invoke_result_impl::value, Fn, Args...>{}; 182 | 183 | } // namespace detail 184 | } // namespace bpstd 185 | 186 | BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 187 | 188 | #endif /* BPSTD_DETAIL_INVOKE_HPP */ 189 | -------------------------------------------------------------------------------- /include/bpstd/exception.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// \file exception.hpp 3 | /// 4 | /// \brief This header provides definitions from the C++ header 5 | //////////////////////////////////////////////////////////////////////////////// 6 | 7 | /* 8 | The MIT License (MIT) 9 | 10 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | #ifndef BPSTD_EXCEPTION_HPP 31 | #define BPSTD_EXCEPTION_HPP 32 | 33 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) 34 | # pragma once 35 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 36 | 37 | #include "detail/config.hpp" 38 | 39 | #include 40 | 41 | BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 42 | 43 | // The large #if/endif block below, and the definition of 44 | // bpstd::uncaught_exceptions is taken from boost: 45 | // https://beta.boost.org/doc/libs/develop/boost/core/uncaught_exceptions.hpp 46 | 47 | // Copyright Andrey Semashev 2018. 48 | // Distributed under the Boost Software License, Version 1.0. 49 | // (See accompanying file LICENSE_1_0.txt or copy at 50 | // http://www.boost.org/LICENSE_1_0.txt) 51 | 52 | #if (__cplusplus >= 201703L && defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411) || \ 53 | defined(_MSC_VER) && _MSC_VER >= 1900 54 | # define BPSTD_HAS_UNCAUGHT_EXCEPTIONS 55 | #endif 56 | 57 | #if !defined(BPSTD_HAS_UNCAUGHT_EXCEPTIONS) 58 | 59 | // cxxabi.h availability macro 60 | # if defined(__has_include) 61 | # if __has_include() 62 | # define BPSTD_HAS_CXXABI_H 63 | # endif 64 | # elif defined(__GLIBCXX__) || defined(__GLIBCPP__) 65 | # define BPSTD_HAS_CXXABI_H 66 | # endif 67 | 68 | # if defined(BPSTD_HAS_CXXABI_H) 69 | // MinGW GCC 4.4 seem to not work the same way the newer GCC versions do. As 70 | // a result, __cxa_get_globals based implementation will always return 0. 71 | // Just disable it for now and fall back to std::uncaught_exception(). 72 | # if !(defined(__MINGW32__) && (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 405)) 73 | # include 74 | # include 75 | # define BPSTD_HAS_CXA_GET_GLOBALS 76 | 77 | // At least on MinGW and Linux, only GCC since 4.7 declares __cxa_get_globals() 78 | // in cxxabi.h. Older versions of GCC do not expose this function but it's 79 | // there. 80 | // On OpenBSD, it seems, the declaration is also missing. 81 | // Note that at least on FreeBSD 11, cxxabi.h declares __cxa_get_globals with 82 | // a different exception specification, so we can't declare the function 83 | // unconditionally. On Linux with clang and libc++ and on OS X, there is a 84 | // version of cxxabi.h from libc++abi that doesn't declare __cxa_get_globals, 85 | // but provides __cxa_uncaught_exceptions. 86 | // The function only appeared in version _LIBCPPABI_VERSION >= 1002 of the 87 | // library. Unfortunately, there are linking errors about undefined reference 88 | // to __cxa_uncaught_exceptions on Ubuntu Trusty and OS X, so we avoid using 89 | // it and forward-declare __cxa_get_globals instead. On QNX SDP 7.0 (QCC 5.4.0), 90 | // there are multiple cxxabi.h, one from glibcxx from gcc and another from 91 | // libc++abi from LLVM. Which one is included will be determined by the qcc 92 | // command line arguments (-V and/or -Y; 93 | // http://www.qnx.com/developers/docs/7.0.0/#com.qnx.doc.neutrino.utilities/topic/q/qcc.html 94 | // ). 95 | // The LLVM libc++abi is missing the declaration of __cxa_get_globals but it is 96 | // also patched by QNX developers to not define _LIBCPPABI_VERSION. Older QNX 97 | // SDP versions, up to and including 6.6, don't provide LLVM and libc++abi. 98 | // See https://github.com/boostorg/core/issues/59. 99 | # if !defined(__FreeBSD__) && \ 100 | ( \ 101 | (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407) || \ 102 | defined(__OpenBSD__) || \ 103 | (defined(__QNXNTO__) && !defined(__GLIBCXX__) && !defined(__GLIBCPP__)) || \ 104 | defined(_LIBCPPABI_VERSION) \ 105 | ) 106 | namespace __cxxabiv1 { 107 | struct __cxa_eh_globals; 108 | # if defined(__OpenBSD__) 109 | extern "C" __cxa_eh_globals* __cxa_get_globals(); 110 | # else 111 | extern "C" __cxa_eh_globals* __cxa_get_globals() noexcept __attribute__((__const__)); 112 | # endif 113 | } // namespace __cxxabiv1 114 | # endif 115 | # endif // !(defined(__MINGW32__) && (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 405)) 116 | # endif // defined(BPSTD_HAS_CXXABI_H) 117 | 118 | # if defined(_MSC_VER) && _MSC_VER >= 1400 119 | # include 120 | # define BPSTD_HAS_GETPTD 121 | namespace scope { 122 | namespace detail { 123 | extern "C" void* _getptd(); 124 | } // namespace detail 125 | } // namespace scope 126 | # endif // defined(_MSC_VER) && _MSC_VER >= 1400 127 | #endif // !defined(BPSTD_HAS_UNCAUGHT_EXCEPTIONS) 128 | 129 | #if !defined(BPSTD_HAS_UNCAUGHT_EXCEPTIONS) && \ 130 | !defined(BPSTD_HAS_CXA_GET_GLOBALS) && \ 131 | !defined(BPSTD_HAS_GETPTD) 132 | //! This macro is defined when `uncaught_exceptions` is not guaranteed to 133 | //! return values greater than 1 if multiple exceptions are pending 134 | # define BPSTD_UNCAUGHT_EXCEPTIONS_EMULATED 135 | #endif 136 | 137 | namespace bpstd { 138 | 139 | //============================================================================ 140 | // non-member functions 141 | //============================================================================ 142 | 143 | /// \brief Returns the number of exceptions currently in-flight in the current 144 | /// frame 145 | /// 146 | /// \return the number of exceptions 147 | int uncaught_exceptions() noexcept; 148 | 149 | } // namespace bpstd 150 | 151 | //============================================================================== 152 | // definitions : non-member functions 153 | //============================================================================== 154 | 155 | //------------------------------------------------------------------------------ 156 | // Utilities 157 | //------------------------------------------------------------------------------ 158 | 159 | inline BPSTD_INLINE_VISIBILITY 160 | int bpstd::uncaught_exceptions() 161 | noexcept 162 | { 163 | #if defined(BPSTD_HAS_UNCAUGHT_EXCEPTIONS) 164 | // C++17 implementation 165 | return std::uncaught_exceptions(); 166 | #elif defined(BPSTD_HAS_CXA_GET_GLOBALS) 167 | // Tested on {clang 3.2,GCC 3.5.6,GCC 4.1.2,GCC 4.4.6,GCC 4.4.7}x{x32,x64} 168 | using byte = unsigned char; 169 | auto count = int{}; 170 | const auto* ptr = reinterpret_cast(::abi::__cxa_get_globals()) + sizeof(void*); 171 | 172 | // __cxa_eh_globals::uncaughtExceptions, x32 offset - 0x4, x64 - 0x8 173 | std::memcpy(&count, ptr, sizeof(count)); 174 | return count; 175 | #elif defined(BPSTD_HAS_GETPTD) 176 | // MSVC specific. Tested on {MSVC2005SP1,MSVC2008SP1,MSVC2010SP1,MSVC2012}x{x32,x64}. 177 | using byte = unsigned char; 178 | auto count = int{}; 179 | 180 | const auto offset = (sizeof(void*) == 8u ? 0x100 : 0x90); 181 | const auto* ptr = static_cast(::scope::detail::_getptd()) + offset; 182 | 183 | // _tiddata::_ProcessingThrow, x32 offset - 0x90, x64 - 0x100 184 | std::memcpy(&count, ptr, sizeof(count)); 185 | return count; 186 | #else 187 | // Portable C++03 implementation. Does not allow to detect multiple 188 | // nested exceptions. 189 | 190 | // This is a buggy fallback since it will only work with 1 exception 191 | // in-flight, but we don't have any other options without exploiting 192 | // internal compiler features. 193 | return static_cast(std::uncaught_exception()); 194 | #endif 195 | } 196 | 197 | BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 198 | 199 | #endif /* BPSTD_EXCEPTION_HPP */ 200 | -------------------------------------------------------------------------------- /include/bpstd/detail/variant_base.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * \file variant_base.hpp 3 | * 4 | * \brief This internal header provides the definition of a utility for 5 | * variant, variant_base 6 | *****************************************************************************/ 7 | 8 | /* 9 | The MIT License (MIT) 10 | 11 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in 21 | all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | SOFTWARE. 30 | */ 31 | #ifndef BPSTD_DETAIL_VARIANT_BASE_HPP 32 | #define BPSTD_DETAIL_VARIANT_BASE_HPP 33 | 34 | #include "config.hpp" // BPSTD_CPP14_CONSTEXPR 35 | #include "variant_union.hpp" // detail::variant_union 36 | 37 | #include // std::size_t 38 | #include // std::forward 39 | 40 | BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 41 | 42 | namespace bpstd { 43 | namespace detail { 44 | 45 | //========================================================================== 46 | // class : variant_base 47 | //========================================================================== 48 | 49 | //////////////////////////////////////////////////////////////////////////// 50 | /// \brief The base class used by variant 51 | //////////////////////////////////////////////////////////////////////////// 52 | template 53 | class variant_base; 54 | 55 | //========================================================================== 56 | // class : variant_base 57 | //========================================================================== 58 | 59 | template 60 | class variant_base 61 | { 62 | //------------------------------------------------------------------------ 63 | // Constructors 64 | //------------------------------------------------------------------------ 65 | public: 66 | 67 | constexpr variant_base(); 68 | 69 | template 70 | constexpr variant_base(variant_index_tag, Args&&...args); 71 | 72 | //------------------------------------------------------------------------ 73 | // Protected Members 74 | //------------------------------------------------------------------------ 75 | protected: 76 | 77 | variant_union m_union; 78 | std::size_t m_index; 79 | 80 | //--------------------------------------------------------------------- 81 | // Protected Member Functions 82 | //--------------------------------------------------------------------- 83 | protected: 84 | 85 | void destroy_active_object(); 86 | }; 87 | 88 | //========================================================================== 89 | // class : variant_base 90 | //========================================================================== 91 | 92 | template 93 | class variant_base 94 | { 95 | public: 96 | 97 | constexpr variant_base(); 98 | 99 | template 100 | constexpr variant_base(variant_index_tag, Args&&...args); 101 | 102 | ~variant_base(); 103 | 104 | //--------------------------------------------------------------------- 105 | // Protected Members 106 | //--------------------------------------------------------------------- 107 | protected: 108 | 109 | variant_union m_union; 110 | std::size_t m_index; 111 | 112 | //--------------------------------------------------------------------- 113 | // Protected Member Functions 114 | //--------------------------------------------------------------------- 115 | protected: 116 | 117 | void destroy_active_object(); 118 | 119 | //--------------------------------------------------------------------- 120 | // Private Static Member Functions 121 | //--------------------------------------------------------------------- 122 | private: 123 | 124 | struct destroy_visitor 125 | { 126 | template 127 | inline BPSTD_INLINE_VISIBILITY 128 | void operator()(T& v) { 129 | v.~T(); 130 | } 131 | }; 132 | }; 133 | 134 | } // namespace detail 135 | } // namespace bpstd 136 | 137 | //============================================================================== 138 | // class : variant_base 139 | //============================================================================== 140 | 141 | //------------------------------------------------------------------------------ 142 | // Constructors 143 | //------------------------------------------------------------------------------ 144 | 145 | template 146 | inline BPSTD_INLINE_VISIBILITY constexpr 147 | bpstd::detail::variant_base::variant_base() 148 | : m_union{}, 149 | m_index{static_cast(-1)} 150 | { 151 | 152 | } 153 | 154 | template 155 | template 156 | inline BPSTD_INLINE_VISIBILITY constexpr 157 | bpstd::detail::variant_base::variant_base(variant_index_tag, 158 | Args&&...args) 159 | : m_union{variant_index_tag{}, std::forward(args)...}, 160 | m_index{N} 161 | { 162 | 163 | } 164 | 165 | //------------------------------------------------------------------------------ 166 | // Protected Members 167 | //------------------------------------------------------------------------------ 168 | 169 | template 170 | inline BPSTD_INLINE_VISIBILITY 171 | void bpstd::detail::variant_base::destroy_active_object() 172 | { 173 | m_index = static_cast(-1); 174 | } 175 | 176 | //============================================================================== 177 | // class : variant_base 178 | //============================================================================== 179 | 180 | //------------------------------------------------------------------------------ 181 | // Constructors / Destructor 182 | //------------------------------------------------------------------------------ 183 | 184 | template 185 | inline BPSTD_INLINE_VISIBILITY constexpr 186 | bpstd::detail::variant_base::variant_base() 187 | : m_union{}, 188 | m_index{static_cast(-1)} 189 | { 190 | 191 | } 192 | 193 | #if defined(_MSC_VER) 194 | # pragma warning(push) 195 | # pragma warning(disable:4702) 196 | #endif 197 | 198 | template 199 | template 200 | inline BPSTD_INLINE_VISIBILITY constexpr 201 | bpstd::detail::variant_base::variant_base(variant_index_tag, 202 | Args&&...args) 203 | : m_union{variant_index_tag{}, std::forward(args)...}, 204 | m_index{N} 205 | { 206 | 207 | } 208 | 209 | #if defined(_MSC_VER) 210 | # pragma warning(pop) 211 | #endif 212 | 213 | //------------------------------------------------------------------------------ 214 | 215 | template 216 | inline BPSTD_INLINE_VISIBILITY 217 | bpstd::detail::variant_base::~variant_base() 218 | { 219 | destroy_active_object(); 220 | } 221 | 222 | //------------------------------------------------------------------------------ 223 | // Protected Members 224 | //------------------------------------------------------------------------------ 225 | 226 | template 227 | inline BPSTD_INLINE_VISIBILITY 228 | void bpstd::detail::variant_base::destroy_active_object() 229 | { 230 | if (m_index == static_cast(-1)) { 231 | return; 232 | } 233 | 234 | visit_union(m_index, destroy_visitor{}, m_union); 235 | m_index = static_cast(-1); 236 | } 237 | 238 | BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 239 | 240 | #endif /* BPSTD_DETAIL_VARIANT_BASE_HPP */ 241 | -------------------------------------------------------------------------------- /include/bpstd/memory.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// \file memory.hpp 3 | /// 4 | /// \brief This header provides definitions from the C++ header 5 | //////////////////////////////////////////////////////////////////////////////// 6 | 7 | /* 8 | The MIT License (MIT) 9 | 10 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | #ifndef BPSTD_MEMORY_HPP 31 | #define BPSTD_MEMORY_HPP 32 | 33 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) 34 | # pragma once 35 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 36 | 37 | #include "detail/config.hpp" 38 | #include "type_traits.hpp" // conditional_t, void_t 39 | #include "utility.hpp" // forward 40 | 41 | #include // std::unique_ptr 42 | #include // std::size_t 43 | #include // std::declval 44 | 45 | BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 46 | 47 | namespace bpstd { 48 | 49 | namespace detail { 50 | template 51 | struct make_unique_result 52 | { 53 | using object = T; 54 | }; 55 | template 56 | struct make_unique_result 57 | { 58 | using unbounded_array = T[]; 59 | }; 60 | template 61 | struct make_unique_result 62 | { 63 | using bounded_array = T[N]; 64 | }; 65 | } 66 | 67 | /// \brief Constructs an object of type T and wraps it in a std::unique_ptr 68 | /// 69 | /// Constructs a non-array type T. The arguments args are passed to the 70 | /// constructor of T. This overload only participates in overload resolution 71 | /// if T is not an array type. 72 | /// 73 | /// \tparam T the type to construct 74 | /// \param args the arguments to forward to T's constructor 75 | /// \return the unique_ptr 76 | template 77 | std::unique_ptr::object> 78 | make_unique(Args&&...args); 79 | 80 | /// \brief Constructs an object of type T[] and wraps it in a std::unique_ptr 81 | /// 82 | /// Constructs an array of unknown bound T. This overload only participates 83 | /// in overload resolution if T is an array of unknown bound. 84 | /// 85 | /// \tparam T the type to construct 86 | /// \param size the size of the array 87 | /// \return the unique_ptr 88 | template 89 | std::unique_ptr::unbounded_array> 90 | make_unique(std::size_t size); 91 | 92 | // Construction of arrays of known bound is disallowed 93 | template 94 | std::unique_ptr::bounded_array> 95 | make_unique() = delete; 96 | 97 | /// \brief Constructs an object of type T through default-initialization 98 | /// and wraps it in a std::unique_ptr 99 | /// 100 | /// Constructs a non-array type T. This overload only participates in 101 | /// overload resolution if T is not an array type. The object is 102 | /// default-initialised, which may mean it will need to be overwritten before 103 | /// it is legal to be read 104 | /// 105 | /// \tparam T the type to construct 106 | /// \return the unique_ptr 107 | template 108 | std::unique_ptr::object> 109 | make_unique_for_overwrite(); 110 | 111 | /// \brief Constructs an object of type T[] through default-initialization 112 | /// and wraps it in a std::unique_ptr 113 | /// 114 | /// Constructs an array of unknown bound T. This overload only participates 115 | /// in overload resolution if T is an array of unknown bound. The array is 116 | /// default-initialised, which may mean it will need to be overwritten before 117 | /// it is legal to be read 118 | /// 119 | /// \tparam T the type to construct 120 | /// \return the unique_ptr 121 | template 122 | std::unique_ptr::unbounded_array> 123 | make_unique_for_overwrite(std::size_t size); 124 | 125 | // Construction of arrays of known bound is disallowed 126 | template 127 | std::unique_ptr::bounded_array> 128 | make_unique_for_overwrite() = delete; 129 | 130 | //---------------------------------------------------------------------------- 131 | 132 | namespace detail { 133 | 134 | template 135 | struct has_to_address : false_type{}; 136 | 137 | template 138 | struct has_to_address::to_address(std::declval()))>> 139 | : true_type{}; 140 | 141 | //-------------------------------------------------------------------------- 142 | 143 | template 144 | struct operator_deref 145 | { 146 | using type = decltype(std::declval().operator->()); 147 | }; 148 | 149 | template 150 | struct operator_deref{}; 151 | 152 | //-------------------------------------------------------------------------- 153 | 154 | template 155 | struct to_address_result 156 | : operator_deref>::value, T>{}; 157 | 158 | template 159 | struct to_address_result::to_address(std::declval()))>> 160 | { 161 | using type = decltype(std::pointer_traits::to_address(std::declval())); 162 | }; 163 | 164 | template 165 | using to_address_result_t = typename to_address_result::type; 166 | 167 | } // namespace detail 168 | 169 | /// \{ 170 | /// \brief Converts a pointer-like type to a raw pointer by recursively 171 | /// calling to_address on it 172 | /// 173 | /// \param p the pointer-like type 174 | /// \return the pointer 175 | template 176 | constexpr T* to_address(T* p) noexcept; 177 | template 178 | constexpr detail::to_address_result_t to_address(const T& p) noexcept; 179 | /// \} 180 | 181 | } // namespace bpstd 182 | 183 | template 184 | inline BPSTD_INLINE_VISIBILITY 185 | std::unique_ptr::object> 186 | bpstd::make_unique(Args&&...args) 187 | { 188 | return std::unique_ptr{new T(bpstd::forward(args)...)}; 189 | } 190 | 191 | template 192 | inline BPSTD_INLINE_VISIBILITY 193 | std::unique_ptr::unbounded_array> 194 | bpstd::make_unique(std::size_t size) 195 | { 196 | return std::unique_ptr{new remove_extent_t[size]()}; 197 | } 198 | 199 | template 200 | inline BPSTD_INLINE_VISIBILITY 201 | std::unique_ptr::object> 202 | bpstd::make_unique_for_overwrite() 203 | { 204 | return std::unique_ptr{new T}; 205 | } 206 | 207 | template 208 | inline BPSTD_INLINE_VISIBILITY 209 | std::unique_ptr::unbounded_array> 210 | bpstd::make_unique_for_overwrite(std::size_t size) 211 | { 212 | return std::unique_ptr{new remove_extent_t[size]}; 213 | } 214 | 215 | namespace bpstd { 216 | namespace detail { 217 | 218 | template 219 | inline BPSTD_INLINE_VISIBILITY constexpr 220 | auto to_address_impl(const T& p, std::true_type) 221 | -> decltype(std::pointer_traits::to_address(std::declval())) 222 | { 223 | return to_address(std::pointer_traits::to_address(p)); 224 | } 225 | 226 | template 227 | inline BPSTD_INLINE_VISIBILITY constexpr 228 | auto to_address_impl(const T& p, std::false_type) 229 | -> decltype(std::declval().operator->()) 230 | { 231 | return to_address(p.operator->()); 232 | } 233 | 234 | } // namespace detail 235 | } // namespace bpstd 236 | 237 | template 238 | inline BPSTD_INLINE_VISIBILITY constexpr 239 | T* bpstd::to_address(T* p) 240 | noexcept 241 | { 242 | static_assert( 243 | !std::is_function::value, 244 | "T* must not be a function pointer" 245 | ); 246 | 247 | return p; 248 | } 249 | 250 | template 251 | inline BPSTD_INLINE_VISIBILITY constexpr 252 | bpstd::detail::to_address_result_t 253 | bpstd::to_address(const T& p) 254 | noexcept 255 | { 256 | return detail::to_address_impl(p, detail::has_to_address{}); 257 | } 258 | 259 | BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 260 | 261 | #endif /* BPSTD_MEMORY_HPP */ 262 | -------------------------------------------------------------------------------- /include/bpstd/cstddef.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// \file cstddef.hpp 3 | /// 4 | /// \brief This header provides definitions from the C++ header 5 | //////////////////////////////////////////////////////////////////////////////// 6 | 7 | /* 8 | The MIT License (MIT) 9 | 10 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | #ifndef BPSTD_CSTDDEF_HPP 31 | #define BPSTD_CSTDDEF_HPP 32 | 33 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) 34 | # pragma once 35 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 36 | 37 | #include "detail/config.hpp" 38 | #include "type_traits.hpp" 39 | 40 | #include // std::is_integral 41 | #include // __cpp_lib_byte, and to proxy API 42 | 43 | BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 44 | 45 | // The below implementation is based on GSL's implementation of 'gsl::byte' 46 | 47 | // VS2017 15.8 added support for the __cpp_lib_byte definition 48 | // To do: drop _HAS_STD_BYTE when support for pre 15.8 expires 49 | #if defined(_MSC_VER) 50 | 51 | // Turn MSVC /analyze rules that generate too much noise. 52 | # pragma warning(push) 53 | # pragma warning(disable : 26493) // don't use c-style cast 54 | 55 | # if !defined(BPSTD_USE_STD_BYTE) 56 | // this tests if we are under MSVC and the standard lib has std::byte and it is 57 | // enabled 58 | # if defined(_HAS_STD_BYTE) && _HAS_STD_BYTE 59 | # define BPSTD_USE_STD_BYTE 1 60 | # elif defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603 61 | # define BPSTD_USE_STD_BYTE 1 62 | # else 63 | # define BPSTD_USE_STD_BYTE 0 64 | # endif 65 | # endif // BPSTD_USE_STD_BYTE 66 | #endif // _MSC_VER 67 | 68 | #if !defined(BPSTD_USE_STD_BYTE) 69 | 70 | // this tests if we are under GCC or Clang with enough -std:c++1z power to get us std::byte 71 | // also check if libc++ version is sufficient (> 5.0) or libstc++ actually contains std::byte 72 | # if defined(__cplusplus) && (__cplusplus >= 201703L) && \ 73 | (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \ 74 | defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) 75 | # define BPSTD_USE_STD_BYTE 1 76 | # else 77 | # define BPSTD_USE_STD_BYTE 0 78 | # endif 79 | #endif // BPSTD_USE_STD_BYTE 80 | 81 | namespace bpstd { 82 | 83 | #if BPSTD_USE_STD_BYTE 84 | using std::byte; 85 | #else 86 | enum class BPSTD_MAY_ALIAS byte : unsigned char {}; 87 | 88 | //============================================================================ 89 | // non-member functions : enum lass : byte 90 | //============================================================================ 91 | 92 | //---------------------------------------------------------------------------- 93 | // Bitwise operators 94 | //---------------------------------------------------------------------------- 95 | 96 | template ::value>> 98 | constexpr byte operator<<(byte b, Integer shift) noexcept; 99 | template ::value>> 101 | constexpr byte operator>>(byte b, Integer shift) noexcept; 102 | 103 | constexpr byte operator|(byte lhs, byte rhs) noexcept; 104 | constexpr byte operator&(byte lhs, byte rhs) noexcept; 105 | constexpr byte operator^(byte lhs, byte rhs) noexcept; 106 | constexpr byte operator~(byte b) noexcept; 107 | 108 | //---------------------------------------------------------------------------- 109 | // Compound Bitwise Operators 110 | //---------------------------------------------------------------------------- 111 | 112 | template ::value>> 114 | BPSTD_CPP14_CONSTEXPR byte& operator<<=(byte& b, Integer shift) noexcept; 115 | template ::value>> 117 | BPSTD_CPP14_CONSTEXPR byte& operator>>=(byte& b, Integer shift) noexcept; 118 | BPSTD_CPP14_CONSTEXPR byte& operator|=(byte& lhs, byte rhs) noexcept; 119 | BPSTD_CPP14_CONSTEXPR byte& operator&=(byte& lhs, byte rhs) noexcept; 120 | 121 | BPSTD_CPP14_CONSTEXPR byte& operator^=(byte& lhs, byte rhs) noexcept; 122 | 123 | #endif 124 | 125 | //---------------------------------------------------------------------------- 126 | // Utilities 127 | //---------------------------------------------------------------------------- 128 | 129 | template ::value>> 131 | constexpr Integer to_integer(byte b) noexcept; 132 | 133 | } // namespace bpstd 134 | 135 | //============================================================================== 136 | // definitions : non-member functions : enum class : byte 137 | //============================================================================== 138 | 139 | #if !BPSTD_USE_STD_BYTE 140 | 141 | //------------------------------------------------------------------------------ 142 | // Bitwise Operators 143 | //------------------------------------------------------------------------------ 144 | 145 | template 146 | inline BPSTD_INLINE_VISIBILITY constexpr 147 | bpstd::byte bpstd::operator<<(byte b, Integer shift) 148 | noexcept 149 | { 150 | return static_cast(static_cast(b) << shift); 151 | } 152 | 153 | template 154 | inline BPSTD_INLINE_VISIBILITY constexpr 155 | bpstd::byte bpstd::operator>>(byte b, Integer shift) 156 | noexcept 157 | { 158 | return static_cast(static_cast(b) >> shift); 159 | } 160 | 161 | inline BPSTD_INLINE_VISIBILITY constexpr 162 | bpstd::byte bpstd::operator|(byte lhs, byte rhs) 163 | noexcept 164 | { 165 | return static_cast( 166 | static_cast(lhs) | static_cast(rhs) 167 | ); 168 | } 169 | 170 | inline BPSTD_INLINE_VISIBILITY constexpr 171 | bpstd::byte bpstd::operator&(byte lhs, byte rhs) 172 | noexcept 173 | { 174 | return static_cast( 175 | static_cast(lhs) & static_cast(rhs) 176 | ); 177 | } 178 | 179 | inline BPSTD_INLINE_VISIBILITY constexpr 180 | bpstd::byte bpstd::operator^(byte lhs, byte rhs) 181 | noexcept 182 | { 183 | return static_cast( 184 | static_cast(lhs) ^ static_cast(rhs) 185 | ); 186 | } 187 | 188 | inline BPSTD_INLINE_VISIBILITY constexpr 189 | bpstd::byte bpstd::operator~(byte b) 190 | noexcept 191 | { 192 | return static_cast(~static_cast(b)); 193 | } 194 | 195 | //------------------------------------------------------------------------------ 196 | // Compound Bitwise Operators 197 | //------------------------------------------------------------------------------ 198 | 199 | template 200 | inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR 201 | bpstd::byte& bpstd::operator<<=(byte& b, Integer shift) 202 | noexcept 203 | { 204 | return b = static_cast(static_cast(b) << shift); 205 | } 206 | 207 | template 208 | inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR 209 | bpstd::byte& bpstd::operator>>=(byte& b, Integer shift) 210 | noexcept 211 | { 212 | return b = static_cast(static_cast(b) >> shift); 213 | } 214 | 215 | inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR 216 | bpstd::byte& bpstd::operator|=(byte& lhs, byte rhs) 217 | noexcept 218 | { 219 | return lhs = static_cast( 220 | static_cast(lhs) | static_cast(rhs) 221 | ); 222 | } 223 | 224 | inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR 225 | bpstd::byte& bpstd::operator&=(byte& lhs, byte rhs) 226 | noexcept 227 | { 228 | return lhs = static_cast( 229 | static_cast(lhs) & static_cast(rhs) 230 | ); 231 | } 232 | 233 | inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR 234 | bpstd::byte& bpstd::operator^=(byte& lhs, byte rhs) 235 | noexcept 236 | { 237 | return lhs = static_cast( 238 | static_cast(lhs) ^ static_cast(rhs) 239 | ); 240 | } 241 | 242 | #endif // BPSTD_USE_STD_BYTE 243 | 244 | //------------------------------------------------------------------------------ 245 | // Utilities 246 | //------------------------------------------------------------------------------ 247 | 248 | template 249 | inline BPSTD_INLINE_VISIBILITY constexpr 250 | Integer bpstd::to_integer(byte b) 251 | noexcept 252 | { 253 | return static_cast(b); 254 | } 255 | 256 | BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 257 | 258 | #endif /* BPSTD_CSTDDEF_HPP */ 259 | -------------------------------------------------------------------------------- /include/bpstd/iterator.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// \file iterator.hpp 3 | /// 4 | /// \brief This header provides definitions from the C++ header 5 | //////////////////////////////////////////////////////////////////////////////// 6 | 7 | /* 8 | The MIT License (MIT) 9 | 10 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | #ifndef BPSTD_ITERATOR_HPP 31 | #define BPSTD_ITERATOR_HPP 32 | 33 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) 34 | # pragma once 35 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 36 | 37 | #include "detail/config.hpp" 38 | #include "type_traits.hpp" // common_type_t 39 | 40 | #include 41 | #include // std::size_t 42 | #include 43 | 44 | BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 45 | 46 | namespace bpstd { 47 | 48 | //============================================================================ 49 | // class : reverse_iterator 50 | //============================================================================ 51 | 52 | template 53 | using reverse_iterator = std::reverse_iterator; 54 | 55 | //============================================================================ 56 | // non-member functions : class : reverse_iterator 57 | //============================================================================ 58 | 59 | /// \brief Makes a reverse_iterator given an iterator \p i 60 | /// 61 | /// This is a convenience function template that constructs a 62 | /// reverse_iterator for the given iterator \p i with the type deduced from 63 | /// the type of the argument. 64 | /// 65 | /// \param i the iterator 66 | /// \return the reverse_iterator 67 | template 68 | constexpr reverse_iterator make_reverse_iterator(Iterator i); 69 | 70 | //============================================================================ 71 | // non-member functions 72 | //============================================================================ 73 | 74 | /// \{ 75 | /// \brief Gets a pointer to the data from \p c 76 | /// 77 | /// \param c the container to get the data pointe rrom 78 | /// \return a pointer to the data 79 | template 80 | constexpr auto data(C& c) -> decltype(c.data()); 81 | template 82 | constexpr auto data(const C& c) -> decltype(c.data()); 83 | /// \} 84 | 85 | /// \brief Gets a pointer to the start of an array 86 | /// 87 | /// \param array the array to get the pointer to 88 | /// \return a pointer to the data 89 | template 90 | constexpr T* data(T (&array)[N]) noexcept; 91 | 92 | /// \brief Gets a pointer to the start of an initializer list 93 | /// 94 | /// \param il the initializer list 95 | /// \return a pointer to the start of the initializer list 96 | template 97 | constexpr const E* data(std::initializer_list il) noexcept; 98 | 99 | //---------------------------------------------------------------------------- 100 | 101 | /// \brief Queries whether \p c is empty 102 | /// 103 | /// \param c the container to query 104 | /// \return true if \p is empty 105 | template 106 | constexpr auto empty(const C& c) -> decltype(c.empty()); 107 | 108 | /// \brief Queries whether the array is empty 109 | /// 110 | /// \param array the array to check 111 | /// \return true if N is 0 112 | template 113 | constexpr bool empty(const T (&array)[N]) noexcept; 114 | 115 | /// \brief Queries whether an initializer list is empty 116 | /// 117 | /// \param il the initializer list to check 118 | /// \return true if \p il is empty 119 | template 120 | constexpr bool empty(std::initializer_list il) noexcept; 121 | 122 | //---------------------------------------------------------------------------- 123 | 124 | /// \brief Gets the size of a container 125 | /// 126 | /// \param c the container to check 127 | /// \return the container's size 128 | template 129 | constexpr auto size(const C& c) -> decltype(c.size()); 130 | 131 | /// \brief Gets the size of an array 132 | /// 133 | /// \param array the array to get the size from 134 | /// \return the size of an array 135 | template 136 | constexpr std::size_t size(const T (&array)[N]) noexcept; 137 | 138 | //---------------------------------------------------------------------------- 139 | 140 | /// \brief Gets the signed-size of a container 141 | /// 142 | /// \param c the container to get the size from 143 | /// \return the size of the container 144 | template 145 | constexpr auto ssize(const C& c) 146 | -> common_type_t>; 147 | 148 | /// \brief Gets the signed size of an array 149 | /// 150 | /// \param array the array to get the size from 151 | /// \return the size of an array 152 | template 153 | constexpr std::ptrdiff_t ssize(const T (&array)[N]) noexcept; 154 | 155 | } // namespace bpstd 156 | 157 | //============================================================================== 158 | // non-member functions : class : reverse_iterator 159 | //============================================================================== 160 | 161 | //------------------------------------------------------------------------------ 162 | // Utilities 163 | //------------------------------------------------------------------------------ 164 | 165 | template 166 | inline BPSTD_INLINE_VISIBILITY constexpr 167 | bpstd::reverse_iterator 168 | bpstd::make_reverse_iterator(Iterator i) 169 | { 170 | return reverse_iterator{i}; 171 | } 172 | 173 | //============================================================================== 174 | // non-member functions 175 | //============================================================================== 176 | 177 | //------------------------------------------------------------------------------ 178 | // Utilities 179 | //------------------------------------------------------------------------------ 180 | 181 | template 182 | inline BPSTD_INLINE_VISIBILITY constexpr 183 | auto bpstd::data(C& c) 184 | -> decltype(c.data()) 185 | { 186 | return c.data(); 187 | } 188 | 189 | template 190 | inline BPSTD_INLINE_VISIBILITY constexpr 191 | auto bpstd::data(const C& c) 192 | -> decltype(c.data()) 193 | { 194 | return c.data(); 195 | } 196 | template 197 | inline BPSTD_INLINE_VISIBILITY constexpr 198 | T* bpstd::data(T (&array)[N]) 199 | noexcept 200 | { 201 | return array; 202 | } 203 | 204 | template 205 | inline BPSTD_INLINE_VISIBILITY constexpr 206 | const E* bpstd::data(std::initializer_list il) 207 | noexcept 208 | { 209 | return il.begin(); 210 | } 211 | 212 | //------------------------------------------------------------------------------ 213 | 214 | template 215 | inline BPSTD_INLINE_VISIBILITY constexpr 216 | auto bpstd::empty(const C& c) 217 | -> decltype(c.empty()) 218 | { 219 | return c.empty(); 220 | } 221 | 222 | template 223 | inline BPSTD_INLINE_VISIBILITY constexpr 224 | bool bpstd::empty(const T (&)[N]) 225 | noexcept 226 | { 227 | return N == 0; 228 | } 229 | 230 | template 231 | inline BPSTD_INLINE_VISIBILITY constexpr 232 | bool bpstd::empty(std::initializer_list il) 233 | noexcept 234 | { 235 | return il.begin() == il.end(); 236 | } 237 | 238 | //------------------------------------------------------------------------------ 239 | 240 | template 241 | inline BPSTD_INLINE_VISIBILITY constexpr 242 | auto bpstd::size(const C& c) 243 | -> decltype(c.size()) 244 | { 245 | return c.size(); 246 | } 247 | 248 | template 249 | inline BPSTD_INLINE_VISIBILITY constexpr 250 | std::size_t bpstd::size(const T (&)[N]) 251 | noexcept 252 | { 253 | return N; 254 | } 255 | 256 | //------------------------------------------------------------------------------ 257 | 258 | template 259 | inline BPSTD_INLINE_VISIBILITY constexpr 260 | auto bpstd::ssize(const C& c) 261 | -> bpstd::common_type_t> 262 | { 263 | using type = bpstd::common_type_t>; 264 | 265 | return static_cast(c.size()); 266 | } 267 | 268 | template 269 | inline BPSTD_INLINE_VISIBILITY constexpr 270 | std::ptrdiff_t bpstd::ssize(const T (&)[N]) 271 | noexcept 272 | { 273 | return N; 274 | } 275 | 276 | BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 277 | 278 | #endif /* BPSTD_ITERATOR_HPP */ 279 | -------------------------------------------------------------------------------- /include/bpstd/tuple.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// \file tuple.hpp 3 | /// 4 | /// \brief This header provides definitions from the C++ header 5 | //////////////////////////////////////////////////////////////////////////////// 6 | 7 | /* 8 | The MIT License (MIT) 9 | 10 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | #ifndef BPSTD_TUPLE_HPP 31 | #define BPSTD_TUPLE_HPP 32 | 33 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) 34 | # pragma once 35 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 36 | 37 | #include "type_traits.hpp" // invoke_result 38 | #include "utility.hpp" // index_sequence, forward 39 | #include "functional.hpp" // invoke 40 | 41 | #include // std::tuple_element, and to proxy API 42 | #include // std::size_t 43 | 44 | BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 45 | 46 | namespace bpstd { 47 | 48 | //============================================================================ 49 | // class : tuple 50 | //============================================================================ 51 | 52 | template 53 | using tuple = std::tuple; 54 | 55 | //============================================================================ 56 | // utilities : tuple 57 | //============================================================================ 58 | 59 | template 60 | using tuple_element = std::tuple_element; 61 | 62 | template 63 | using tuple_element_t = typename tuple_element::type; 64 | 65 | //---------------------------------------------------------------------------- 66 | 67 | template 68 | using tuple_size = std::tuple_size; 69 | 70 | #if BPSTD_HAS_TEMPLATE_VARIABLES 71 | template 72 | BPSTD_CPP17_INLINE constexpr auto tuple_size_v = tuple_size::value; 73 | #endif 74 | 75 | //============================================================================ 76 | // non-member functions : class : tuple 77 | //============================================================================ 78 | 79 | //---------------------------------------------------------------------------- 80 | // Utilities 81 | //---------------------------------------------------------------------------- 82 | 83 | namespace detail { 84 | template 85 | struct is_tuple : false_type{}; 86 | 87 | template 88 | struct is_tuple> : true_type{}; 89 | } // namespace detail 90 | 91 | template >::value && is_lvalue_reference::value>> 93 | inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR 94 | tuple_element_t>& 95 | get(Tuple&& t) noexcept 96 | { 97 | return std::get(t); 98 | } 99 | 100 | template >::value && !is_lvalue_reference::value>> 102 | inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR 103 | tuple_element_t>&& 104 | get(Tuple&& t) noexcept 105 | { 106 | return bpstd::move(std::get(t)); 107 | } 108 | 109 | template 110 | BPSTD_CPP14_CONSTEXPR T& get(tuple& t) noexcept; 111 | template 112 | BPSTD_CPP14_CONSTEXPR T&& get(tuple&& t) noexcept; 113 | template 114 | BPSTD_CPP14_CONSTEXPR const T& get(const tuple& t) noexcept; 115 | template 116 | BPSTD_CPP14_CONSTEXPR const T&& get(const tuple&& t) noexcept; 117 | 118 | //---------------------------------------------------------------------------- 119 | 120 | namespace detail { 121 | 122 | // primary template left undefined 123 | template 124 | struct apply_result_impl; 125 | 126 | template 127 | struct apply_result_impl, Tuple> 128 | : invoke_result...>{}; 129 | 130 | template 131 | struct apply_result : apply_result_impl< 132 | Fn, 133 | make_index_sequence>::value>, 134 | Tuple 135 | >{}; 136 | 137 | template 138 | using apply_result_t = typename apply_result::type; 139 | } // namespace detail 140 | 141 | /// \brief Invokes the function \p fn using the arguments in \p tuple 142 | /// 143 | /// This invokes \p fn as if it were a call to bpstd::invoke using the 144 | /// arguments in \p tuple 145 | /// 146 | /// \param fn the function to invoke 147 | /// \param tuple the tuple of arguments to pass to fn 148 | /// \return the result from \p fn 149 | template 150 | constexpr detail::apply_result_t apply(Fn&& fn, Tuple&& tuple); 151 | 152 | /// \brief Constructs a type \p T using the arguments in \p tuple 153 | /// 154 | /// \tparam T the type to construct 155 | /// \param tuple the tuple of arguments to pass to T's constructor 156 | template 157 | constexpr T make_from_tuple(Tuple&& tuple); 158 | 159 | } // namespace bpstd 160 | 161 | //============================================================================== 162 | // definitions : non-member functions : class : tuple 163 | //============================================================================== 164 | 165 | //------------------------------------------------------------------------------ 166 | // Utilities 167 | //------------------------------------------------------------------------------ 168 | 169 | namespace bpstd { namespace detail { 170 | 171 | template 172 | struct index_of_impl; 173 | 174 | template 175 | struct index_of_impl 176 | : index_of_impl{}; 177 | 178 | template 179 | struct index_of_impl 180 | : integral_constant{}; 181 | 182 | template 183 | struct index_of : index_of_impl{}; 184 | 185 | }} // namespace bpstd::detail 186 | 187 | template 188 | inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR 189 | T& bpstd::get(tuple& t) 190 | noexcept 191 | { 192 | return std::get::value>(t); 193 | } 194 | 195 | template 196 | inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR 197 | T&& bpstd::get(tuple&& t) 198 | noexcept 199 | { 200 | return move(std::get::value>(t)); 201 | } 202 | 203 | template 204 | inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR 205 | const T& bpstd::get(const tuple& t) 206 | noexcept 207 | { 208 | return std::get::value>(t); 209 | } 210 | 211 | template 212 | inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR 213 | const T&& bpstd::get(const tuple&& t) 214 | noexcept 215 | { 216 | return move(std::get::value>(t)); 217 | } 218 | 219 | //============================================================================== 220 | // definition : apply 221 | //============================================================================== 222 | 223 | #if defined(_MSC_VER) 224 | # pragma warning(push) 225 | # pragma warning(disable:4100) // MSVC warns that 'tuple' is not used below 226 | #endif 227 | 228 | namespace bpstd { 229 | namespace detail { 230 | template 231 | inline BPSTD_INLINE_VISIBILITY constexpr 232 | apply_result_t apply_impl(Fn&& fn, Tuple&& tuple, index_sequence) 233 | { 234 | return ::bpstd::invoke( 235 | bpstd::forward(fn), 236 | std::get(bpstd::forward(tuple))... 237 | ); 238 | } 239 | } // namespace detail 240 | } // namespace bpstd 241 | 242 | #if defined(_MSC_VER) 243 | # pragma warning(pop) 244 | #endif 245 | 246 | template 247 | inline BPSTD_INLINE_VISIBILITY constexpr 248 | bpstd::detail::apply_result_t bpstd::apply(Fn&& fn, Tuple&& tuple) 249 | { 250 | return detail::apply_impl( 251 | bpstd::forward(fn), 252 | bpstd::forward(tuple), 253 | make_index_sequence>::value>{} 254 | ); 255 | } 256 | 257 | //============================================================================== 258 | // definition : make_from_tuple 259 | //============================================================================== 260 | 261 | #if defined(_MSC_VER) 262 | # pragma warning(push) 263 | # pragma warning(disable:4100) // MSVC warns that 'tuple' is not used below 264 | #endif 265 | 266 | namespace bpstd { 267 | namespace detail { 268 | template 269 | inline BPSTD_INLINE_VISIBILITY constexpr 270 | T make_from_tuple_impl(Tuple&& tuple, index_sequence) 271 | { 272 | return T(std::get(bpstd::forward(tuple))...); 273 | } 274 | } // namespace detail 275 | } // namespace bpstd 276 | 277 | #if defined(_MSC_VER) 278 | # pragma warning(pop) 279 | #endif 280 | 281 | template 282 | inline BPSTD_INLINE_VISIBILITY constexpr 283 | T bpstd::make_from_tuple(Tuple&& tuple) 284 | { 285 | return detail::make_from_tuple_impl( 286 | bpstd::forward(tuple), 287 | make_index_sequence>::value>{} 288 | ); 289 | } 290 | 291 | BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 292 | 293 | #endif /* BPSTD_TUPLE_HPP */ 294 | -------------------------------------------------------------------------------- /include/bpstd/utility.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// \file utility.hpp 3 | /// 4 | /// \brief This header provides definitions from the C++ header 5 | //////////////////////////////////////////////////////////////////////////////// 6 | 7 | /* 8 | The MIT License (MIT) 9 | 10 | Copyright (c) 2020 Matthew Rodusek All rights reserved. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | #ifndef BPSTD_UTILITY_HPP 31 | #define BPSTD_UTILITY_HPP 32 | 33 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) 34 | # pragma once 35 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 36 | 37 | #include "detail/config.hpp" 38 | #include "detail/move.hpp" // IWYU pragma: export 39 | #include "type_traits.hpp" // add_const_t 40 | 41 | #include // to proxy the API 42 | #include // std::size_t 43 | 44 | BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE 45 | 46 | namespace bpstd { 47 | 48 | //============================================================================ 49 | // struct : in_place_t 50 | //============================================================================ 51 | 52 | /// \brief This function is a special disambiguation tag for variadic 53 | /// functions, used in any and optional 54 | /// 55 | /// \note Calling this function results in undefined behaviour. 56 | struct in_place_t 57 | { 58 | explicit in_place_t() = default; 59 | }; 60 | BPSTD_CPP17_INLINE constexpr in_place_t in_place{}; 61 | 62 | //============================================================================ 63 | // in_place_type_t 64 | //============================================================================ 65 | 66 | /// \brief This function is a special disambiguation tag for variadic 67 | /// functions, used in any and optional 68 | /// 69 | /// \note Calling this function results in undefined behaviour. 70 | template 71 | struct in_place_type_t 72 | { 73 | explicit in_place_type_t() = default; 74 | }; 75 | 76 | #if BPSTD_HAS_TEMPLATE_VARIABLES 77 | template 78 | BPSTD_CPP17_INLINE constexpr in_place_type_t in_place_type{}; 79 | #endif 80 | 81 | //============================================================================ 82 | // in_place_index_t 83 | //============================================================================ 84 | 85 | /// \brief This function is a special disambiguation tag for variadic 86 | /// functions, used in any and optional 87 | /// 88 | /// \note Calling this function results in undefined behaviour. 89 | template struct in_place_index_t 90 | { 91 | explicit in_place_index_t() = default; 92 | }; 93 | 94 | #if BPSTD_HAS_TEMPLATE_VARIABLES 95 | template 96 | BPSTD_CPP17_INLINE constexpr in_place_index_t in_place_index{}; 97 | #endif 98 | 99 | //============================================================================ 100 | // non-member functions 101 | //============================================================================ 102 | 103 | //---------------------------------------------------------------------------- 104 | // Utilities 105 | //---------------------------------------------------------------------------- 106 | 107 | /// \brief Moves a type \p x if it move-construction is non-throwing 108 | /// 109 | /// \param x the parameter to move 110 | /// \return an rvalue reference if nothrow moveable, const reference otherwise 111 | template 112 | constexpr typename bpstd::conditional< 113 | !bpstd::is_nothrow_move_constructible::value && bpstd::is_copy_constructible::value, 114 | const T&, 115 | T&& 116 | >::type move_if_noexcept(T& x) noexcept; 117 | 118 | /// \brief Forms an lvalue reference to const type of t 119 | /// 120 | /// \param t the type to form an lvalue reference to 121 | /// \return the reference to const T 122 | template 123 | constexpr add_const_t& as_const(T& t) noexcept; 124 | template 125 | void as_const(const T&&) = delete; 126 | 127 | /// \brief Replaces the value of obj with new_value and returns the old value 128 | /// of obj. 129 | /// 130 | /// \pre \p T must meet the requirements of MoveConstructible. 131 | /// 132 | /// \pre It must be possible to move-assign objects of type \p U to objects of 133 | /// type \p T 134 | /// 135 | /// \param obj object whose value to replace 136 | /// \param new_value the value to assign to obj 137 | template 138 | BPSTD_CPP14_CONSTEXPR T exchange(T& obj, U&& new_value); 139 | 140 | //============================================================================ 141 | // class : pair 142 | //============================================================================ 143 | 144 | template 145 | using pair = std::pair; 146 | 147 | //============================================================================ 148 | // non-member functions : class : pair 149 | //============================================================================ 150 | 151 | //---------------------------------------------------------------------------- 152 | // Utilities 153 | //---------------------------------------------------------------------------- 154 | 155 | // C++11 does not implement const pair&& 156 | template 157 | constexpr conditional_t& get(pair& p) noexcept; 158 | template 159 | constexpr conditional_t&& get(pair&& p) noexcept; 160 | template 161 | constexpr const conditional_t& get(const pair& p) noexcept; 162 | template 163 | constexpr const conditional_t&& get(const pair&& p) noexcept; 164 | 165 | template 166 | constexpr T& get(pair& p) noexcept; 167 | template 168 | constexpr T&& get(pair&& p) noexcept; 169 | template 170 | constexpr const T& get(const pair& p) noexcept; 171 | template 172 | constexpr const T&& get(const pair&& p) noexcept; 173 | 174 | template 175 | constexpr T& get(pair& p) noexcept; 176 | template 177 | constexpr const T& get(const pair& p) noexcept; 178 | template 179 | constexpr T&& get(pair&& p) noexcept; 180 | template 181 | constexpr const T&& get(const pair&& p) noexcept; 182 | 183 | //============================================================================ 184 | // struct : integer_sequence 185 | //============================================================================ 186 | 187 | template 188 | struct integer_sequence 189 | { 190 | using value_type = T; 191 | 192 | static constexpr std::size_t size() noexcept { return sizeof...(Ints); } 193 | }; 194 | 195 | template 196 | using index_sequence = integer_sequence; 197 | 198 | namespace detail { 199 | template 200 | struct make_integer_sequence_impl 201 | : make_integer_sequence_impl{}; 202 | 203 | template 204 | struct make_integer_sequence_impl 205 | : type_identity>{}; 206 | 207 | } // namespace detail 208 | 209 | template 210 | using make_integer_sequence 211 | = typename detail::make_integer_sequence_impl::type; 212 | 213 | template 214 | using make_index_sequence = make_integer_sequence; 215 | 216 | template 217 | using index_sequence_for = make_index_sequence; 218 | 219 | } // namespace bpstd 220 | 221 | //============================================================================== 222 | // non-member functions 223 | //============================================================================== 224 | 225 | //------------------------------------------------------------------------------ 226 | // Utilities 227 | //------------------------------------------------------------------------------ 228 | 229 | template 230 | inline BPSTD_INLINE_VISIBILITY constexpr 231 | typename bpstd::conditional< 232 | !bpstd::is_nothrow_move_constructible::value && bpstd::is_copy_constructible::value, 233 | const T&, 234 | T&& 235 | >::type bpstd::move_if_noexcept(T& x) 236 | noexcept 237 | { 238 | using result_type = conditional_t< 239 | !is_nothrow_move_constructible::value && is_copy_constructible::value, 240 | const T&, 241 | T&& 242 | >; 243 | 244 | return static_cast(x); 245 | } 246 | 247 | template 248 | inline BPSTD_INLINE_VISIBILITY constexpr 249 | bpstd::add_const_t& bpstd::as_const(T& t) 250 | noexcept 251 | { 252 | return t; 253 | } 254 | 255 | template 256 | inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR 257 | T bpstd::exchange(T& obj, U&& new_value) 258 | { 259 | auto old_value = bpstd::move(obj); 260 | obj = bpstd::forward(new_value); 261 | return old_value; 262 | } 263 | 264 | //============================================================================== 265 | // definitions : non-member functions : class : pair 266 | //============================================================================== 267 | 268 | //------------------------------------------------------------------------------ 269 | // Utilities 270 | //------------------------------------------------------------------------------ 271 | 272 | template 273 | inline BPSTD_INLINE_VISIBILITY constexpr 274 | bpstd::conditional_t& 275 | bpstd::get(pair& p) 276 | noexcept 277 | { 278 | static_assert(N<=1, "N must be either 0 or 1 for get(pair)"); 279 | 280 | return std::get(p); 281 | } 282 | 283 | template 284 | inline BPSTD_INLINE_VISIBILITY constexpr 285 | bpstd::conditional_t&& 286 | bpstd::get(pair&& p) 287 | noexcept 288 | { 289 | static_assert(N<=1, "N must be either 0 or 1 for get(pair)"); 290 | 291 | return move(std::get(p)); 292 | } 293 | 294 | template 295 | inline BPSTD_INLINE_VISIBILITY constexpr 296 | const bpstd::conditional_t& 297 | bpstd::get(const pair& p) 298 | noexcept 299 | { 300 | static_assert(N<=1, "N must be either 0 or 1 for get(pair)"); 301 | 302 | return std::get(p); 303 | } 304 | 305 | template 306 | inline BPSTD_INLINE_VISIBILITY constexpr 307 | const bpstd::conditional_t&& 308 | bpstd::get(const pair&& p) 309 | noexcept 310 | { 311 | static_assert(N<=1, "N must be either 0 or 1 for get(pair)"); 312 | 313 | return move(std::get(p)); 314 | } 315 | 316 | template 317 | inline BPSTD_INLINE_VISIBILITY constexpr 318 | T& bpstd::get(pair& p) 319 | noexcept 320 | { 321 | return p.first; 322 | } 323 | 324 | template 325 | inline BPSTD_INLINE_VISIBILITY constexpr 326 | const T& bpstd::get(const pair& p) 327 | noexcept 328 | { 329 | return p.first; 330 | } 331 | 332 | template 333 | inline BPSTD_INLINE_VISIBILITY constexpr 334 | T&& bpstd::get(pair&& p) 335 | noexcept 336 | { 337 | return move(p.first); 338 | } 339 | 340 | template 341 | inline BPSTD_INLINE_VISIBILITY constexpr 342 | const T&& bpstd::get(const pair&& p) 343 | noexcept 344 | { 345 | return move(p.first); 346 | } 347 | 348 | template 349 | inline BPSTD_INLINE_VISIBILITY constexpr 350 | T& bpstd::get(pair& p) 351 | noexcept 352 | { 353 | return p.second; 354 | } 355 | 356 | template 357 | inline BPSTD_INLINE_VISIBILITY constexpr 358 | const T& bpstd::get(const pair& p) 359 | noexcept 360 | { 361 | return p.second; 362 | } 363 | 364 | template 365 | inline BPSTD_INLINE_VISIBILITY constexpr 366 | T&& bpstd::get(pair&& p) 367 | noexcept 368 | { 369 | return move(p.second); 370 | } 371 | 372 | template 373 | inline BPSTD_INLINE_VISIBILITY constexpr 374 | const T&& bpstd::get(const pair&& p) 375 | noexcept 376 | { 377 | return move(p.second); 378 | } 379 | 380 | BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE 381 | 382 | #endif /* BPSTD_UTILITY_HPP */ 383 | --------------------------------------------------------------------------------