├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── documentation.yml │ ├── integration.yml │ └── unit.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE.md ├── README.md ├── cmake ├── compiler.cmake ├── dependencies.cmake ├── raberu-config.cmake └── run_wasm.sh ├── doc ├── Doxyfile ├── base.html ├── changelog.md ├── color.css ├── custom.hpp ├── index.hpp ├── layout.xml ├── licence.md ├── logo.png ├── setup.hpp └── tutorial.hpp ├── include └── raberu │ ├── impl │ ├── algo.hpp │ ├── algo │ │ ├── drop.hpp │ │ ├── fetch.hpp │ │ ├── is_equivalent.hpp │ │ ├── keys_values.hpp │ │ └── merge.hpp │ ├── concepts.hpp │ ├── helpers.hpp │ ├── keywords.hpp │ ├── literals.hpp │ └── settings.hpp │ └── raberu.hpp ├── standalone └── raberu │ └── raberu.hpp └── test ├── CMakeLists.txt ├── doc ├── accept.cpp ├── checked.cpp ├── contains.cpp ├── contains_any.cpp ├── contains_none.cpp ├── contains_only.cpp ├── drop.cpp ├── fetch.cpp ├── flag.cpp ├── is_equivalent.cpp ├── keyword_fetch.cpp ├── keywords.cpp ├── merge.cpp ├── regular.cpp ├── show.cpp ├── subscript.cpp ├── tutorial01.cpp ├── tutorial02.cpp ├── tutorial03.cpp ├── tutorial04.cpp ├── tutorial05.cpp └── values.cpp ├── integration ├── cpm-test │ ├── CMakeLists.txt │ └── cpm.cmake ├── fetch-test │ └── CMakeLists.txt ├── install-test │ └── CMakeLists.txt └── main.cpp └── unit ├── access.cpp ├── common.hpp ├── concepts.cpp ├── constraints.cpp ├── contains.cpp ├── doc.cpp ├── drop.cpp ├── extract_types.cpp ├── fetch.cpp ├── interface.cpp ├── merge.cpp └── size.cpp /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior. A Compiler Explorer link is the preferred way to transfer buggy code fragment. Code must be as small as possible while still exhibiting the bug. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Setup:** 20 | - Compiler and compiler's version: [e.g. g++ 10] 21 | - OS: [e.g. Arch Linux] 22 | 23 | **Additional context** 24 | Add any other context about the problem here. 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE]" 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/documentation.yml: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## RABERU - Fancy Parameters Library 3 | ## Copyright : RABERU Contributors & Maintainers 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | name: RABERU Documentation Generation 7 | on: 8 | push: 9 | branches: 10 | - main 11 | 12 | jobs: 13 | generate-doc: 14 | runs-on: ubuntu-latest 15 | container: 16 | image: ghcr.io/jfalcou/compilers:v9 17 | strategy: 18 | fail-fast: false 19 | steps: 20 | - name: Fetch current branch 21 | uses: actions/checkout@v3 22 | - name: Prepare RABERU for documentation 23 | run: | 24 | mkdir build && cd build 25 | cmake .. -G Ninja -DRABERU_BUILD_TEST=OFF -DRABERU_BUILD_DOCUMENTATION=ON 26 | 27 | - name: Generate Doxygen 28 | run: | 29 | cd build 30 | ninja raberu-doxygen 31 | 32 | - name: Deploy to gh-pages 33 | uses: peaceiris/actions-gh-pages@v3 34 | with: 35 | github_token: ${{ secrets.GITHUB_TOKEN }} 36 | publish_dir: ./build/doc 37 | -------------------------------------------------------------------------------- /.github/workflows/integration.yml: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## RABERU - Fancy Parameters Library 3 | ## Copyright : RABERU Contributors & Maintainers 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | name: RABERU Integration Tests 7 | on: 8 | pull_request: 9 | branches: 10 | - main 11 | 12 | concurrency: 13 | group: raberu-integration-${{ github.ref }} 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | 18 | install: 19 | runs-on: [ubuntu-latest] 20 | container: 21 | image: ghcr.io/jfalcou/compilers:v9 22 | strategy: 23 | fail-fast: false 24 | 25 | steps: 26 | - name: Fetch current branch 27 | uses: actions/checkout@v3 28 | - name: Install RABERU from checkout 29 | run: | 30 | mkdir build && cd build 31 | cmake -G Ninja .. -DRABERU_BUILD_TEST=OFF -DCMAKE_CXX_COMPILER=clang++ 32 | ninja install 33 | - name: Run Sample CMake 34 | run: | 35 | mkdir install && cd install 36 | cmake ../test/integration/install-test -G Ninja 37 | ninja && ctest --verbose 38 | 39 | fetch-content: 40 | env: 41 | BRANCH_NAME: ${{ github.head_ref || github.ref_name }} 42 | runs-on: [ubuntu-latest] 43 | container: 44 | image: ghcr.io/jfalcou/compilers:v9 45 | strategy: 46 | fail-fast: false 47 | 48 | steps: 49 | - name: Fetch current branch 50 | uses: actions/checkout@v3 51 | - name: Compile using FetchContent 52 | run: | 53 | git config --global --add safe.directory /__w/raberu/raberu 54 | mkdir install && cd install 55 | cmake ../test/integration/fetch-test -G Ninja -DGIT_BRANCH=${BRANCH_NAME} -DRABERU_BUILD_TEST=OFF -DCMAKE_CXX_COMPILER=clang++ 56 | ninja && ctest --verbose 57 | 58 | cpm: 59 | env: 60 | BRANCH_NAME: ${{ github.head_ref || github.ref_name }} 61 | runs-on: [ubuntu-latest] 62 | container: 63 | image: ghcr.io/jfalcou/compilers:v9 64 | strategy: 65 | fail-fast: false 66 | 67 | steps: 68 | - name: Fetch current branch 69 | uses: actions/checkout@v3 70 | - name: Compile using CPM 71 | run: | 72 | git config --global --add safe.directory /__w/raberu/raberu 73 | mkdir install && cd install 74 | cmake ../test/integration/cpm-test -G Ninja -DGIT_BRANCH=${BRANCH_NAME} -DCMAKE_CXX_COMPILER=clang++ -DRABERU_BUILD_TEST=OFF 75 | ninja && ctest --verbose 76 | -------------------------------------------------------------------------------- /.github/workflows/unit.yml: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## RABERU - Fancy Parameters Library 3 | ## Copyright : RABERU Contributors & Maintainers 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | name: RABERU Unit Testing 7 | on: 8 | pull_request: 9 | branches: 10 | - main 11 | 12 | concurrency: 13 | group: raberu-unit-${{ github.ref }} 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | 18 | windows: 19 | runs-on: [windows-2022] 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | cfg: 24 | - { tool: "-T ClangCL", config: Debug } 25 | - { tool: "-T ClangCL", config: Release } 26 | - { tool: , config: Debug } 27 | - { tool: , config: Release } 28 | steps: 29 | - name: Fetch current branch 30 | uses: actions/checkout@v3 31 | - name: Running CMake for MSVC 32 | run: | 33 | mkdir build && cd build 34 | cmake -G "Visual Studio 17 2022" ${{ matrix.cfg.tool }} -A x64 .. 35 | - name: Compiling Unit Tests 36 | run: | 37 | cd build 38 | cmake --build . --target raberu-test --config ${{ matrix.cfg.config }} --parallel 2 39 | cmake --build . --target raberu-test --config Release --parallel 2 40 | - name: Running Tests 41 | run: | 42 | cd build 43 | ctest -C ${{ matrix.cfg.config }} --output-on-failure 44 | 45 | linux: 46 | runs-on: [ubuntu-latest] 47 | container: 48 | image: ghcr.io/jfalcou/compilers:v9 49 | strategy: 50 | fail-fast: false 51 | matrix: 52 | cfg: 53 | - { compiler: g++-14 , opts: -O0 , linker: } 54 | - { compiler: clang++ , opts: -O0 , linker: } 55 | - { compiler: clang++ , opts: "-O3 -flto -DNDEBUG" , linker: } 56 | - { compiler: g++-14 , opts: "-O3 -flto -DNDEBUG" , linker: } 57 | - { compiler: clang++ , opts: "-O3 -flto -DNDEBUG -stdlib=libc++" , linker: -stdlib=libc++ } 58 | - { compiler: clang++ , opts: "-O0 -stdlib=libc++" , linker: -stdlib=libc++ } 59 | steps: 60 | - name: Fetch current branch 61 | uses: actions/checkout@v3 62 | - name: Running CMake for ${{ matrix.cfg.compiler }} with ${{ matrix.cfg.opts }} 63 | run: | 64 | mkdir build && cd build 65 | cmake .. -G Ninja -DCMAKE_CXX_COMPILER=${{ matrix.cfg.compiler }} -DCMAKE_CXX_FLAGS="${{ matrix.cfg.opts }}" -DCMAKE_EXE_LINKER_FLAGS=${{ matrix.cfg.linker }} 66 | - name: Running Unit Tests 67 | run: cd build && ninja raberu-test -j 2 && ctest --output-on-failure -j 2 68 | 69 | macosx: 70 | runs-on: [macos-14] 71 | strategy: 72 | fail-fast: false 73 | matrix: 74 | cfg: 75 | - { compiler: g++-14 , opts: -O0 , linker: } 76 | - { compiler: g++-14 , opts: "-O3 -DNDEBUG" , linker: } 77 | - { compiler: clang++ , opts: -O0 , linker: } 78 | - { compiler: clang++ , opts: "-O3 -flto -DNDEBUG" , linker: } 79 | - { compiler: clang++ , opts: "-O3 -flto -DNDEBUG -stdlib=libc++" , linker: -stdlib=libc++ } 80 | - { compiler: clang++ , opts: "-O0 -stdlib=libc++" , linker: -stdlib=libc++ } 81 | steps: 82 | - name: Fetch current branch 83 | uses: actions/checkout@v3 84 | - name: Running CMake for ${{ matrix.cfg.compiler }} with ${{ matrix.cfg.opts }} 85 | run: | 86 | mkdir build && cd build 87 | cmake .. -DCMAKE_CXX_COMPILER=${{ matrix.cfg.compiler }} -DCMAKE_CXX_FLAGS="${{ matrix.cfg.opts }}" -DCMAKE_EXE_LINKER_FLAGS=${{ matrix.cfg.linker }} 88 | - name: Running Unit Tests 89 | run: cd build && make raberu-test -j 2 && ctest --output-on-failure -j 2 90 | 91 | android: 92 | runs-on: [macos-14] 93 | strategy: 94 | fail-fast: false 95 | matrix: 96 | cfg: 97 | - { opts: -O0 } 98 | - { opts: "-O3 -flto -DNDEBUG"} 99 | steps: 100 | - name: Fetch current branch 101 | uses: actions/checkout@v3 102 | - name: Running CMake for ${{ matrix.cfg.compiler }} with ${{ matrix.cfg.opts }} 103 | run: | 104 | mkdir build && cd build 105 | cmake .. -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a 106 | - name: Compiling Unit Tests 107 | run: cd build && make raberu-test -j 2 108 | 109 | wasm: 110 | runs-on: ubuntu-latest 111 | container: 112 | image: ghcr.io/jfalcou/compilers:v9 113 | strategy: 114 | fail-fast: false 115 | matrix: 116 | cfg: 117 | - { opts: -O0 } 118 | - { opts: "-O3 -flto -DNDEBUG"} 119 | steps: 120 | - name: Fetch current branch 121 | uses: actions/checkout@v3 122 | - name: RABERU using em++ with ${{ matrix.cfg.opts }} 123 | run: | 124 | mkdir build 125 | cd build 126 | emcmake cmake .. -G Ninja -DCMAKE_CXX_COMPILER=em++ -DCMAKE_CXX_FLAGS="${{ matrix.cfg.opts }}" -DCMAKE_CROSSCOMPILING_CMD="`pwd`/../cmake/run_wasm.sh" 127 | - name: Compile Unit Tests 128 | run: | 129 | cd build 130 | ninja raberu-test -j 2 131 | - name: Running Unit Tests 132 | run: | 133 | cd build 134 | ctest --output-on-failure -j 2 135 | 136 | icpx: 137 | runs-on: ubuntu-latest 138 | container: 139 | image: ghcr.io/jfalcou/compilers:sycl-v1 140 | strategy: 141 | fail-fast: false 142 | matrix: 143 | cfg: 144 | - { opts: "-O0" } 145 | - { opts: "-O3 -flto -DNDEBUG" } 146 | steps: 147 | - name: Fetch current branch 148 | uses: actions/checkout@v3 149 | - name: Running CMake for icpx with ${{ matrix.cfg.opts }} 150 | run: | 151 | source /opt/intel/oneapi/setvars.sh 152 | mkdir build 153 | cd build 154 | cmake .. -G Ninja -DCMAKE_CXX_COMPILER=icpx -DCMAKE_CXX_FLAGS="${{ matrix.cfg.opts }}" 155 | - name: Running Unit Tests 156 | run: | 157 | cd build 158 | ninja raberu-test -j 2 && ctest --output-on-failure -j 2 159 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | build/* 35 | .cache 36 | compile_commands.json 37 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## RABERU - Fancy Named Parameter Library 3 | ## Copyright : RABERU Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | cmake_minimum_required(VERSION 3.22) 7 | project(raberu LANGUAGES CXX) 8 | 9 | ##====================================================================================================================== 10 | option( RABERU_BUILD_TEST "Build tests for Raberu" ON ) 11 | option( RABERU_BUILD_DOCUMENTATION "Build Doxygen for Raberu" OFF ) 12 | 13 | ##====================================================================================================================== 14 | include(${PROJECT_SOURCE_DIR}/cmake/dependencies.cmake) 15 | 16 | if(RABERU_BUILD_TEST) 17 | include(${PROJECT_SOURCE_DIR}/cmake/compiler.cmake) 18 | endif() 19 | 20 | ##====================================================================================================================== 21 | ## Project setup via copacabana 22 | ##====================================================================================================================== 23 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake ${COPACABANA_SOURCE_DIR}/copacabana/cmake) 24 | include(${COPACABANA_SOURCE_DIR}/copacabana/cmake/copacabana.cmake) 25 | copa_project_version(MAJOR 1 MINOR 1 PATCH 0) 26 | 27 | ##====================================================================================================================== 28 | ## Summary Display 29 | ##====================================================================================================================== 30 | if(NOT RABERU_QUIET) 31 | if(CMAKE_BUILD_TYPE) 32 | message(STATUS "[${PROJECT_NAME}] - Building in ${CMAKE_BUILD_TYPE} mode") 33 | endif() 34 | message(STATUS "[${PROJECT_NAME}] - Unit tests : ${RABERU_BUILD_TEST} (via RABERU_BUILD_TEST)") 35 | message(STATUS "[${PROJECT_NAME}] - Doxygen : ${RABERU_BUILD_DOCUMENTATION} (via RABERU_BUILD_DOCUMENTATION)") 36 | set(QUIET_OPTION "") 37 | else() 38 | set(QUIET_OPTION "QUIET") 39 | endif() 40 | 41 | ##====================================================================================================================== 42 | ## Install Process setup 43 | ##====================================================================================================================== 44 | copa_setup_install( LIBRARY raberu 45 | FEATURES cxx_std_20 46 | DOC ${PROJECT_SOURCE_DIR}/LICENSE.md 47 | INCLUDE ${PROJECT_SOURCE_DIR}/include/raberu 48 | ) 49 | 50 | ##====================================================================================================================== 51 | ## Setup doxygen 52 | ##====================================================================================================================== 53 | if(RABERU_BUILD_DOCUMENTATION) 54 | copa_setup_doxygen(${QUIET_OPTION} TARGET raberu-doxygen DESTINATION "${PROJECT_BINARY_DIR}/doc") 55 | endif() 56 | 57 | ##====================================================================================================================== 58 | ## Standalone generation 59 | ##====================================================================================================================== 60 | copa_setup_standalone ( ${QUIET_OPTION} 61 | FILE raberu.hpp SOURCE include DESTINATION standalone 62 | ROOT raberu TARGET raberu-standalone 63 | ) 64 | 65 | ##====================================================================================================================== 66 | ## Tests setup 67 | ##====================================================================================================================== 68 | if(RABERU_BUILD_TEST) 69 | enable_testing() 70 | add_custom_target(raberu-unit) 71 | add_subdirectory(test) 72 | endif() 73 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Boost Software License 2 | 3 | Copyright : RABERU Project Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the 6 | software and accompanying documentation covered by this license (the "Software") to use, reproduce, 7 | display, distribute, execute, and transmit the Software, and to prepare derivative works of the 8 | Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the 9 | following: 10 | 11 | The copyright notices in the Software and this entire statement, including the above license grant, 12 | this restriction and the following disclaimer, must be included in all copies of the Software, in 13 | whole or in part, and all derivative works of the Software, unless such copies or derivative works 14 | are solely in the form of machine-executable object code generated by a source language processor. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 17 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 18 | NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE 19 | BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING 20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | raberu Logo : Red parens in a red square box on white background 2 | 3 | # RABERU - The Fancy Named Parameters Library 4 | 5 | **RABERU** provides a way to define and use named parameters, *i.e* a list of values assigned to 6 | arbitrary keyword-like identifiers, to functions. 7 | 8 | It does so by providing: 9 | 10 | * a protocol to define such keywords. 11 | * a type to process such aggregate of parameters. 12 | * a `constexpr`-compatible implementation for all of those. 13 | 14 | # A Short Example 15 | 16 | [See it live on Compiler Explorer](https://godbolt.org/z/oWjP44n57) 17 | 18 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++ 19 | #include 20 | #include 21 | #include 22 | 23 | template 24 | auto replicate( P0 p0, P1 p1 ) 25 | { 26 | auto const params = rbr::settings(p0,p1); 27 | return std::string( params["replication"_kw], params["letter"_kw] ); 28 | } 29 | 30 | int main() 31 | { 32 | using namespace rbr::literals; 33 | 34 | std::cout << replicate("replication"_kw = 9, "letter"_kw = 'z' ) << "\n"; 35 | std::cout << replicate("letter"_kw = '!' , "replication"_kw = 3) << "\n"; 36 | } 37 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 38 | 39 | # Licence 40 | 41 | This library is licensed under the [Boost Software License](https://opensource.org/licenses/BSL-1.0): 42 | 43 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ none 44 | Copyright : RABERU Project Contributors 45 | 46 | Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the 47 | software and accompanying documentation covered by this license (the "Software") to use, reproduce, 48 | display, distribute, execute, and transmit the Software, and to prepare derivative works of the 49 | Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the 50 | following: 51 | 52 | The copyright notices in the Software and this entire statement, including the above license grant, 53 | this restriction and the following disclaimer, must be included in all copies of the Software, in 54 | whole or in part, and all derivative works of the Software, unless such copies or derivative works 55 | are solely in the form of machine-executable object code generated by a source language processor. 56 | 57 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 58 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 59 | NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE 60 | BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING 61 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 62 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 63 | -------------------------------------------------------------------------------- /cmake/compiler.cmake: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## RABERU - Fancy Named Parameter Library 3 | ## Copyright : RABERU Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | 7 | ##====================================================================================================================== 8 | ## Compiler options 9 | ##====================================================================================================================== 10 | add_library(raberu_test INTERFACE) 11 | 12 | target_compile_features ( raberu_test INTERFACE cxx_std_20 ) 13 | 14 | if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 15 | if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") 16 | target_compile_options( raberu_test INTERFACE /W3 /EHsc ) 17 | else() 18 | target_compile_options( raberu_test INTERFACE -Werror -Wall -Wextra -Wunused-variable -Wdocumentation 19 | ) 20 | endif() 21 | elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 22 | target_compile_options( raberu_test INTERFACE /W3 /EHsc /Zc:preprocessor) 23 | else() 24 | target_compile_options( raberu_test INTERFACE -Werror -Wall -Wextra -Wunused-variable) 25 | endif() 26 | 27 | target_include_directories( raberu_test INTERFACE 28 | ${PROJECT_SOURCE_DIR}/test 29 | ${PROJECT_SOURCE_DIR}/standalone 30 | ) 31 | 32 | target_link_libraries(raberu_test INTERFACE tts::tts) 33 | -------------------------------------------------------------------------------- /cmake/dependencies.cmake: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## RABERU - Fancy Named Parameter Library 3 | ## Copyright : RABERU Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | 7 | ##====================================================================================================================== 8 | ## Download and setup CPM 9 | ##====================================================================================================================== 10 | set(CPM_DOWNLOAD_VERSION 0.40.8) 11 | 12 | if(CPM_SOURCE_CACHE) 13 | set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 14 | elseif(DEFINED ENV{CPM_SOURCE_CACHE}) 15 | set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 16 | else() 17 | set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 18 | endif() 19 | 20 | if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION})) 21 | message(STATUS "[${PROJECT_NAME}] Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}") 22 | file(DOWNLOAD 23 | https://github.com/TheLartians/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake 24 | ${CPM_DOWNLOAD_LOCATION} 25 | ) 26 | endif() 27 | 28 | include(${CPM_DOWNLOAD_LOCATION}) 29 | 30 | ##====================================================================================================================== 31 | ## Retrieve dependencies 32 | ##====================================================================================================================== 33 | CPMAddPackage(NAME COPACABANA GITHUB_REPOSITORY jfalcou/copacabana GIT_TAG main) 34 | 35 | if(RABERU_BUILD_TEST) 36 | CPMAddPackage ( NAME TTS GITHUB_REPOSITORY jfalcou/tts 37 | GIT_TAG main 38 | OPTIONS "TTS_BUILD_TEST OFF" 39 | "TTS_BUILD_DOCUMENTATION OFF" 40 | "TTS_QUIET ON" 41 | ) 42 | endif() 43 | -------------------------------------------------------------------------------- /cmake/raberu-config.cmake: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## RABERU - Fancy Named Parameter Library 3 | ## Copyright : RABERU Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | 7 | ##====================================================================================================================== 8 | ## Reuse install.cmake to preapre package properly 9 | ##====================================================================================================================== 10 | include("${CMAKE_CURRENT_LIST_DIR}/raberu-targets.cmake") 11 | set(RABERU_LIBRARIES raberu::raberu) 12 | -------------------------------------------------------------------------------- /cmake/run_wasm.sh: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## KUMI - Compact C++20 Tuple Toolbox 3 | ## Copyright : KUMI Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | #!/bin/sh 7 | 8 | node $@ 9 | -------------------------------------------------------------------------------- /doc/Doxyfile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------- 2 | # Project related configuration options 3 | #--------------------------------------------------------------------------- 4 | DOXYFILE_ENCODING = UTF-8 5 | 6 | PROJECT_NAME = $(DOXYGEN_PROJECT_NAME) 7 | PROJECT_NUMBER = v$(DOXYGEN_PROJECT_VERSION) 8 | PROJECT_BRIEF = Fancy Named Parameter Library 9 | PROJECT_LOGO = logo.png 10 | OUTPUT_DIRECTORY = $(DOXYGEN_OUPUT) 11 | CREATE_SUBDIRS = NO 12 | ALLOW_UNICODE_NAMES = NO 13 | 14 | BRIEF_MEMBER_DESC = YES 15 | REPEAT_BRIEF = YES 16 | ABBREVIATE_BRIEF = "The $name class" \ 17 | "The $name widget" \ 18 | "The $name file" \ 19 | is \ 20 | provides \ 21 | specifies \ 22 | contains \ 23 | represents \ 24 | a \ 25 | an \ 26 | the 27 | ALWAYS_DETAILED_SEC = NO 28 | INLINE_INHERITED_MEMB = YES 29 | 30 | FULL_PATH_NAMES = YES 31 | STRIP_FROM_INC_PATH = $(DOXYGEN_STRIP)/src 32 | STRIP_FROM_INC_PATH = $(DOXYGEN_STRIP)/include 33 | STRIP_FROM_PATH = $(DOXYGEN_STRIP)/src 34 | STRIP_FROM_PATH += $(DOXYGEN_STRIP)/include 35 | 36 | 37 | EXAMPLE_PATH = ../test/doc \ 38 | ../test/integration \ 39 | . 40 | 41 | SEPARATE_MEMBER_PAGES = YES 42 | TAB_SIZE = 2 43 | 44 | ALIASES += "godbolt{1}=@include \1" 45 | ALIASES += "groupheader{1}=

\1

" 46 | ALIASES += "nullable=[NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer)" 47 | ALIASES += "semiregular=SemiRegular" 48 | ALIASES += "regular=Regular" 49 | ALIASES += "swappable=Swappable" 50 | ALIASES += "callable=[Callable Object](https://en.cppreference.com/w/cpp/named_req/Callable)" 51 | ALIASES += "container=[Container](https://en.cppreference.com/w/cpp/named_req/Container)" 52 | ALIASES += "iterator=[Input Iterator](https://en.cppreference.com/w/cpp/named_req/Inputterator)" 53 | ALIASES += "raiterator=[Random Access Iterator](https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator)" 54 | ALIASES += "callable{1}=[Callable Object\1](https://en.cppreference.com/w/cpp/named_req/Callable)" 55 | ALIASES += "container{1}=[Container\1](https://en.cppreference.com/w/cpp/named_req/Container)" 56 | ALIASES += "iterator{1}=[Input Iterator\1](https://en.cppreference.com/w/cpp/named_req/Inputterator)" 57 | ALIASES += "raiterator{1}=[Random Access Iterator\1](https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator" 58 | ALIASES += "view{1}=[view\1](@ref kwk::view)" 59 | ALIASES += "view=[view](@ref kwk::view)" 60 | 61 | EXTENSION_MAPPING = 62 | MARKDOWN_SUPPORT = YES 63 | TOC_INCLUDE_HEADINGS = 5 64 | AUTOLINK_SUPPORT = YES 65 | LOOKUP_CACHE_SIZE = 0 66 | 67 | #--------------------------------------------------------------------------- 68 | # Build related configuration options 69 | #--------------------------------------------------------------------------- 70 | EXTRACT_ALL = NO 71 | EXTRACT_PRIVATE = NO 72 | EXTRACT_PRIV_VIRTUAL = NO 73 | EXTRACT_PACKAGE = NO 74 | EXTRACT_STATIC = NO 75 | EXTRACT_LOCAL_CLASSES = NO 76 | EXTRACT_LOCAL_METHODS = NO 77 | EXTRACT_ANON_NSPACES = NO 78 | HIDE_UNDOC_MEMBERS = YES 79 | HIDE_UNDOC_CLASSES = YES 80 | HIDE_FRIEND_COMPOUNDS = NO 81 | HIDE_IN_BODY_DOCS = NO 82 | INTERNAL_DOCS = NO 83 | CASE_SENSE_NAMES = YES 84 | HIDE_SCOPE_NAMES = NO 85 | HIDE_COMPOUND_REFERENCE= NO 86 | SHOW_INCLUDE_FILES = NO 87 | SHOW_GROUPED_MEMB_INC = YES 88 | SORT_MEMBER_DOCS = YES 89 | SORT_BRIEF_DOCS = YES 90 | SORT_MEMBERS_CTORS_1ST = YES 91 | SORT_GROUP_NAMES = YES 92 | GENERATE_TODOLIST = NO 93 | GENERATE_TESTLIST = NO 94 | GENERATE_BUGLIST = NO 95 | SHOW_USED_FILES = NO 96 | SHOW_FILES = YES 97 | LAYOUT_FILE = layout.xml 98 | INPUT = ../include \ 99 | . 100 | 101 | RECURSIVE = YES 102 | EXCLUDE_SYMBOLS = detail* 103 | SOURCE_BROWSER = NO 104 | VERBATIM_HEADERS = NO 105 | 106 | #--------------------------------------------------------------------------- 107 | # Configuration options related to the HTML output 108 | #--------------------------------------------------------------------------- 109 | GENERATE_HTML = YES 110 | HTML_OUTPUT = ./ 111 | HTML_FILE_EXTENSION = .html 112 | HTML_HEADER = ./base.html 113 | HTML_FOOTER = $(DOXYGEN_ASSETS)/footer.html 114 | HTML_STYLESHEET = 115 | HTML_EXTRA_STYLESHEET = $(DOXYGEN_ASSETS)/custom.css 116 | HTML_EXTRA_STYLESHEET += color.css 117 | HTML_EXTRA_STYLESHEET += $(DOXYGEN_ASSETS)/doxygen-awesome.css 118 | HTML_EXTRA_STYLESHEET += $(DOXYGEN_ASSETS)/doxygen-awesome-sidebar-only.css 119 | HTML_EXTRA_FILES = $(DOXYGEN_ASSETS)/godbolt.js 120 | HTML_EXTRA_FILES += $(DOXYGEN_ASSETS)/fragment.js 121 | HTML_EXTRA_FILES += $(DOXYGEN_ASSETS)/paragraph.js 122 | HTML_COLORSTYLE_HUE = 189 123 | HTML_COLORSTYLE_SAT = 28 124 | HTML_COLORSTYLE_GAMMA = 68 125 | HTML_TIMESTAMP = NO 126 | HTML_DYNAMIC_MENUS = NO 127 | HTML_DYNAMIC_SECTIONS = NO 128 | HTML_INDEX_NUM_ENTRIES = 100 129 | GENERATE_DOCSET = NO 130 | 131 | DISABLE_INDEX = YES 132 | GENERATE_TREEVIEW = YES 133 | ENUM_VALUES_PER_LINE = 4 134 | TREEVIEW_WIDTH = 250 135 | 136 | EXT_LINKS_IN_WINDOW = NO 137 | FORMULA_FONTSIZE = 10 138 | FORMULA_TRANSPARENT = YES 139 | USE_MATHJAX = YES 140 | MATHJAX_FORMAT = HTML-CSS 141 | MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1 142 | MATHJAX_EXTENSIONS = 143 | MATHJAX_CODEFILE = 144 | SEARCHENGINE = YES 145 | SEARCHDATA_FILE = searchdata.xml 146 | GENERATE_LATEX = NO 147 | GENERATE_RTF = NO 148 | GENERATE_MAN = NO 149 | GENERATE_XML = NO 150 | GENERATE_DOCBOOK = NO 151 | GENERATE_AUTOGEN_DEF = NO 152 | GENERATE_PERLMOD = NO 153 | 154 | ENABLE_PREPROCESSING = YES 155 | MACRO_EXPANSION = YES 156 | EXPAND_ONLY_PREDEF = YES 157 | SEARCH_INCLUDES = YES 158 | INCLUDE_PATH = ../include 159 | INCLUDE_FILE_PATTERNS = 160 | PREDEFINED = RABERU_DOXYGEN_INVOKED 161 | EXPAND_AS_DEFINED = 162 | SKIP_FUNCTION_MACROS = YES 163 | DIA_PATH = 164 | HIDE_UNDOC_RELATIONS = YES 165 | HAVE_DOT = NO 166 | CLASS_GRAPH = NO 167 | COLLABORATION_GRAPH = NO 168 | GROUP_GRAPHS = NO 169 | UML_LOOK = NO 170 | DOT_UML_DETAILS = NO 171 | DOT_WRAP_THRESHOLD = 17 172 | TEMPLATE_RELATIONS = NO 173 | INCLUDE_GRAPH = NO 174 | CALL_GRAPH = NO 175 | CALLER_GRAPH = NO 176 | GRAPHICAL_HIERARCHY = YES 177 | DIRECTORY_GRAPH = NO 178 | DIR_GRAPH_MAX_DEPTH = 1 179 | -------------------------------------------------------------------------------- /doc/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | $projectname: $title 10 | $title 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | $treeview 28 | $search 29 | $mathjax 30 | 31 | $extrastylesheet 32 | 33 | 34 | 35 | 36 |
37 | 38 | 39 | 40 | 42 | 43 |
44 | 45 | 46 |
47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 59 | 60 | 61 | 62 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |
55 |
$projectname $projectnumber 56 |
57 |
$projectbrief
58 |
63 |
$projectbrief
64 |
$searchbox
76 |
77 | 78 | 79 | -------------------------------------------------------------------------------- /doc/changelog.md: -------------------------------------------------------------------------------- 1 | Change Log {#changelog} 2 | ========== 3 | 4 | # Version 2.0 - Past Prologue 5 | 6 | ## Bug Fixes 7 | * Moved from `pragma once` to `#ifndef` to allow for multiple raberu files to coexist in multiple projects. 8 | * Fixed a regression in Visual Studio that affected ability to run tests. 9 | * Fix #6 - Compile-time ID are now properly displayed and compared without any issues due to terminal `\0`. 10 | 11 | ## New Features 12 | * Fix #4 - Simplify and generalize custom keyword generation 13 | A new CRTP class `rbr::as_keyword` streamlines the definition of compact keyword by users while 14 | supporting the whole range of built-in keywords. Associated documentation has been updated. 15 | 16 | * Fix #2 - Implement direct keyword value access 17 | Keyword can now fetch themselves from a bundles of options. E.g 18 | 19 | ``` c++ 20 | inline constexpr auto coord_ = "coord"_kw; 21 | inline constexpr auto is_modal_ = "is_modal"_fl; 22 | 23 | auto x = coord_(coord_ = "Jane"s, is_modal_); 24 | ``` 25 | 26 | * Fix #5 - Mass extractors for keyword and values 27 | `rbr::keywords` and`rbr::values` can be used to retrieve a tuple-like object containing all the 28 | keywords or values from a bundle of options. 29 | 30 | * `rbr::get_type` is removed and is replaced by `rbr::fetch` and `rbr::result::fetch_t`. 31 | This functions provides an infix syntax for options access. 32 | 33 | # Version 1.0 - Emissary 34 | 35 | ## First autonomous public release. 36 | 37 | **RABERU** (ラベル組) is now independent of the OFW repository. 38 | -------------------------------------------------------------------------------- /doc/color.css: -------------------------------------------------------------------------------- 1 | html 2 | { 3 | /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */ 4 | --primary-dark-color: hsl(0, 100%, 10%); 5 | --primary-color: hsl(0, 100%, 25%); 6 | --primary-light-color: hsl(0, 100%, 40%); 7 | 8 | /* page base colors */ 9 | --page-background-color: white; 10 | --page-foreground-color: hsl(0, 100%, 10%); 11 | --page-secondary-foreground-color: hsl(0, 100%, 25%); 12 | } 13 | -------------------------------------------------------------------------------- /doc/custom.hpp: -------------------------------------------------------------------------------- 1 | #error DO NOT INCLUDE - DOCUMENTATION PURPOSE ONLY 2 | 3 | //================================================================================================== 4 | /** 5 | \page custom Tutorial: Customizing Keyword 6 | 7 | @tableofcontents 8 | 9 | \section custom_01 Using Pre-bound keyword 10 | 11 | Sometimes you wish you could have a terser syntax for keyword parameters. 12 | Let's say you want to pass a compile-time unrolling factor to some algorithm. 13 | 14 | @code 15 | // This is working but a bit verbose 16 | using namespace rbr::literals; 17 | inline constexpr auto unroll = rbr::keyword("unrolling"_id); 18 | 19 | auto x = my_algorithm( unroll = std::integral_constant{}); 20 | @endcode 21 | 22 | One idea is to defines a **pre-bound keyword parameter**, i.e constructs an inline 23 | variable initialized with the result of the assignment of a value to a keyword. 24 | 25 | @code 26 | using namespace rbr::literals; 27 | inline constexpr auto unrolling = rbr::keyword("unrolling"_id); 28 | 29 | template inline constexpr auto unroll = (unrolling = std::integral_constant{}); 30 | @endcode 31 | 32 | `unroll` is now ready to be passed around. To retrieve it, you'll need to use 33 | the `unrolling` keyword. 34 | 35 | @include doc/tutorial04.cpp 36 | 37 | \section custom_02 Custom RABERU Keywords 38 | 39 | The keywords provided by **RABERU** can also be extended to propose a better user experience. 40 | This includes using user-defined type instead of **RABERU** long symbol to improve diagnostic 41 | , complex checks or provide custom display when using stream insertion of settings. 42 | 43 | \subsection custom-extension Extending RABERU Keywords 44 | Let's start again with our unrolling option. This time we want to be able to be sure nobody 45 | will use it with a non integral constant value and to display the value in a more informative way. 46 | To do so, we can inherits from `rbr::as_keyword`, a CRTP enabled base class: 47 | 48 | @code 49 | struct unrolling : rbr::as_keyword 50 | { 51 | template 52 | constexpr auto operator=(std::integral_constant const&) const noexcept 53 | { 54 | return rbr::option>{}; 55 | } 56 | 57 | std::ostream& display(std::ostream& os, auto v) const { return os << "Unroll Factor: " << v; } 58 | }; 59 | 60 | template inline constexpr auto unroll = (unrolling{} = std::integral_constant{}); 61 | @endcode 62 | 63 | What if we call `f( unrolling{} = 3.f );` ? Well, we go this error message: 64 | 65 | @code 66 | example.cpp:25:18: error: no viable overloaded '=' 67 | f( unrolling{} = 3.f ); 68 | ~~~~~~~~~~~ ^ ~~~ 69 | :8:18: note: candidate template ignored: could not match 'integral_constant' against 'float' 70 | constexpr auto operator=(std::integral_constant const&) const noexcept 71 | @endcode 72 | 73 | \subsection custom-display Custom Keywords Display 74 | Let's now improve the output of the option. Currently, the output is like: 75 | 76 | @code 77 | [unrolling] : 8 (std::integral_constant) 78 | @endcode 79 | 80 | A bit verbose especially for end-user. 81 | Keyword-like entity can specialize a `display` member function to replace this output by a custom one. 82 | 83 | @code 84 | struct unrolling : rbr::as_keyword 85 | { 86 | template 87 | constexpr auto operator=(std::integral_constant const&) const noexcept 88 | { 89 | return rbr::option>{}; 90 | } 91 | 92 | std::ostream& display(std::ostream& os, auto v) const { return os << "Unroll Factor: " << v; } 93 | }; 94 | @endcode 95 | 96 | The `display` member takes the output stream and the actual value of the option to be displayed. 97 | One can then arrange those as they see fit, leading to a better output: 98 | 99 | @include doc/tutorial05.cpp 100 | 101 | **/ 102 | //================================================================================================== 103 | -------------------------------------------------------------------------------- /doc/index.hpp: -------------------------------------------------------------------------------- 1 | #error DO NOT INCLUDE - DOCUMENTATION PURPOSE ONLY 2 | 3 | //================================================================================================== 4 | //! \mainpage The Fancy Named Parameters Library 5 | //! 6 | //! **RABERU** provides a way to define and use named parameters, *i.e* a list of values assigned to 7 | //! arbitrary keyword-like identifiers, to functions. 8 | //! 9 | //! It does so by providing: 10 | //! 11 | //! * a protocol to define such keywords. 12 | //! * a type to process such aggregate of parameters. 13 | //! * a `constexpr`-compatible implementation for all of those. 14 | //! 15 | //! # A Short Example 16 | //! 17 | //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++ 18 | //! #include 19 | //! #include 20 | //! #include 21 | //! 22 | //! using namespace rbr::literals; 23 | //! 24 | //! template 25 | //! auto replicate( P0 p0, P1 p1 ) 26 | //! { 27 | //! auto const params = rbr::settings(p0,p1); 28 | //! return std::string( params["replication"_kw], params["letter"_kw] ); 29 | //! } 30 | //! 31 | //! int main() 32 | //! { 33 | //! std::cout << replicate("replication"_kw = 9, "letter"_kw = 'z' ) << "\n"; 34 | //! std::cout << replicate("letter"_kw = '!' , "replication"_kw = 3) << "\n"; 35 | //! } 36 | //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 37 | //! 38 | //! # Licence 39 | //! 40 | //! This library is licensed under the [Boost Software License](https://opensource.org/licenses/BSL-1.0): 41 | //! 42 | //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ none 43 | //! Copyright : RABERU Project Contributors 44 | //! 45 | //! Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the 46 | //! software and accompanying documentation covered by this license (the "Software") to use, reproduce, 47 | //! display, distribute, execute, and transmit the Software, and to prepare derivative works of the 48 | //! Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the 49 | //! following: 50 | //! 51 | //! The copyright notices in the Software and this entire statement, including the above license grant, 52 | //! this restriction and the following disclaimer, must be included in all copies of the Software, in 53 | //! whole or in part, and all derivative works of the Software, unless such copies or derivative works 54 | //! are solely in the form of machine-executable object code generated by a source language processor. 55 | //! 56 | //! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 57 | //! NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 58 | //! NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE 59 | //! BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING 60 | //! FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 61 | //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 62 | //! 63 | //================================================================================================== 64 | -------------------------------------------------------------------------------- /doc/layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /doc/licence.md: -------------------------------------------------------------------------------- 1 | Licence {#licence} 2 | ======= 3 | 4 | This library is licensed under the [Boost Software License](https://opensource.org/licenses/BSL-1.0): 5 | 6 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ none 7 | Copyright : RABERU Project Contributors 8 | 9 | Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the 10 | software and accompanying documentation covered by this license (the "Software") to use, reproduce, 11 | display, distribute, execute, and transmit the Software, and to prepare derivative works of the 12 | Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the 13 | following: 14 | 15 | The copyright notices in the Software and this entire statement, including the above license grant, 16 | this restriction and the following disclaimer, must be included in all copies of the Software, in 17 | whole or in part, and all derivative works of the Software, unless such copies or derivative works 18 | are solely in the form of machine-executable object code generated by a source language processor. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 22 | NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE 23 | BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 26 | -------------------------------------------------------------------------------- /doc/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfalcou/raberu/3c94ac628a80ac9d21e71b4e3c5719e80a82a684/doc/logo.png -------------------------------------------------------------------------------- /doc/setup.hpp: -------------------------------------------------------------------------------- 1 | #error DO NOT INCLUDE - DOCUMENTATION PURPOSE ONLY 2 | 3 | //================================================================================================== 4 | /** 5 | @page setup Setup 6 | 7 | @tableofcontents 8 | 9 | @section setup-source Install from the source 10 | 11 | Code source of **RABERU** is available on GitHub and can be retrieved via the following command: 12 | 13 | @code 14 | $ git clone https://github.com/jfalcou/raberu.git 15 | @endcode 16 | 17 | Once retrieved, you should have a `raberu` folder which contains the whole source code. 18 | 19 | Create a `build` directory here and enter it. Once in the `build` directory, 20 | you can use **CMake** to generate the build system for **RABERU**. We recommend using 21 | Ninja but any build system is fine. 22 | 23 | @code 24 | $ mkdir build 25 | $ cd build 26 | $ cmake .. -G Ninja 27 | @endcode 28 | 29 | Once **CMake** completes, you can use the `install` target to build and install **RABERU**. 30 | By default, the library will be installed in the `/usr/local` directory, thus requiring 31 | root privileges. 32 | 33 | @code 34 | $ sudo ninja install 35 | @endcode 36 | 37 | You can select an alternative installation path by specifying the `CMAKE_INSTALL_PREFIX` 38 | option at configuration time. 39 | 40 | @code 41 | $ cmake .. -G Ninja -DCMAKE_INSTALL_PREFIX=path/to/install 42 | $ ninja install 43 | @endcode 44 | 45 | Once installed, **RABERU** is usable directly by providing the path to its installed files. 46 | 47 | @section setup-standalone Standalone setup 48 | 49 | You can also use **RABERU** via a single standalone file that can be vendored in your own project without 50 | having to deal with **RABERU** as a dependency. 51 | 52 | Simply use `wget` to fetch the latest version and place it where you want: 53 | 54 | @code 55 | wget https://raw.githubusercontent.com/jfalcou/raberu/main/standalone/raberu/raberu.hpp 56 | @endcode 57 | 58 | Use **RABERU** by just compiling your code with the include path pointing to the location of this single file. 59 | 60 | @section setup-fetchcontent CMake FetchContent 61 | 62 | You can also use CMake FetchContent operation and use the `raberu::raberu` library target that our CMake exports. 63 | 64 | @code{cmake} 65 | ##================================================================================================== 66 | ## Your project setup 67 | ##================================================================================================== 68 | cmake_minimum_required(VERSION 3.22) 69 | project(raberu-fetch LANGUAGES CXX) 70 | 71 | include(FetchContent) 72 | FetchContent_Declare(raberu GIT_REPOSITORY "https://github.com/jfalcou/raberu.git") 73 | FetchContent_MakeAvailable(raberu) 74 | 75 | add_executable(test_raberu ../main.cpp) 76 | target_link_libraries(test_raberu PUBLIC raberu::raberu) 77 | @endcode 78 | 79 | @section setup-cpm Setup with CPM 80 | 81 | The **RABERU** library can be setup using [CPM](https://github.com/cpm-cmake/CPM.cmake): 82 | 83 | @code{cmake} 84 | ##================================================================================================== 85 | ## Your project setup 86 | ##================================================================================================== 87 | cmake_minimum_required(VERSION 3.18) 88 | project(raberu-cpm LANGUAGES CXX) 89 | 90 | # Setup CPM - See https://github.com/cpm-cmake/CPM.cmake#adding-cpm 91 | include(cpm.cmake) 92 | 93 | CPMAddPackage ( NAME raberu 94 | GIT_REPOSITORY "https://github.com/jfalcou/raberu.git" 95 | OPTIONS "RABERU_BUILD_TEST OFF" 96 | ) 97 | 98 | add_executable(test_raberu ../main.cpp) 99 | target_link_libraries(test_raberu PUBLIC raberu::raberu) 100 | @endcode 101 | **/ 102 | //================================================================================================== 103 | -------------------------------------------------------------------------------- /doc/tutorial.hpp: -------------------------------------------------------------------------------- 1 | #error DO NOT INCLUDE - DOCUMENTATION PURPOSE ONLY 2 | 3 | //================================================================================================== 4 | /** 5 | \page tutorial RABERU 101 6 | 7 | @tableofcontents 8 | 9 | The **RABERU** library provides a way to define and use named parameters, *i.e* a list of values assigned to 10 | arbitrary keyword-like identifiers, to functions. 11 | 12 | It does so by providing: 13 | 14 | + a protocol to define such keywords. 15 | + a type to process such aggregate of parameters. 16 | + a `constexpr`-compatible implementation for all of those. 17 | 18 | 19 | \section tutorial_01 Keyword, Options, Settings 20 | 21 | Let's define a small function - `replicate` - that takes a character `c` and an integer `n` as parameters and 22 | return a string containing `c` repeated `n` times. As we want our users to have maximum flexibility, we will 23 | pass those parameters as keyword/value pairs. 24 | 25 | @include doc/tutorial01.cpp 26 | 27 | Let's decompose this code: 28 | 29 | + First, we define the `replicate` function. It takes two parameters which model 30 | rbr::concepts::option, ensuring the parameters are valid **RABERU** key/value pairs. 31 | + Those parameters are then turned into an instance of rbr::settings which will provide the interface to query values from the bundle of parameters. 32 | + We retrieve the value associated to the `"replication"_kw` and `"letter"_kw` keywords. 33 | + In the `main` function, we call `replicate` by passing key/value pairs. Note that the keys are the exact same identifiers than those used inside the function. Their order is irrelevant. 34 | 35 | That's it. The `replicate` function can now takes keywords arguments and as long as the proper keywords are used, it will work as intended. 36 | 37 | \section tutorial_02 Flavor of Keywords 38 | 39 | \subsection tutorial-keywords Regular keywords 40 | 41 | Let's say you want to pass a compile-time unrolling factor to some algorithm. 42 | You can use a regular keyword as seen in the tutorial: 43 | 44 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++ 45 | auto x = my_algorithm( "unroll"_kw = std::integral_constant{}); 46 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 47 | 48 | This is working but a bit verbose. Another issue can be that documenting the fact 49 | that your functions awaits a `"unroll"_kw` maybe cumbersome. 50 | 51 | A nicer way to simplify the user experience is to preemptively defines a keyword variable. 52 | 53 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++ 54 | inline constexpr auto unroll = "unroll"_kw; 55 | 56 | auto x = my_algorithm( unroll = std::integral_constant{}); 57 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 58 | 59 | Slightly terser and far easier to document. 60 | You can also use the rbr::keyword factory that takes an ID and returns a keyword instance 61 | 62 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++ 63 | inline constexpr auto unroll = rbr::keyword("unroll"_id); 64 | 65 | auto x = my_algorithm( unroll = std::integral_constant{}); 66 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 67 | 68 | \subsection tutorial-flags Flags 69 | Sometimes, you just want to check if a given parameter has been passed but you don't really care about an associated value. Such keyword parameters are **flags**, carrying information about their sole presence without the need ot be bound to a value. 70 | 71 | They work in a similar way than regular keyword parameters but use the `_fl` user-defined literal 72 | ior the rbr::flag factory. Their value can be retrieved via rbr::settings::operator[]. If present, the value returned is `std::true_type`, otherwise `std::false_type` is returned. 73 | 74 | @include doc/tutorial02.cpp 75 | 76 | \subsection tutorial-checked Checked keywords 77 | Regular keywords accept value of any types. Flag keyword implicitly behaves as boolean parameters. 78 | What if you need to have a keyword accepting values of a specific type ? Or, in more complex 79 | context, what if you need a keyword accepting values which types satisfy an arbitrary set of 80 | constraints ? 81 | 82 | To do so, we'll need to use the rbr::keyword factory function that 83 | accepts an optional template parameter. If this template parameter is a type, 84 | the keyword is setup to only accept value of this exact type. 85 | 86 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++ 87 | using namespace rbr::literals; 88 | 89 | // color can only accept unsigned 32 bits integer 90 | auto color = rbr::keyword("color"_id); 91 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 92 | 93 | If this template parameter is a unary template meta-function `F`, the keyword is setup to only 94 | accept value which type satisfy `F::value == true`. 95 | 96 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++ 97 | using namespace rbr::literals; 98 | 99 | template struct large_type 100 | { 101 | static constexpr auto value = sizeof(T) >= 4; 102 | }; 103 | 104 | // entropy can only accept types of at least 32 bits 105 | inline constexpr auto entropy = rbr::keyword( "entropy"_id); 106 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 107 | 108 | \section tutorial_03 Settings 109 | 110 | Another important **RABERU** component is rbr::settings. It aggregates key/value pairs in a way their 111 | exploitation is simplified. rbr::settings provides functions for retrieving value from keywords, 112 | inspect the stored keywords and more. 113 | 114 | \subsection tutorial-settings Defining a Settings 115 | rbr::settings can be directly constructed from an arbitrary list of options, ie values bound to 116 | a keyword. Once constructed, its operator[] can be used to fetch the value of a given keyword. 117 | 118 | @include doc/tutorial03.cpp 119 | 120 | \subsection tutorial-stream Stream insertion 121 | rbr::settings can be streamed to display the list of keyword/value pairs it contains 122 | 123 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++ 124 | #include 125 | #include 126 | 127 | int main() 128 | { 129 | using namespace rbr::literals; 130 | 131 | auto values = rbr::settings("size"_kw = 75ULL, "transparent"_fl, "value"_kw = 7.7f); 132 | 133 | std::cout << values << "\n"; 134 | } 135 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 136 | 137 | The expected output should be: 138 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 139 | 'size' : 75 (long long unsigned int) 140 | 'transparent' : 1 (std::integral_constant) 141 | 'value' : 7.7 (float) 142 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 143 | **/ 144 | //================================================================================================== 145 | -------------------------------------------------------------------------------- /include/raberu/impl/algo.hpp: -------------------------------------------------------------------------------- 1 | //====================================================================================================================== 2 | /* 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //====================================================================================================================== 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | -------------------------------------------------------------------------------- /include/raberu/impl/algo/drop.hpp: -------------------------------------------------------------------------------- 1 | //====================================================================================================================== 2 | /* 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //====================================================================================================================== 8 | #pragma once 9 | 10 | namespace rbr 11 | { 12 | namespace _ 13 | { 14 | template 15 | struct filter 16 | { 17 | using type = _::keys; 18 | 19 | template constexpr auto operator+(keys const&) const 20 | { 21 | using kw_t = typename T::keyword_type; 22 | if constexpr(!stdfix::same_as) return filter{}; 23 | else return *this; 24 | } 25 | }; 26 | 27 | template< typename K, typename S> struct select_keys; 28 | 29 | template< typename K, concepts::option... Os> 30 | struct select_keys> 31 | : decltype((filter{} + ... + _::keys{})) 32 | { 33 | }; 34 | } 35 | 36 | //==================================================================================================================== 37 | //! @ingroup stng 38 | //! @related rbr::settings 39 | //! @brief Remove an option from a rbr::settings 40 | //! 41 | //! Build a rbr::settings containing all options from s except for any option bound to the `k` 42 | //! rbr::keyword. 43 | //! 44 | //! @param k Keyword to remove 45 | //! @param s Original rbr::settings 46 | //! @return An instance of rbr::settings containing all options of `s` except those bound to `k`. 47 | //! 48 | //! ## Example: 49 | //! @include doc/drop.cpp 50 | //==================================================================================================================== 51 | template 52 | [[nodiscard]] constexpr auto drop([[maybe_unused]] K const& k, settings const& s) 53 | { 54 | using selected_keys_t = typename _::select_keys>::type; 55 | 56 | return [&]( _::keys ) 57 | { 58 | // Rebuild a new settings by going over the keys that we keep 59 | return rbr::settings{ (Ks{} = s[Ks{}] )...}; 60 | }(selected_keys_t{}); 61 | } 62 | 63 | namespace result 64 | { 65 | template 66 | struct drop 67 | { 68 | using type = decltype( rbr::drop(std::declval(),std::declval()...) ); 69 | }; 70 | 71 | template 72 | using drop_t = typename drop::type; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /include/raberu/impl/algo/fetch.hpp: -------------------------------------------------------------------------------- 1 | //====================================================================================================================== 2 | /* 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //====================================================================================================================== 8 | #pragma once 9 | 10 | namespace rbr 11 | { 12 | //==================================================================================================================== 13 | //! @ingroup stng 14 | //! @brief Retrieved a value via a keyword 15 | //! 16 | //! Retrieve the value bound to a given keyword `k` inside a variadic list of rbr::options. 17 | //! If such a keyword is not present, either an instance of rbr::unknown_key is returned or 18 | //! a default value or function call will be returned. 19 | //! 20 | //! @param k Keywords to check 21 | //! @param os Options to inspect 22 | //! @return If any, the value bound to `k`. 23 | //! 24 | //! ## Helper Types 25 | //! @code 26 | //! namespace rbr::result 27 | //! { 28 | //! template struct fetch 29 | //! 30 | //! template 31 | //! using fetch_t = typename fetch::type; 32 | //! } 33 | //! @endcode 34 | //! 35 | //! Return the type of a call to rbr::fetch. 36 | //! 37 | //! ## Example: 38 | //! @include doc/fetch.cpp 39 | //==================================================================================================================== 40 | template 41 | constexpr decltype(auto) fetch(K const& k, Os const&... os) 42 | { 43 | auto const opts = settings(os...); 44 | return opts[k]; 45 | } 46 | 47 | //! @overload 48 | template 49 | constexpr decltype(auto) fetch(_::type_or_ const& k, Os const&... os) 50 | { 51 | auto const opts = settings(os...); 52 | return opts[k]; 53 | } 54 | 55 | //! @overload 56 | template 57 | constexpr decltype(auto) fetch(K const& k, Settings const& opts) 58 | { 59 | return opts[k]; 60 | } 61 | 62 | namespace result 63 | { 64 | template struct fetch; 65 | 66 | template 67 | struct fetch 68 | { 69 | using type = decltype( rbr::fetch(Keyword, std::declval()...) ); 70 | }; 71 | 72 | template 73 | struct fetch 74 | { 75 | using type = decltype( rbr::fetch(Keyword, std::declval()) ); 76 | }; 77 | 78 | template 79 | using fetch_t = typename fetch::type; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /include/raberu/impl/algo/is_equivalent.hpp: -------------------------------------------------------------------------------- 1 | //====================================================================================================================== 2 | /* 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //====================================================================================================================== 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace rbr 13 | { 14 | //==================================================================================================================== 15 | //! @ingroup stng 16 | //! @brief Checks the equivalence of two rbr::settings 17 | //! 18 | //! Two rbr::settings are equivalent if they contain the same exact set of keywords irregardless 19 | //! of their values or value types. 20 | //! 21 | //! @tparam S1 rbr::settings to compare 22 | //! @tparam S2 rbr::settings to compare 23 | //! 24 | //! ## Helper Value 25 | //! @code 26 | //! namespace rbr 27 | //! { 28 | //! template 29 | //! inline constexpr bool is_equivalent_v = is_equivalent::value; 30 | //! } 31 | //! @endcode 32 | //! 33 | //! Contains the result of a call to rbr::is_equivalent. 34 | //! 35 | //! ## Example: 36 | //! @include doc/is_equivalent.cpp 37 | //==================================================================================================================== 38 | template 39 | struct is_equivalent 40 | : std::bool_constant< _::is_equivalent< result::keywords_t 41 | , result::keywords_t 42 | >::value 43 | && _::is_equivalent< result::keywords_t 44 | , result::keywords_t 45 | >::value 46 | > 47 | {}; 48 | 49 | template 50 | inline constexpr bool is_equivalent_v = is_equivalent::value; 51 | } 52 | -------------------------------------------------------------------------------- /include/raberu/impl/algo/keys_values.hpp: -------------------------------------------------------------------------------- 1 | //====================================================================================================================== 2 | /* 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //====================================================================================================================== 8 | #pragma once 9 | 10 | namespace rbr 11 | { 12 | namespace result 13 | { 14 | template class List = types> struct keywords; 15 | template class List = types> struct values; 16 | 17 | template class List> 18 | struct keywords, List> 19 | { 20 | using type = List; 21 | }; 22 | 23 | template class List> 24 | struct values, List> 25 | { 26 | using type = List; 27 | }; 28 | 29 | template class List = types> 30 | using keywords_t = typename keywords::type; 31 | 32 | template class List = types> 33 | using values_t = typename values::type; 34 | } 35 | 36 | //==================================================================================================================== 37 | //! @ingroup stng 38 | //! @brief Retrieved the list of all keywords in a settings 39 | //! 40 | //! @tparam List A n-ary template type to hold the result values 41 | //! @param s Settings to inspect 42 | //! @return An instance of rbr::type containing all the keyword from a rbr::settings. 43 | //! 44 | //! ## Helper Types 45 | //! @code 46 | //! namespace rbr::result 47 | //! { 48 | //! template class List, typename Settings> struct keywords; 49 | //! 50 | //! template class List, typename Settings> 51 | //! using keywords_t = typename keywords::type; 52 | //! } 53 | //! @endcode 54 | //! 55 | //! Return the type of a call to rbr::keywords. 56 | //! 57 | //! ## Example: 58 | //! @include doc/keywords.cpp 59 | //==================================================================================================================== 60 | template class List, typename... Opts> 61 | constexpr auto keywords([[maybe_unused]]rbr::settings const& s) 62 | { 63 | return result::keywords_t,List>{typename Opts::keyword_type{}...}; 64 | } 65 | 66 | //==================================================================================================================== 67 | //! @ingroup stng 68 | //! @brief Retrieved the list of all value stored in a settings 69 | //! 70 | //! @tparam List A n-ary template type to hold the result 71 | //! @param s Settings to inspect 72 | //! @return an instance of rbr::type containing all the values from a rbr::settings. 73 | //! 74 | //! ## Helper Types 75 | //! @code 76 | //! namespace rbr::result 77 | //! { 78 | //! template class List, typename Settings> struct values; 79 | //! 80 | //! template class List, typename Settings> 81 | //! using values_t = typename values::type; 82 | //! } 83 | //! @endcode 84 | //! 85 | //! Return the type of a call to rbr::values. 86 | //! 87 | //! ## Example: 88 | //! @include doc/values.cpp 89 | //==================================================================================================================== 90 | template class List, typename... Opts> 91 | constexpr auto values(rbr::settings const& s) 92 | { 93 | return result::values_t,List>{ s[typename Opts::keyword_type{}]... }; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /include/raberu/impl/algo/merge.hpp: -------------------------------------------------------------------------------- 1 | //====================================================================================================================== 2 | /* 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //====================================================================================================================== 8 | #pragma once 9 | 10 | namespace rbr 11 | { 12 | //================================================================================================ 13 | //! @ingroup stng 14 | //! @related rbr::settings 15 | //! @brief Merge two instances of rbr::settings 16 | //! 17 | //! Merge all options of `opts` and `defs`. If an options is present in both arguments, the one 18 | //! from `opts` is used. 19 | //! 20 | //! @param opts rbr::settings to merge 21 | //! @param defs rbr::settings acting as default value 22 | //! @return An instance of rbr::settings containing all options from `opts` and any options 23 | //! from `defs` not present in `opts`. 24 | //! ## Example: 25 | //! @include doc/merge.cpp 26 | //================================================================================================ 27 | template 28 | constexpr auto merge(settings const& opts, settings const& defs) noexcept 29 | { 30 | auto selector = [](K const&, Opts const& o, auto const& d) 31 | { 32 | constexpr K key; 33 | if constexpr( Opts::contains(key) ) return (key = o[key]); 34 | else return (key = d[key]); 35 | }; 36 | 37 | auto select = [&](_::keys const&, auto const& os, auto const& ds) 38 | { 39 | return settings(selector(Ks{},os,ds)...); 40 | }; 41 | 42 | return select(typename _::uniques<_::keys 43 | ,_::keys 44 | >::type{},opts,defs); 45 | } 46 | 47 | namespace result 48 | { 49 | template 50 | struct merge 51 | { 52 | using type = decltype( rbr::merge(std::declval(),std::declval()) ); 53 | }; 54 | 55 | template 56 | using merge_t = typename merge::type; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /include/raberu/impl/concepts.hpp: -------------------------------------------------------------------------------- 1 | //====================================================================================================================== 2 | /* 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //====================================================================================================================== 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | //====================================================================================================================== 15 | //! @namespace rbr::concepts 16 | //! @brief Raberu Concepts namespace 17 | //====================================================================================================================== 18 | namespace rbr::concepts 19 | { 20 | //==================================================================================================================== 21 | //! @brief Keyword concept 22 | //! 23 | //! A Keyword type is able to be bound to a value as an [Option](@ref rbr::concepts::option) 24 | //==================================================================================================================== 25 | template concept keyword = requires( K k ) 26 | { 27 | typename K::tag_type; 28 | { K::template accept() } -> stdfix::same_as; 29 | }; 30 | 31 | //==================================================================================================================== 32 | //! @brief Option concept 33 | //! 34 | //! An Option type can be aggregated in a [Settings](@ref rbr::concepts::settings) and be 35 | //! fetched later 36 | //==================================================================================================================== 37 | template concept option = requires( O const& o ) 38 | { 39 | { o(typename std::remove_cvref_t::keyword_type{}) } 40 | -> stdfix::same_as::stored_value_type>; 41 | }; 42 | 43 | //==================================================================================================================== 44 | //! @brief Settings concept 45 | //! 46 | //! A Settings is a group of [Options](@ref rbr::concepts::option) 47 | //==================================================================================================================== 48 | template concept settings = requires( S const& s ) 49 | { 50 | typename S::rbr_settings; 51 | }; 52 | 53 | //==================================================================================================================== 54 | //! @brief Exact match concept helper 55 | //! 56 | //! rbr::concepts::exactly is to be used to constraint functions template parameter to be an 57 | //! instantiation of a precise [Keyword](@ref rbr::concepts::keyword) 58 | //==================================================================================================================== 59 | template 60 | concept exactly = stdfix::same_as < typename Option::keyword_type 61 | , std::remove_cvref_t 62 | >; 63 | } 64 | 65 | // Internal concepts 66 | namespace rbr::_ 67 | { 68 | // Check for check() 69 | template 70 | concept checks_for = requires(K) 71 | { 72 | { K::template check() }; 73 | }; 74 | 75 | // Checks for identifier 76 | template 77 | concept identifiable = requires(T t) 78 | { 79 | { t.identifier }; 80 | }; 81 | 82 | // Checks for identifier 83 | template 84 | concept self_identifiable = requires(T t, std::ostream& os) 85 | { 86 | { os << t }; 87 | }; 88 | 89 | // Checks for display 90 | template 91 | concept displayable = requires(T t, std::ostream& os, V v) 92 | { 93 | { t.display(os,v) }; 94 | }; 95 | 96 | // Concept to constraint size 97 | template 98 | concept fits = (N <= M); 99 | } 100 | -------------------------------------------------------------------------------- /include/raberu/impl/helpers.hpp: -------------------------------------------------------------------------------- 1 | //====================================================================================================================== 2 | /* 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //====================================================================================================================== 8 | #pragma once 9 | 10 | #include 11 | 12 | #define RBR_FWD(...) static_cast(__VA_ARGS__) 13 | 14 | // Fix for non-conformant libcpp 15 | namespace rbr::stdfix 16 | { 17 | template 18 | concept is_same_impl = std::is_same_v; 19 | 20 | template 21 | concept same_as = is_same_impl && is_same_impl; 22 | } 23 | 24 | // Helpers for working on list of keys as unique lists - needed by merge and some contains_* 25 | namespace rbr::_ 26 | { 27 | template struct keys {}; 28 | 29 | template struct contains; 30 | 31 | template 32 | struct contains> : std::bool_constant<(stdfix::same_as || ...)> 33 | {}; 34 | 35 | template struct append_if_impl; 36 | 37 | template struct append_if_impl,true> 38 | { 39 | using type = keys; 40 | }; 41 | 42 | template struct append_if_impl,false> 43 | { 44 | using type = keys; 45 | }; 46 | 47 | template struct append_if; 48 | 49 | template 50 | struct append_if : append_if_impl::value> 51 | {}; 52 | 53 | template struct uniques; 54 | 55 | template 56 | struct uniques> 57 | : uniques< typename append_if::type, keys > 58 | {}; 59 | 60 | template struct uniques> { using type = K1s; }; 61 | 62 | template struct contain_all; 63 | 64 | template 65 | struct contain_all> : std::bool_constant<(contains::value && ...)> 66 | {}; 67 | 68 | template struct contain_all> : std::false_type {}; 69 | template struct contain_all, K2s > : std::false_type {}; 70 | template<> struct contain_all,keys<>> : std::true_type {}; 71 | 72 | template 73 | struct is_equivalent : std::bool_constant::value && contain_all::value> 74 | {}; 75 | } 76 | 77 | namespace rbr 78 | { 79 | //==================================================================================================================== 80 | //! @ingroup utility 81 | //! @brief Lightweight variadic type list 82 | //==================================================================================================================== 83 | template struct types {}; 84 | } 85 | -------------------------------------------------------------------------------- /include/raberu/impl/keywords.hpp: -------------------------------------------------------------------------------- 1 | //====================================================================================================================== 2 | /* 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //====================================================================================================================== 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | //====================================================================================================================== 15 | //! @defgroup main Main RABERU components 16 | //! 17 | //! @ingroup main 18 | //! @{ 19 | //! @defgroup kwds Keywords definitions and handling 20 | //! @brief Functions and types to handle RABERU keywords 21 | //! @} 22 | //====================================================================================================================== 23 | namespace rbr 24 | { 25 | //==================================================================================================================== 26 | //! @ingroup kwds 27 | //! @brief Callable object wrapper for functional default value 28 | //! @tparam Func Callable object to keep 29 | //==================================================================================================================== 30 | template struct call 31 | { 32 | constexpr call(Func f) : callable(f) {} 33 | constexpr auto perform() const { return callable(); } 34 | Func callable; 35 | }; 36 | 37 | //==================================================================================================================== 38 | //! @ingroup stng 39 | //! @brief Callable object wrapper for functional default value 40 | //! @tparam Keyword Keyword for the option 41 | //! @tparam Value Value stored in the option 42 | //==================================================================================================================== 43 | template struct option 44 | { 45 | using stored_value_type = std::decay_t; 46 | using keyword_type = Keyword; 47 | 48 | constexpr stored_value_type operator()(keyword_type const&) const noexcept { return contents; } 49 | stored_value_type contents; 50 | }; 51 | 52 | //==================================================================================================================== 53 | //! @ingroup kwds 54 | //! @brief Base class for keyword definition 55 | //! 56 | //! rbr::as_keyword provides an CRTP base class for keyword-like types. It is internally used 57 | //! to provide specific keyword constructors but can be used to define user-defined keyword. 58 | //! 59 | //! @tparam Keyword Keyword type being defined 60 | //==================================================================================================================== 61 | template struct as_keyword 62 | { 63 | /// Derived keyword type 64 | using tag_type = Keyword; 65 | 66 | /// Keyword comparison 67 | inline constexpr auto operator<=>(as_keyword const&) const noexcept = default; 68 | 69 | //================================================================================================================== 70 | //! @brief Compile-time validation of value 71 | //! 72 | //! When a value is bound to a [Keyword](@ref rbr::concepts::keyword) to form an 73 | //! [Option](@ref rbr::concepts::option), one can validate this binding by checking arbitrary 74 | //! properties on the value type. This is done by the accept() member. 75 | //! 76 | //! If `Keyword` defines a `check` static template member function, it will be called to provide 77 | //! the return value of accept(). Otherwise, true is returned, thus automatically validating any 78 | //! value type. 79 | //! 80 | //! @tparam T Type to validate 81 | //! @return `true` if T is accepted by current keyword, `false` otherwise. 82 | //! 83 | //! ## Example: 84 | //! @snippet doc/accept.cpp Custom Accept 85 | //================================================================================================================== 86 | 87 | template 88 | static constexpr bool accept() 89 | { 90 | if constexpr(stdfix::same_as,as_keyword>) return true; 91 | else if constexpr(_::checks_for) return Keyword::template check(); 92 | else return true; 93 | } 94 | 95 | //================================================================================================================== 96 | //! @brief Assignment of a value to a keyword 97 | //! 98 | //! Bind a value to current [Keyword](@ref rbr::concepts::keyword) and returns an instance of 99 | //! an [Option](@ref rbr::concepts::option). 100 | //! 101 | //! @param v Bound value 102 | //! @return An rbr::option binding the keyword to `v`. 103 | //================================================================================================================== 104 | template 105 | constexpr auto operator=(Type&& v) const noexcept requires( accept() ) 106 | { 107 | return option{RBR_FWD(v)}; 108 | } 109 | 110 | //================================================================================================================== 111 | //! @brief Stream insertion function 112 | //! 113 | //! Display a textual description of current keyword and bound value over an output stream. 114 | //! 115 | //! If `Keyword` defines a `display` member variable, it will be used to perform this display. 116 | //! Otherwise, its value will be displayed along with either a user-defined identifier or its 117 | //! stringified typename. 118 | //! 119 | //! @param os Output stream 120 | //! @param v Value bound to current keyword 121 | //! @return The up-to-date output stream 122 | //! 123 | //! ## Example: 124 | //! @snippet doc/show.cpp Custom Show 125 | //================================================================================================================== 126 | template std::ostream& show(std::ostream& os, V const& v) const 127 | { 128 | if constexpr(_::displayable) return Keyword{}.display(os,v); 129 | else 130 | { 131 | if constexpr(_::identifiable) os << Keyword::identifier; 132 | else os << '[' << _::type.name() << ']'; 133 | 134 | return os << " : " << v << " (" << _::type.name() << ')'; 135 | } 136 | } 137 | 138 | /// Specify a default value for the keyword 139 | template 140 | constexpr auto operator|(Type&& v) const noexcept requires( accept() ) 141 | { 142 | return _::type_or_>{RBR_FWD(v)}; 143 | } 144 | 145 | /// Specify a Callable object as a default value for the keyword 146 | template constexpr auto operator|(call&& v) const noexcept 147 | { 148 | return _::type_or_>{RBR_FWD(v)}; 149 | } 150 | 151 | //================================================================================================================== 152 | //! @brief Keyword fetching from options set 153 | //! 154 | //! @param o Set of options to inspect 155 | //! @return f current keyword is present in `o...`, return its bound value. Otherwise, 156 | //! returns an instance of rbr::unknown_key. 157 | //! 158 | //! ## Example: 159 | //! @include doc/keyword_fetch.cpp 160 | //================================================================================================================== 161 | template 162 | constexpr decltype(auto) operator()(Os&&... o) const { return fetch(Keyword{}, RBR_FWD(o)...); } 163 | }; 164 | 165 | //==================================================================================================================== 166 | //! @ingroup kwds 167 | //! @brief Checked keyword 168 | //! 169 | //! A Checked keyword is a keyword that verify if a value's type satisfies a predicates before 170 | //! binding it 171 | //! 172 | //! @tparam ID Unique identifier for the keyword 173 | //! @tparam Checker Unary template meta-function acting as predicate 174 | //==================================================================================================================== 175 | template class Checker> 176 | struct checked_keyword : as_keyword> 177 | { 178 | using as_keyword>::operator=; 179 | template static constexpr bool check() { return Checker::value; } 180 | 181 | template 182 | std::ostream& display(std::ostream& os, V const& v) const 183 | { 184 | if constexpr(_::self_identifiable) os << ID{}; 185 | else 186 | { 187 | if constexpr(_::identifiable) os << ID::identifier; 188 | else os << '[' << _::type.name() << ']'; 189 | } 190 | 191 | os << " ::: " << v << " (" << _::type.name() << ") checked by '"; 192 | return os << _::type>.name() << '\''; 193 | } 194 | }; 195 | 196 | //==================================================================================================================== 197 | //! @ingroup kwds 198 | //! @brief Typed keyword 199 | //! 200 | //! A Typed keyword is a keyword that verify if a value's type is exactly matching a type. 201 | //! 202 | //! @tparam ID Unique identifier for the keyword 203 | //! @tparam Type Type to accept 204 | //==================================================================================================================== 205 | template 206 | struct typed_keyword : as_keyword> 207 | { 208 | using as_keyword>::operator=; 209 | template 210 | static constexpr bool check() { return std::is_same_v,Type>; } 211 | 212 | template 213 | std::ostream& display(std::ostream& os, V const& v) const 214 | { 215 | if constexpr(_::self_identifiable) os << ID{}; 216 | else 217 | { 218 | if constexpr(_::identifiable) os << ID::identifier; 219 | else os << '[' << _::type.name() << ']'; 220 | } 221 | 222 | return os << " : " << v << " of type '" << _::type.name() << '\''; 223 | } 224 | }; 225 | 226 | //==================================================================================================================== 227 | //! @ingroup kwds 228 | //! @brief Regular keyword 229 | //! 230 | //! A Regular keyword is a keyword that accepts any types. 231 | //! 232 | //! @tparam ID Unique identifier for the keyword 233 | //==================================================================================================================== 234 | template 235 | struct any_keyword : as_keyword> 236 | { 237 | using as_keyword>::operator=; 238 | 239 | /// ID type associated to the keyword 240 | using id_type = ID; 241 | 242 | template 243 | std::ostream& display(std::ostream& os, V const& v) const 244 | { 245 | if constexpr(_::self_identifiable) os << ID{}; 246 | else 247 | { 248 | if constexpr(_::identifiable) os << ID::identifier; 249 | else os << '[' << _::type.name() << ']'; 250 | } 251 | 252 | return os << " : " << v << " (" << _::type.name() << ')'; 253 | } 254 | }; 255 | 256 | //==================================================================================================================== 257 | //! @ingroup kwds 258 | //! @brief Flag keyword 259 | //! 260 | //! A Flag keyword is a keyword which value is given by its mere presence. It accepts no binding 261 | //! and return a value convertible to `bool` when set in a rbr::settings. 262 | //! 263 | //! By design, a flag is also its own rbr::option. 264 | //! 265 | //! @tparam ID Unique identifier for the keyword 266 | //==================================================================================================================== 267 | template struct flag_keyword 268 | { 269 | constexpr flag_keyword() {} 270 | constexpr flag_keyword(ID const&) {} 271 | 272 | /// ID type associated to the keyword 273 | using id_type = ID; 274 | 275 | template static constexpr bool accept() 276 | { 277 | return std::is_same_v; 278 | } 279 | 280 | std::ostream& show(std::ostream& os, bool) const 281 | { 282 | if constexpr(_::identifiable) os << ID::identifier; 283 | else if constexpr(_::self_identifiable) os << ID{}; 284 | else os << '[' << _::type.name() << ']'; 285 | 286 | return os << " : set"; 287 | } 288 | 289 | using tag_type = ID; 290 | using keyword_type = flag_keyword; 291 | using stored_value_type = bool; 292 | 293 | template 294 | constexpr auto operator=(Type&&) const noexcept { return *this; } 295 | 296 | template 297 | constexpr auto operator|(Type&& v) const noexcept 298 | { 299 | return _::type_or_>{RBR_FWD(v)}; 300 | } 301 | 302 | template constexpr auto operator|(call&& v) const noexcept 303 | { 304 | return _::type_or_>{RBR_FWD(v)}; 305 | } 306 | 307 | constexpr auto operator()(keyword_type const&) const noexcept { return true; } 308 | 309 | template 310 | constexpr decltype(auto) operator()(O0&&, O1&&, Os&&... ) const 311 | { 312 | return stdfix::same_as::keyword_type> 313 | || stdfix::same_as::keyword_type> 314 | || (stdfix::same_as::keyword_type> || ...); 315 | } 316 | }; 317 | 318 | //==================================================================================================================== 319 | //! @ingroup kwds 320 | //! @related rbr::flag_keyword 321 | //! @brief Create a flag keyword for reuse 322 | //! @param id Unique rbr::id_ for the keyword being built 323 | //! @return An instance of rbr::flag_keyword 324 | //! ## Example: 325 | //! @include doc/flag.cpp 326 | //==================================================================================================================== 327 | template 328 | constexpr flag_keyword flag([[maybe_unused]] Tag id) noexcept { return {}; } 329 | 330 | //==================================================================================================================== 331 | //! @ingroup kwds 332 | //! @related rbr::any_keyword 333 | //! @brief Create a regular keyword for reuse 334 | //! @param id Unique rbr::id_ for the keyword being built 335 | //! @return An instance of rbr::any_keyword 336 | //! ## Example: 337 | //! @include doc/regular.cpp 338 | //==================================================================================================================== 339 | template 340 | constexpr any_keyword keyword([[maybe_unused]] ID id) noexcept { return {}; } 341 | 342 | //==================================================================================================================== 343 | //! @ingroup kwds 344 | //! @related rbr::checked_keyword 345 | //! @brief Create a checked keyword for reuse 346 | //! @tparam Checker Unary template meta-function to use for validation 347 | //! @param id Unique rbr::id_ for the keyword being built 348 | //! @return An instance of rbr::checked_keyword 349 | //! ## Example: 350 | //! @include doc/checked.cpp 351 | //==================================================================================================================== 352 | template class Checker, typename ID> 353 | constexpr checked_keyword keyword([[maybe_unused]] ID id) noexcept { return {}; } 354 | 355 | //==================================================================================================================== 356 | //! @ingroup kwds 357 | //! @related rbr::typed_keyword 358 | //! @brief Create a typed Keyword for reuse 359 | //! @tparam Type Type accepted by the keyword 360 | //! @param id Unique rbr::id_ for the keyword being built 361 | //! @return An instance of rbr::checked_keyword 362 | //! ## Example: 363 | //! @include doc/checked.cpp 364 | //==================================================================================================================== 365 | template 366 | constexpr typed_keyword keyword([[maybe_unused]] ID id) noexcept { return {}; } 367 | 368 | namespace literals 369 | { 370 | //================================================================================================================== 371 | //! @ingroup udls 372 | //! @related rbr::any_keyword 373 | //! @brief Forms an instance of rbr::any_keyword from a literal string 374 | //! @return An instance of rbr::any_keyword using the specified string as ID 375 | //================================================================================================================== 376 | template 377 | constexpr auto operator""_kw() noexcept { return any_keyword>{}; } 378 | 379 | //================================================================================================================== 380 | //! @ingroup udls 381 | //! @related rbr::flag_keyword 382 | //! @brief Forms an instance of rbr::flag_keyword from a literal string 383 | //! @return An instance of rbr::flag_keyword using the specified string as ID 384 | //================================================================================================================== 385 | template 386 | constexpr auto operator""_fl() noexcept { return flag_keyword>{}; } 387 | } 388 | } 389 | -------------------------------------------------------------------------------- /include/raberu/impl/literals.hpp: -------------------------------------------------------------------------------- 1 | //====================================================================================================================== 2 | /* 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //====================================================================================================================== 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | //====================================================================================================================== 18 | //! @defgroup utility Helper types and function 19 | //! @brief Tools for interacting with Raberu components 20 | //====================================================================================================================== 21 | 22 | //====================================================================================================================== 23 | //! @ingroup utility 24 | //! @{ 25 | //! @defgroup udls User-defined Literal operators 26 | //! @brief UDL operators 27 | //! @} 28 | //====================================================================================================================== 29 | namespace rbr::_ 30 | { 31 | // Lightweight container of value in alternatives 32 | template struct type_or_ 33 | { 34 | V value; 35 | 36 | template 37 | constexpr decltype(auto) operator()(Os&&... os) const { return fetch(*this, RBR_FWD(os)...); } 38 | }; 39 | 40 | // Type -> String converter 41 | template constexpr auto typer() noexcept 42 | { 43 | #if defined(__clang__) 44 | constexpr auto pfx = std::string_view("auto rbr::_::typer() [T = ").size(); 45 | constexpr auto sfx = std::string_view("]").size(); 46 | constexpr auto raw = std::string_view(__PRETTY_FUNCTION__); 47 | #elif defined(__GNUC__) 48 | constexpr auto pfx = std::string_view("constexpr auto rbr::_::typer() [with " "T = ").size(); 49 | constexpr auto sfx = std::string_view("]").size(); 50 | constexpr auto raw = std::string_view(__PRETTY_FUNCTION__); 51 | #elif defined(_MSC_VER) 52 | constexpr auto pfx = std::string_view("auto __cdecl rbr::_::typer<").size(); 53 | constexpr auto sfx = std::string_view(">(void)").size(); 54 | constexpr auto raw = std::string_view(__FUNCSIG__); 55 | #endif 56 | auto value = raw; 57 | value.remove_prefix(pfx); 58 | value.remove_suffix(sfx); 59 | 60 | constexpr auto size = raw.size() - (pfx + sfx); 61 | auto fn = [&](std::index_sequence) 62 | { 63 | return std::array{value[Is]...}; 64 | }; 65 | 66 | return fn(std::make_index_sequence{}); 67 | } 68 | 69 | template inline constexpr auto type_array = typer(); 70 | 71 | template> 72 | struct type_t 73 | { 74 | static constexpr auto name() { return std::string_view(ID.data(), ID.size());} 75 | }; 76 | 77 | template 78 | inline constexpr auto type = type_t{}; 79 | } 80 | 81 | 82 | #if !defined(RBR_MAX_LITERAL_SIZE) 83 | #define RBR_MAX_LITERAL_SIZE 32 84 | #endif 85 | 86 | namespace rbr 87 | { 88 | //==================================================================================================================== 89 | //! @namespace rbr::literals 90 | //! @brief Raberu literals namespace 91 | //==================================================================================================================== 92 | namespace literals 93 | { 94 | //================================================================================================================== 95 | //! @ingroup utility 96 | //! @brief Compile-time static string 97 | //================================================================================================================== 98 | struct str 99 | { 100 | static constexpr std::size_t max_size = RBR_MAX_LITERAL_SIZE; 101 | 102 | char data_[max_size+1]; 103 | std::uint8_t size_; 104 | 105 | template 106 | requires _::fits 107 | constexpr str(const char (&s)[N], std::index_sequence) : data_{s[Is]...}, size_(N) 108 | {} 109 | 110 | template 111 | requires _::fits 112 | constexpr str(const char (&s)[N]) : str{s, std::make_index_sequence{}} 113 | {} 114 | 115 | constexpr std::size_t size() const { return size_; } 116 | constexpr std::string_view value() const { return std::string_view(&data_[0],size_); } 117 | 118 | friend std::ostream& operator<<(std::ostream& os, str const& s) 119 | { 120 | return os << '\'' << s.value() << '\''; 121 | } 122 | }; 123 | } 124 | 125 | //==================================================================================================================== 126 | //! @ingroup utility 127 | //! @brief Compile-time text based ID 128 | //! @tparam ID Compile-time string for the ID 129 | //==================================================================================================================== 130 | template struct id_ 131 | { 132 | /// Inserts an rbr::id_ in an output stream 133 | friend std::ostream& operator<<(std::ostream& os, id_ const&) 134 | { 135 | return os << ID; 136 | } 137 | }; 138 | 139 | namespace literals 140 | { 141 | //================================================================================================================== 142 | //! @ingroup udls 143 | //! @brief Forms an ID constant literal 144 | //! @return An instance of rbr::id_ for the specified string 145 | //================================================================================================================== 146 | template constexpr auto operator""_id() noexcept { return id_{}; } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /include/raberu/impl/settings.hpp: -------------------------------------------------------------------------------- 1 | //====================================================================================================================== 2 | /* 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //====================================================================================================================== 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | //================================================================================================== 15 | //! @ingroup main 16 | //! @{ 17 | //! @defgroup stng Settings definitions and handling 18 | //! @brief Functions and types to handle RABERU settings 19 | //! @} 20 | //================================================================================================== 21 | 22 | namespace rbr 23 | { 24 | /// Type indicating that a [Keyword](@ref rbr::concepts::keyword) is not available 25 | struct unknown_key { using type = unknown_key; }; 26 | 27 | // Option calls aggregator 28 | template struct aggregator : Ts... 29 | { 30 | constexpr aggregator(Ts const&...t) noexcept : Ts(t)... {} 31 | using Ts::operator()...; 32 | 33 | template constexpr auto operator()(K const &) const noexcept 34 | { 35 | return unknown_key {}; 36 | } 37 | }; 38 | 39 | //================================================================================================ 40 | //! @ingroup stng 41 | //! @brief Defines a group of options for processing 42 | //! 43 | //! rbr::settings acts as an aggregation of [Options](@ref rbr::concepts::option) (ie pair of 44 | //! [Keyword](@ref rbr::concepts::keyword)/value) that provides an user-interface for accessing 45 | //! or managing said [Options](@ref rbr::concepts::option) and to gather informations. 46 | //! 47 | //! @tparam Opts List of [options](@ref rbr::concepts::option) aggregated 48 | //================================================================================================ 49 | template struct settings 50 | { 51 | using rbr_settings = void; 52 | using base = aggregator; 53 | 54 | /// Constructor from a variadic pack of rbr::concepts::option 55 | constexpr settings(Opts const&... opts) : content_(opts...) {} 56 | 57 | /// Number of options in current rbr::settings 58 | static constexpr std::ptrdiff_t size() noexcept { return sizeof...(Opts); } 59 | 60 | //============================================================================================== 61 | //! @brief Checks if a given rbr::keyword is stored inside rbr::settings 62 | //! @param kw Keyword to check 63 | //! @return An instance of `std::true_type` if current setting contains an option based on `kw`. 64 | //! Otherwise, return an instance of `std::false_type`. 65 | //! ## Example: 66 | //! @include doc/contains.cpp 67 | //============================================================================================== 68 | template 69 | static constexpr auto contains([[maybe_unused]] Key const& kw) noexcept 70 | { 71 | using found = decltype((std::declval())(Key{})); 72 | return !stdfix::same_as; 73 | } 74 | 75 | //============================================================================================== 76 | //! @brief Checks if rbr::settings contains at least one of maybe keyword 77 | //! @param ks Keywords to check 78 | //! @return An instance of `std::true_type` if current setting contains at least one option 79 | //! based on any of the `ks`. Otherwise, return an instance of `std::false_type`. 80 | //! ## Example: 81 | //! @include doc/contains_any.cpp 82 | //============================================================================================== 83 | template 84 | static constexpr auto contains_any(Keys... ks) noexcept { return (contains(ks) || ...); } 85 | 86 | //============================================================================================== 87 | //! @brief Checks if rbr::settings contains options based only on selected keywords 88 | //! @param ks Keywords to check 89 | //! @return An instance of `std::true_type` if current setting contains only options 90 | //! based on any of the `ks`. Otherwise, return an instance of `std::false_type`. 91 | //! ## Example: 92 | //! @include doc/contains_only.cpp 93 | //============================================================================================== 94 | template 95 | static constexpr auto contains_only([[maybe_unused]] Keys const&... ks) noexcept 96 | { 97 | using current_keys = _::keys; 98 | using acceptable_keys = _::keys; 99 | using unique_set = typename _::uniques::type; 100 | return _::is_equivalent::value; 101 | } 102 | 103 | //============================================================================================== 104 | //! @brief Checks if rbr::settings contains no options based on any of the selected keywords 105 | //! @param ks Keywords to check 106 | //! @return An instance of `std::true_type` if current setting contains no options 107 | //! based on any of the `ks`. Otherwise, return an instance of `std::false_type`. 108 | //! ## Example: 109 | //! @include doc/contains_none.cpp 110 | //============================================================================================== 111 | template 112 | static constexpr auto contains_none(Keys... ks) noexcept { return !contains_any(ks...); } 113 | 114 | //============================================================================================== 115 | //! @brief Retrieved a value via a keyword 116 | //! 117 | //! Retrieve the value bound to a given keyword `k` inside current rbr::settings instance. 118 | //! If such a keyword is not present, either an instance of rbr::unknown_key is returned or 119 | //! a default value or function call will be returned. 120 | //! 121 | //! @param k Keywords to check 122 | //! @return If any, the value bound to `k`. 123 | //! ## Example: 124 | //! @include doc/subscript.cpp 125 | //============================================================================================== 126 | template constexpr auto operator[](Key const& k) const noexcept 127 | { 128 | return content_(k); 129 | } 130 | 131 | //! @overload 132 | template 133 | constexpr auto operator[](flag_keyword const&) const noexcept 134 | { 135 | return contains(flag_keyword{}); 136 | } 137 | 138 | //! @overload 139 | template 140 | constexpr auto operator[](_::type_or_ const & tgt) const 141 | { 142 | if constexpr( contains(Key{}) ) return (*this)[Key{}]; 143 | else if constexpr( requires(Value t) { t.perform(); } ) return tgt.value.perform(); 144 | else return tgt.value; 145 | } 146 | 147 | //! @related rbr::settings 148 | //! @brief Output stream insertion 149 | friend std::ostream& operator<<(std::ostream& os, settings const& s) 150 | { 151 | auto show = [&](T t, V const& v) -> std::ostream& 152 | { 153 | return t.show(os,v) << "\n"; 154 | }; 155 | 156 | (show(typename Opts::keyword_type{}, s[typename Opts::keyword_type{}]), ...); 157 | 158 | return os; 159 | } 160 | 161 | base content_; 162 | }; 163 | 164 | /// rbr::settings deduction guide 165 | template 166 | settings(Opts const&... opts) -> settings; 167 | } 168 | -------------------------------------------------------------------------------- /include/raberu/raberu.hpp: -------------------------------------------------------------------------------- 1 | //====================================================================================================================== 2 | /* 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //====================================================================================================================== 8 | #ifndef RABERU_HPP_INCLUDED 9 | #define RABERU_HPP_INCLUDED 10 | 11 | //====================================================================================================================== 12 | //! @namespace rbr 13 | //! @brief Main Raberu namespace 14 | //====================================================================================================================== 15 | namespace rbr 16 | { 17 | //==================================================================================================================== 18 | //! @namespace rbr::result 19 | //! @brief Raberu helper traits namespace 20 | //==================================================================================================================== 21 | namespace result {} 22 | } 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #undef RBR_FWD 32 | #endif 33 | -------------------------------------------------------------------------------- /standalone/raberu/raberu.hpp: -------------------------------------------------------------------------------- 1 | //====================================================================================================================== 2 | /* 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //====================================================================================================================== 8 | #ifndef RABERU_HPP_INCLUDED 9 | #define RABERU_HPP_INCLUDED 10 | //====================================================================================================================== 11 | //! @namespace rbr 12 | //! @brief Main Raberu namespace 13 | //====================================================================================================================== 14 | namespace rbr 15 | { 16 | //==================================================================================================================== 17 | //! @namespace rbr::result 18 | //! @brief Raberu helper traits namespace 19 | //==================================================================================================================== 20 | namespace result {} 21 | } 22 | #include 23 | #define RBR_FWD(...) static_cast(__VA_ARGS__) 24 | namespace rbr::stdfix 25 | { 26 | template 27 | concept is_same_impl = std::is_same_v; 28 | template 29 | concept same_as = is_same_impl && is_same_impl; 30 | } 31 | namespace rbr::_ 32 | { 33 | template struct keys {}; 34 | template struct contains; 35 | template 36 | struct contains> : std::bool_constant<(stdfix::same_as || ...)> 37 | {}; 38 | template struct append_if_impl; 39 | template struct append_if_impl,true> 40 | { 41 | using type = keys; 42 | }; 43 | template struct append_if_impl,false> 44 | { 45 | using type = keys; 46 | }; 47 | template struct append_if; 48 | template 49 | struct append_if : append_if_impl::value> 50 | {}; 51 | template struct uniques; 52 | template 53 | struct uniques> 54 | : uniques< typename append_if::type, keys > 55 | {}; 56 | template struct uniques> { using type = K1s; }; 57 | template struct contain_all; 58 | template 59 | struct contain_all> : std::bool_constant<(contains::value && ...)> 60 | {}; 61 | template struct contain_all> : std::false_type {}; 62 | template struct contain_all, K2s > : std::false_type {}; 63 | template<> struct contain_all,keys<>> : std::true_type {}; 64 | template 65 | struct is_equivalent : std::bool_constant::value && contain_all::value> 66 | {}; 67 | } 68 | namespace rbr 69 | { 70 | template struct types {}; 71 | } 72 | #include 73 | #include 74 | #include 75 | namespace rbr::concepts 76 | { 77 | template concept keyword = requires( K k ) 78 | { 79 | typename K::tag_type; 80 | { K::template accept() } -> stdfix::same_as; 81 | }; 82 | template concept option = requires( O const& o ) 83 | { 84 | { o(typename std::remove_cvref_t::keyword_type{}) } 85 | -> stdfix::same_as::stored_value_type>; 86 | }; 87 | template concept settings = requires( S const& s ) 88 | { 89 | typename S::rbr_settings; 90 | }; 91 | template 92 | concept exactly = stdfix::same_as < typename Option::keyword_type 93 | , std::remove_cvref_t 94 | >; 95 | } 96 | namespace rbr::_ 97 | { 98 | template 99 | concept checks_for = requires(K) 100 | { 101 | { K::template check() }; 102 | }; 103 | template 104 | concept identifiable = requires(T t) 105 | { 106 | { t.identifier }; 107 | }; 108 | template 109 | concept self_identifiable = requires(T t, std::ostream& os) 110 | { 111 | { os << t }; 112 | }; 113 | template 114 | concept displayable = requires(T t, std::ostream& os, V v) 115 | { 116 | { t.display(os,v) }; 117 | }; 118 | template 119 | concept fits = (N <= M); 120 | } 121 | #include 122 | #include 123 | #include 124 | #include 125 | #include 126 | #include 127 | namespace rbr::_ 128 | { 129 | template struct type_or_ 130 | { 131 | V value; 132 | template 133 | constexpr decltype(auto) operator()(Os&&... os) const { return fetch(*this, RBR_FWD(os)...); } 134 | }; 135 | template constexpr auto typer() noexcept 136 | { 137 | #if defined(__clang__) 138 | constexpr auto pfx = std::string_view("auto rbr::_::typer() [T = ").size(); 139 | constexpr auto sfx = std::string_view("]").size(); 140 | constexpr auto raw = std::string_view(__PRETTY_FUNCTION__); 141 | #elif defined(__GNUC__) 142 | constexpr auto pfx = std::string_view("constexpr auto rbr::_::typer() [with " "T = ").size(); 143 | constexpr auto sfx = std::string_view("]").size(); 144 | constexpr auto raw = std::string_view(__PRETTY_FUNCTION__); 145 | #elif defined(_MSC_VER) 146 | constexpr auto pfx = std::string_view("auto __cdecl rbr::_::typer<").size(); 147 | constexpr auto sfx = std::string_view(">(void)").size(); 148 | constexpr auto raw = std::string_view(__FUNCSIG__); 149 | #endif 150 | auto value = raw; 151 | value.remove_prefix(pfx); 152 | value.remove_suffix(sfx); 153 | constexpr auto size = raw.size() - (pfx + sfx); 154 | auto fn = [&](std::index_sequence) 155 | { 156 | return std::array{value[Is]...}; 157 | }; 158 | return fn(std::make_index_sequence{}); 159 | } 160 | template inline constexpr auto type_array = typer(); 161 | template> 162 | struct type_t 163 | { 164 | static constexpr auto name() { return std::string_view(ID.data(), ID.size());} 165 | }; 166 | template 167 | inline constexpr auto type = type_t{}; 168 | } 169 | #if !defined(RBR_MAX_LITERAL_SIZE) 170 | #define RBR_MAX_LITERAL_SIZE 32 171 | #endif 172 | namespace rbr 173 | { 174 | namespace literals 175 | { 176 | struct str 177 | { 178 | static constexpr std::size_t max_size = RBR_MAX_LITERAL_SIZE; 179 | char data_[max_size+1]; 180 | std::uint8_t size_; 181 | template 182 | requires _::fits 183 | constexpr str(const char (&s)[N], std::index_sequence) : data_{s[Is]...}, size_(N) 184 | {} 185 | template 186 | requires _::fits 187 | constexpr str(const char (&s)[N]) : str{s, std::make_index_sequence{}} 188 | {} 189 | constexpr std::size_t size() const { return size_; } 190 | constexpr std::string_view value() const { return std::string_view(&data_[0],size_); } 191 | friend std::ostream& operator<<(std::ostream& os, str const& s) 192 | { 193 | return os << '\'' << s.value() << '\''; 194 | } 195 | }; 196 | } 197 | template struct id_ 198 | { 199 | friend std::ostream& operator<<(std::ostream& os, id_ const&) 200 | { 201 | return os << ID; 202 | } 203 | }; 204 | namespace literals 205 | { 206 | template constexpr auto operator""_id() noexcept { return id_{}; } 207 | } 208 | } 209 | #include 210 | #include 211 | #include 212 | namespace rbr 213 | { 214 | template struct call 215 | { 216 | constexpr call(Func f) : callable(f) {} 217 | constexpr auto perform() const { return callable(); } 218 | Func callable; 219 | }; 220 | template struct option 221 | { 222 | using stored_value_type = std::decay_t; 223 | using keyword_type = Keyword; 224 | constexpr stored_value_type operator()(keyword_type const&) const noexcept { return contents; } 225 | stored_value_type contents; 226 | }; 227 | template struct as_keyword 228 | { 229 | using tag_type = Keyword; 230 | inline constexpr auto operator<=>(as_keyword const&) const noexcept = default; 231 | template 232 | static constexpr bool accept() 233 | { 234 | if constexpr(stdfix::same_as,as_keyword>) return true; 235 | else if constexpr(_::checks_for) return Keyword::template check(); 236 | else return true; 237 | } 238 | template 239 | constexpr auto operator=(Type&& v) const noexcept requires( accept() ) 240 | { 241 | return option{RBR_FWD(v)}; 242 | } 243 | template std::ostream& show(std::ostream& os, V const& v) const 244 | { 245 | if constexpr(_::displayable) return Keyword{}.display(os,v); 246 | else 247 | { 248 | if constexpr(_::identifiable) os << Keyword::identifier; 249 | else os << '[' << _::type.name() << ']'; 250 | return os << " : " << v << " (" << _::type.name() << ')'; 251 | } 252 | } 253 | template 254 | constexpr auto operator|(Type&& v) const noexcept requires( accept() ) 255 | { 256 | return _::type_or_>{RBR_FWD(v)}; 257 | } 258 | template constexpr auto operator|(call&& v) const noexcept 259 | { 260 | return _::type_or_>{RBR_FWD(v)}; 261 | } 262 | template 263 | constexpr decltype(auto) operator()(Os&&... o) const { return fetch(Keyword{}, RBR_FWD(o)...); } 264 | }; 265 | template class Checker> 266 | struct checked_keyword : as_keyword> 267 | { 268 | using as_keyword>::operator=; 269 | template static constexpr bool check() { return Checker::value; } 270 | template 271 | std::ostream& display(std::ostream& os, V const& v) const 272 | { 273 | if constexpr(_::self_identifiable) os << ID{}; 274 | else 275 | { 276 | if constexpr(_::identifiable) os << ID::identifier; 277 | else os << '[' << _::type.name() << ']'; 278 | } 279 | os << " ::: " << v << " (" << _::type.name() << ") checked by '"; 280 | return os << _::type>.name() << '\''; 281 | } 282 | }; 283 | template 284 | struct typed_keyword : as_keyword> 285 | { 286 | using as_keyword>::operator=; 287 | template 288 | static constexpr bool check() { return std::is_same_v,Type>; } 289 | template 290 | std::ostream& display(std::ostream& os, V const& v) const 291 | { 292 | if constexpr(_::self_identifiable) os << ID{}; 293 | else 294 | { 295 | if constexpr(_::identifiable) os << ID::identifier; 296 | else os << '[' << _::type.name() << ']'; 297 | } 298 | return os << " : " << v << " of type '" << _::type.name() << '\''; 299 | } 300 | }; 301 | template 302 | struct any_keyword : as_keyword> 303 | { 304 | using as_keyword>::operator=; 305 | using id_type = ID; 306 | template 307 | std::ostream& display(std::ostream& os, V const& v) const 308 | { 309 | if constexpr(_::self_identifiable) os << ID{}; 310 | else 311 | { 312 | if constexpr(_::identifiable) os << ID::identifier; 313 | else os << '[' << _::type.name() << ']'; 314 | } 315 | return os << " : " << v << " (" << _::type.name() << ')'; 316 | } 317 | }; 318 | template struct flag_keyword 319 | { 320 | constexpr flag_keyword() {} 321 | constexpr flag_keyword(ID const&) {} 322 | using id_type = ID; 323 | template static constexpr bool accept() 324 | { 325 | return std::is_same_v; 326 | } 327 | std::ostream& show(std::ostream& os, bool) const 328 | { 329 | if constexpr(_::identifiable) os << ID::identifier; 330 | else if constexpr(_::self_identifiable) os << ID{}; 331 | else os << '[' << _::type.name() << ']'; 332 | return os << " : set"; 333 | } 334 | using tag_type = ID; 335 | using keyword_type = flag_keyword; 336 | using stored_value_type = bool; 337 | template 338 | constexpr auto operator=(Type&&) const noexcept { return *this; } 339 | template 340 | constexpr auto operator|(Type&& v) const noexcept 341 | { 342 | return _::type_or_>{RBR_FWD(v)}; 343 | } 344 | template constexpr auto operator|(call&& v) const noexcept 345 | { 346 | return _::type_or_>{RBR_FWD(v)}; 347 | } 348 | constexpr auto operator()(keyword_type const&) const noexcept { return true; } 349 | template 350 | constexpr decltype(auto) operator()(O0&&, O1&&, Os&&... ) const 351 | { 352 | return stdfix::same_as::keyword_type> 353 | || stdfix::same_as::keyword_type> 354 | || (stdfix::same_as::keyword_type> || ...); 355 | } 356 | }; 357 | template 358 | constexpr flag_keyword flag([[maybe_unused]] Tag id) noexcept { return {}; } 359 | template 360 | constexpr any_keyword keyword([[maybe_unused]] ID id) noexcept { return {}; } 361 | template class Checker, typename ID> 362 | constexpr checked_keyword keyword([[maybe_unused]] ID id) noexcept { return {}; } 363 | template 364 | constexpr typed_keyword keyword([[maybe_unused]] ID id) noexcept { return {}; } 365 | namespace literals 366 | { 367 | template 368 | constexpr auto operator""_kw() noexcept { return any_keyword>{}; } 369 | template 370 | constexpr auto operator""_fl() noexcept { return flag_keyword>{}; } 371 | } 372 | } 373 | #include 374 | #include 375 | #include 376 | namespace rbr 377 | { 378 | struct unknown_key { using type = unknown_key; }; 379 | template struct aggregator : Ts... 380 | { 381 | constexpr aggregator(Ts const&...t) noexcept : Ts(t)... {} 382 | using Ts::operator()...; 383 | template constexpr auto operator()(K const &) const noexcept 384 | { 385 | return unknown_key {}; 386 | } 387 | }; 388 | template struct settings 389 | { 390 | using rbr_settings = void; 391 | using base = aggregator; 392 | constexpr settings(Opts const&... opts) : content_(opts...) {} 393 | static constexpr std::ptrdiff_t size() noexcept { return sizeof...(Opts); } 394 | template 395 | static constexpr auto contains([[maybe_unused]] Key const& kw) noexcept 396 | { 397 | using found = decltype((std::declval())(Key{})); 398 | return !stdfix::same_as; 399 | } 400 | template 401 | static constexpr auto contains_any(Keys... ks) noexcept { return (contains(ks) || ...); } 402 | template 403 | static constexpr auto contains_only([[maybe_unused]] Keys const&... ks) noexcept 404 | { 405 | using current_keys = _::keys; 406 | using acceptable_keys = _::keys; 407 | using unique_set = typename _::uniques::type; 408 | return _::is_equivalent::value; 409 | } 410 | template 411 | static constexpr auto contains_none(Keys... ks) noexcept { return !contains_any(ks...); } 412 | template constexpr auto operator[](Key const& k) const noexcept 413 | { 414 | return content_(k); 415 | } 416 | template 417 | constexpr auto operator[](flag_keyword const&) const noexcept 418 | { 419 | return contains(flag_keyword{}); 420 | } 421 | template 422 | constexpr auto operator[](_::type_or_ const & tgt) const 423 | { 424 | if constexpr( contains(Key{}) ) return (*this)[Key{}]; 425 | else if constexpr( requires(Value t) { t.perform(); } ) return tgt.value.perform(); 426 | else return tgt.value; 427 | } 428 | friend std::ostream& operator<<(std::ostream& os, settings const& s) 429 | { 430 | auto show = [&](T t, V const& v) -> std::ostream& 431 | { 432 | return t.show(os,v) << "\n"; 433 | }; 434 | (show(typename Opts::keyword_type{}, s[typename Opts::keyword_type{}]), ...); 435 | return os; 436 | } 437 | base content_; 438 | }; 439 | template 440 | settings(Opts const&... opts) -> settings; 441 | } 442 | namespace rbr 443 | { 444 | namespace _ 445 | { 446 | template 447 | struct filter 448 | { 449 | using type = _::keys; 450 | template constexpr auto operator+(keys const&) const 451 | { 452 | using kw_t = typename T::keyword_type; 453 | if constexpr(!stdfix::same_as) return filter{}; 454 | else return *this; 455 | } 456 | }; 457 | template< typename K, typename S> struct select_keys; 458 | template< typename K, concepts::option... Os> 459 | struct select_keys> 460 | : decltype((filter{} + ... + _::keys{})) 461 | { 462 | }; 463 | } 464 | template 465 | [[nodiscard]] constexpr auto drop([[maybe_unused]] K const& k, settings const& s) 466 | { 467 | using selected_keys_t = typename _::select_keys>::type; 468 | return [&]( _::keys ) 469 | { 470 | return rbr::settings{ (Ks{} = s[Ks{}] )...}; 471 | }(selected_keys_t{}); 472 | } 473 | namespace result 474 | { 475 | template 476 | struct drop 477 | { 478 | using type = decltype( rbr::drop(std::declval(),std::declval()...) ); 479 | }; 480 | template 481 | using drop_t = typename drop::type; 482 | } 483 | } 484 | namespace rbr 485 | { 486 | template 487 | constexpr decltype(auto) fetch(K const& k, Os const&... os) 488 | { 489 | auto const opts = settings(os...); 490 | return opts[k]; 491 | } 492 | template 493 | constexpr decltype(auto) fetch(_::type_or_ const& k, Os const&... os) 494 | { 495 | auto const opts = settings(os...); 496 | return opts[k]; 497 | } 498 | template 499 | constexpr decltype(auto) fetch(K const& k, Settings const& opts) 500 | { 501 | return opts[k]; 502 | } 503 | namespace result 504 | { 505 | template struct fetch; 506 | template 507 | struct fetch 508 | { 509 | using type = decltype( rbr::fetch(Keyword, std::declval()...) ); 510 | }; 511 | template 512 | struct fetch 513 | { 514 | using type = decltype( rbr::fetch(Keyword, std::declval()) ); 515 | }; 516 | template 517 | using fetch_t = typename fetch::type; 518 | } 519 | } 520 | namespace rbr 521 | { 522 | namespace result 523 | { 524 | template class List = types> struct keywords; 525 | template class List = types> struct values; 526 | template class List> 527 | struct keywords, List> 528 | { 529 | using type = List; 530 | }; 531 | template class List> 532 | struct values, List> 533 | { 534 | using type = List; 535 | }; 536 | template class List = types> 537 | using keywords_t = typename keywords::type; 538 | template class List = types> 539 | using values_t = typename values::type; 540 | } 541 | template class List, typename... Opts> 542 | constexpr auto keywords([[maybe_unused]]rbr::settings const& s) 543 | { 544 | return result::keywords_t,List>{typename Opts::keyword_type{}...}; 545 | } 546 | template class List, typename... Opts> 547 | constexpr auto values(rbr::settings const& s) 548 | { 549 | return result::values_t,List>{ s[typename Opts::keyword_type{}]... }; 550 | } 551 | } 552 | namespace rbr 553 | { 554 | template 555 | struct is_equivalent 556 | : std::bool_constant< _::is_equivalent< result::keywords_t 557 | , result::keywords_t 558 | >::value 559 | && _::is_equivalent< result::keywords_t 560 | , result::keywords_t 561 | >::value 562 | > 563 | {}; 564 | template 565 | inline constexpr bool is_equivalent_v = is_equivalent::value; 566 | } 567 | namespace rbr 568 | { 569 | template 570 | constexpr auto merge(settings const& opts, settings const& defs) noexcept 571 | { 572 | auto selector = [](K const&, Opts const& o, auto const& d) 573 | { 574 | constexpr K key; 575 | if constexpr( Opts::contains(key) ) return (key = o[key]); 576 | else return (key = d[key]); 577 | }; 578 | auto select = [&](_::keys const&, auto const& os, auto const& ds) 579 | { 580 | return settings(selector(Ks{},os,ds)...); 581 | }; 582 | return select(typename _::uniques<_::keys 583 | ,_::keys 584 | >::type{},opts,defs); 585 | } 586 | namespace result 587 | { 588 | template 589 | struct merge 590 | { 591 | using type = decltype( rbr::merge(std::declval(),std::declval()) ); 592 | }; 593 | template 594 | using merge_t = typename merge::type; 595 | } 596 | } 597 | #undef RBR_FWD 598 | #endif 599 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## RABERU - Fancy Named Parameter Library 3 | ## Copyright : RABERU Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | copa_setup_test_targets() 7 | set(root "${CMAKE_SOURCE_DIR}/test") 8 | 9 | copa_glob_unit( PATTERN "unit/*.cpp" 10 | QUIET RELATIVE ${root} INTERFACE raberu_test DEPENDENCIES raberu-standalone 11 | ) 12 | 13 | copa_glob_unit( PATTERN "doc/*.cpp" 14 | QUIET RELATIVE ${root} INTERFACE raberu_test DEPENDENCIES raberu-standalone 15 | ) 16 | -------------------------------------------------------------------------------- /test/doc/accept.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #define TTS_MAIN 7 | #include 8 | 9 | //! [Custom Accept] 10 | #include 11 | 12 | // Defines a keyword type that only accept floating point value 13 | struct real_keyword : rbr::as_keyword 14 | { 15 | template static constexpr bool check() { return std::is_floating_point_v; } 16 | using rbr::as_keyword::operator=; 17 | }; 18 | 19 | inline constexpr real_keyword real = {}; 20 | //! [Custom Accept] 21 | 22 | TTS_CASE("Check accept() customization point") 23 | { 24 | TTS_EXPECT_COMPILES (real , { real = 4.f; } ); 25 | TTS_EXPECT_NOT_COMPILES (real , { real = 8ULL; } ); 26 | }; 27 | -------------------------------------------------------------------------------- /test/doc/checked.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | 9 | using namespace rbr::literals; 10 | 11 | template 12 | struct is_big : std::bool_constant<(sizeof(T) > 2)> {}; 13 | 14 | inline constexpr auto large_value = rbr::keyword("large"_id); 15 | 16 | int main() 17 | { 18 | std::cout << rbr::settings( large_value = 9.6 ); 19 | } 20 | -------------------------------------------------------------------------------- /test/doc/contains.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | 9 | using namespace rbr::literals; 10 | 11 | template 12 | void check_contains( S const& s) 13 | { 14 | if constexpr( S::contains( "value"_kw ) ) 15 | std::cout << "Correct settings: " << s["value"_kw] << '\n'; 16 | else 17 | std::cout << "Incorrect settings\n"; 18 | } 19 | 20 | int main() 21 | { 22 | check_contains( rbr::settings("value"_kw = 9 ) ); 23 | check_contains( rbr::settings("malus"_kw = 3.5) ); 24 | check_contains( rbr::settings("malus"_kw = 6.5, "value"_kw = 17) ); 25 | } 26 | -------------------------------------------------------------------------------- /test/doc/contains_any.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | 9 | using namespace rbr::literals; 10 | 11 | template 12 | void check_contains_any( S const& ) 13 | { 14 | if constexpr( S::contains_any( "value"_kw, "active"_fl ) ) 15 | std::cout << "Correct settings\n"; 16 | else 17 | std::cout << "Incorrect settings\n"; 18 | } 19 | 20 | int main() 21 | { 22 | check_contains_any( rbr::settings("value"_kw = 9 ) ); 23 | check_contains_any( rbr::settings("malus"_kw = 3.5) ); 24 | check_contains_any( rbr::settings("malus"_kw = 6.5, "value"_kw = 17) ); 25 | check_contains_any( rbr::settings("active"_fl, "value"_kw = 17) ); 26 | } 27 | -------------------------------------------------------------------------------- /test/doc/contains_none.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | 9 | using namespace rbr::literals; 10 | 11 | template 12 | void check_contains_none( S const& ) 13 | { 14 | if constexpr( S::contains_none( "malus"_kw, "other"_kw ) ) 15 | std::cout << "Correct settings\n"; 16 | else 17 | std::cout << "Incorrect settings\n"; 18 | } 19 | 20 | int main() 21 | { 22 | check_contains_none( rbr::settings("value"_kw = 9) ); 23 | check_contains_none( rbr::settings("active"_fl) ); 24 | check_contains_none( rbr::settings("malus"_kw = 6.5, "value"_kw = 17) ); 25 | check_contains_none( rbr::settings("active"_fl, "value"_kw = 17) ); 26 | check_contains_none( rbr::settings("active"_fl, "value"_kw = 17, "other"_kw = false) ); 27 | } 28 | -------------------------------------------------------------------------------- /test/doc/contains_only.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | 9 | using namespace rbr::literals; 10 | 11 | template 12 | void check_contains_only( S const& ) 13 | { 14 | if constexpr( S::contains_only( "value"_kw, "active"_fl ) ) 15 | std::cout << "Correct settings\n"; 16 | else 17 | std::cout << "Incorrect settings\n"; 18 | } 19 | 20 | int main() 21 | { 22 | check_contains_only( rbr::settings("value"_kw = 9) ); 23 | check_contains_only( rbr::settings("active"_fl) ); 24 | check_contains_only( rbr::settings("malus"_kw = 6.5, "value"_kw = 17) ); 25 | check_contains_only( rbr::settings("active"_fl, "value"_kw = 17) ); 26 | check_contains_only( rbr::settings("active"_fl, "value"_kw = 17, "other"_kw = false) ); 27 | } 28 | -------------------------------------------------------------------------------- /test/doc/drop.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | using namespace rbr::literals; 12 | constexpr auto aligned = "aligned"_fl; 13 | constexpr auto transparent = "transparent"_fl; 14 | 15 | rbr::settings v ( "surname"_kw = std::string{"john"} 16 | , "value"_kw = 3.f 17 | , aligned 18 | , transparent 19 | ); 20 | 21 | std::cout << v << "\n"; 22 | 23 | auto unaligned = drop(aligned, v); 24 | auto unamed = drop("surname"_kw, v); 25 | 26 | std::cout << unaligned << "\n"; 27 | std::cout << unamed << "\n"; 28 | } 29 | -------------------------------------------------------------------------------- /test/doc/fetch.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | using namespace rbr::literals; 12 | 13 | int i = 77; 14 | 15 | auto values = rbr::settings("size"_kw = 75ULL, "transparent"_fl); 16 | 17 | std::cout << rbr::fetch ( "transparent"_fl, values) << "\n"; 18 | std::cout << rbr::fetch ( "size"_kw, "size"_kw = 75ULL, "transparent"_fl) << "\n"; 19 | std::cout << rbr::fetch ( "value"_kw | 13.37, "size"_kw = 75ULL, "transparent"_fl) << "\n"; 20 | std::cout << rbr::fetch ( "modal"_fl | rbr::call([&]() { return i++; }) 21 | , "size"_kw = 75ULL, "transparent"_fl 22 | ) << "\n\n"; 23 | 24 | std::cout << "i = " << i << "\n"; 25 | } 26 | -------------------------------------------------------------------------------- /test/doc/flag.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | 9 | using namespace rbr::literals; 10 | 11 | inline constexpr auto modal = rbr::flag("modal window"_id); 12 | 13 | int main() 14 | { 15 | std::cout << rbr::settings( modal ); 16 | } 17 | -------------------------------------------------------------------------------- /test/doc/is_equivalent.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | using namespace rbr::literals; 12 | 13 | auto s1 = rbr::settings("opt1"_kw = 3, "opt2"_kw = 22, "yes"_fl); 14 | auto s2 = rbr::settings("opt1"_kw = 7.8, "yes"_fl, "opt2"_kw = 789.987); 15 | auto s3 = rbr::settings("opt1"_kw = 7.8, "yes"_fl, "opt3"_kw = 789.987); 16 | 17 | std::cout << std::boolalpha << rbr::is_equivalent_v << "\n"; 18 | std::cout << std::boolalpha << rbr::is_equivalent_v << "\n"; 19 | std::cout << std::boolalpha << rbr::is_equivalent_v << "\n"; 20 | std::cout << std::boolalpha << rbr::is_equivalent_v << "\n"; 21 | std::cout << std::boolalpha << rbr::is_equivalent_v << "\n"; 22 | std::cout << std::boolalpha << rbr::is_equivalent_v << "\n"; 23 | } 24 | -------------------------------------------------------------------------------- /test/doc/keyword_fetch.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | 9 | using namespace rbr::literals; 10 | 11 | inline constexpr auto value = "value"_kw; 12 | inline constexpr auto line = "line"_kw; 13 | inline constexpr auto file = "file"_kw; 14 | 15 | int main() 16 | { 17 | std::cout << file (value = 45.5, line = 158, file = 'x') << '\n'; 18 | std::cout << line (value = 45.5, line = 158, file = 'x') << '\n'; 19 | std::cout << value(value = 45.5, line = 158, file = 'x') << '\n'; 20 | } 21 | -------------------------------------------------------------------------------- /test/doc/keywords.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | #include 9 | 10 | int main() 11 | { 12 | using namespace rbr::literals; 13 | 14 | auto opts = rbr::settings("size"_kw = 75ULL, "modal"_fl, "value"_kw = 13.37); 15 | auto kws = rbr::keywords(opts); 16 | 17 | std::apply( [](T const&...) 18 | { 19 | ((std::cout << typename T::id_type{} << "\n"),...); 20 | } 21 | , kws 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /test/doc/merge.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | using namespace rbr::literals; 12 | 13 | constexpr auto modal = "modal"_fl; 14 | constexpr auto similar = "similar"_fl; 15 | auto defaults = rbr::settings("name"_kw = std::string{"Jane Doe"}, "value"_kw = 42.69f, modal); 16 | auto opts = rbr::settings("value"_kw = 956.7f, similar); 17 | 18 | auto merged = rbr::merge(opts, defaults); 19 | 20 | std::cout << merged[modal] << "\n"; 21 | std::cout << merged["name"_kw] << "\n"; 22 | std::cout << merged[similar] << "\n"; 23 | std::cout << merged["value"_kw] << "\n"; 24 | } 25 | -------------------------------------------------------------------------------- /test/doc/regular.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace rbr::literals; 11 | 12 | inline constexpr auto name = rbr::keyword("name"_id); 13 | 14 | int main() 15 | { 16 | std::cout << rbr::settings( name = std::string{"Jane Doe"} ); 17 | } 18 | -------------------------------------------------------------------------------- /test/doc/show.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #define TTS_MAIN 7 | #include 8 | 9 | //! [Custom Show] 10 | #include 11 | 12 | // Defines a keyword type that only accept floating point value 13 | struct price_keyword : rbr::as_keyword 14 | { 15 | using rbr::as_keyword::operator=; 16 | 17 | std::ostream& display(std::ostream& os, auto const& v) 18 | { 19 | return os << "Price: " << v << '$'; 20 | } 21 | }; 22 | 23 | inline constexpr price_keyword price = {}; 24 | //! [Custom Show] 25 | 26 | #include 27 | 28 | TTS_CASE("Check show() customization point") 29 | { 30 | std::ostringstream os; 31 | 32 | auto s = rbr::settings(price = 4); 33 | os << s; 34 | 35 | TTS_EQUAL(os.str(), std::string{"Price: 4$\n"}); 36 | }; 37 | -------------------------------------------------------------------------------- /test/doc/subscript.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | using namespace rbr::literals; 12 | 13 | int i = 77; 14 | auto values = rbr::settings("size"_kw = 75ULL, "transparent"_fl); 15 | 16 | std::cout << values["size"_kw] << "\n"; 17 | std::cout << values["transparent"_fl] << "\n"; 18 | std::cout << values["value"_kw | 13.37] << "\n"; 19 | std::cout << values["modal"_fl | rbr::call([&]() { return i++; })] << "\n\n"; 20 | 21 | std::cout << "i = " << i << "\n"; 22 | } 23 | -------------------------------------------------------------------------------- /test/doc/tutorial01.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | #include 9 | 10 | template 11 | auto replicate( P0 p0, P1 p1 ) 12 | { 13 | using namespace rbr::literals; 14 | 15 | auto const params = rbr::settings(p0,p1); 16 | return std::string( params["replication"_kw], params["letter"_kw] ); 17 | } 18 | 19 | int main() 20 | { 21 | using namespace rbr::literals; 22 | 23 | std::cout << replicate("replication"_kw = 9, "letter"_kw = 'z' ) << "\n"; 24 | std::cout << replicate("letter"_kw = '!' , "replication"_kw = 3) << "\n"; 25 | } 26 | -------------------------------------------------------------------------------- /test/doc/tutorial02.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | 9 | using namespace rbr::literals; 10 | 11 | inline constexpr auto is_modal = "is_modal"_fl; 12 | inline constexpr auto autosave = rbr::flag("autosave"_id); 13 | 14 | template 15 | void check_options(Params const&... ps) 16 | { 17 | auto s = rbr::settings(ps...); 18 | std::cout << "Modal window: " << std::boolalpha << s[is_modal] << " - " 19 | << "autosave: " << std::boolalpha << s[autosave] << "\n"; 20 | } 21 | 22 | int main() 23 | { 24 | check_options(); 25 | check_options(autosave); 26 | check_options(is_modal); 27 | check_options(autosave,is_modal); 28 | check_options(is_modal,autosave); 29 | } 30 | -------------------------------------------------------------------------------- /test/doc/tutorial03.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | using namespace rbr::literals; 12 | 13 | int i = 77; 14 | auto values = rbr::settings("size"_kw = 75ULL, "transparent"_fl); 15 | 16 | std::cout << values["size"_kw] << "\n"; 17 | std::cout << values["transparent"_fl] << "\n"; 18 | std::cout << values["value"_kw | 13.37] << "\n"; 19 | std::cout << values["value"_kw | rbr::call([&]() { return ++i; })] << "\n\n"; 20 | 21 | std::cout << "i = " << i << "\n"; 22 | } 23 | -------------------------------------------------------------------------------- /test/doc/tutorial04.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace rbr::literals; 11 | 12 | inline constexpr auto unrolling = rbr::keyword("unrolling"_id); 13 | 14 | template inline constexpr auto unroll = (unrolling = std::integral_constant{}); 15 | 16 | void f(rbr::concepts::option auto const& s) 17 | { 18 | std::cout << rbr::settings(s) << "\n"; 19 | } 20 | 21 | int main() 22 | { 23 | f( unroll<8> ); 24 | } 25 | -------------------------------------------------------------------------------- /test/doc/tutorial05.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | #include 9 | 10 | struct unrolling : rbr::as_keyword 11 | { 12 | template 13 | constexpr auto operator=(std::integral_constant const&) const noexcept 14 | { 15 | return rbr::option>{}; 16 | } 17 | std::ostream& display(std::ostream& os, auto v) const { return os << "Unroll Factor: " << v; } 18 | }; 19 | 20 | template 21 | inline constexpr auto unroll = (unrolling{} = std::integral_constant{}); 22 | 23 | void f(rbr::concepts::option auto const& s) 24 | { 25 | std::cout << rbr::settings(s) << "\n"; 26 | } 27 | 28 | int main() 29 | { 30 | f( unroll<8> ); 31 | } 32 | -------------------------------------------------------------------------------- /test/doc/values.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | RABERU - Fancy Parameters Library 3 | Copyright : RABERU Project Contributors 4 | SPDX-License-Identifier: BSL-1.0 5 | **/ 6 | #include 7 | #include 8 | #include 9 | 10 | int main() 11 | { 12 | using namespace rbr::literals; 13 | 14 | auto opts = rbr::settings("size"_kw = 75ULL, "modal"_fl, "value"_kw = 13.37); 15 | auto vs = rbr::values(opts); 16 | 17 | std::apply([](auto const&... e) { ((std::cout << e << "\n"),...); }, vs); 18 | } 19 | -------------------------------------------------------------------------------- /test/integration/cpm-test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## RABERU - Fancy Named Parameter Library 3 | ## Copyright : RABERU Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | cmake_minimum_required(VERSION 3.18) 7 | project(raberu-cpm-test LANGUAGES CXX) 8 | enable_testing() 9 | 10 | message(STATUS "Testing CPM for branch ${GIT_BRANCH}") 11 | 12 | # Setup CPM 13 | include(cpm.cmake) 14 | 15 | # Add dependencies 16 | CPMAddPackage ( NAME raberu 17 | GIT_REPOSITORY "https://github.com/jfalcou/raberu.git" 18 | GIT_TAG "${GIT_BRANCH}" 19 | OPTIONS "RABERU_BUILD_TEST OFF" 20 | ) 21 | 22 | # Use RABERU 23 | add_executable(test_raberu ../main.cpp) 24 | target_link_libraries(test_raberu PUBLIC raberu::raberu) 25 | add_test(NAME test_raberu COMMAND test_raberu) 26 | -------------------------------------------------------------------------------- /test/integration/fetch-test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## RABERU - Fancy Named Parameter Library 3 | ## Copyright : RABERU Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | cmake_minimum_required(VERSION 3.22) 7 | project(raberu-fetch-test LANGUAGES CXX) 8 | enable_testing() 9 | 10 | message(STATUS "Testing FetchContent for branch ${GIT_BRANCH}") 11 | 12 | # Enable FetchContent 13 | include(FetchContent) 14 | 15 | # Retrieve RABERU from relative git directory 16 | FetchContent_Declare(raberu 17 | GIT_REPOSITORY "https://github.com/jfalcou/raberu.git" 18 | GIT_TAG ${GIT_BRANCH} 19 | ) 20 | 21 | # make available 22 | FetchContent_MakeAvailable(raberu) 23 | 24 | add_executable(test_raberu ../main.cpp) 25 | target_link_libraries(test_raberu PUBLIC raberu::raberu) 26 | add_test(NAME test_raberu COMMAND test_raberu) 27 | -------------------------------------------------------------------------------- /test/integration/install-test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## RABERU - Fancy Named Parameter Library 3 | ## Copyright : RABERU Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | cmake_minimum_required(VERSION 3.22) 7 | project(raberu-install-test LANGUAGES CXX) 8 | enable_testing() 9 | 10 | find_package(raberu CONFIG REQUIRED) 11 | add_executable(test_raberu ../main.cpp) 12 | target_link_libraries(test_raberu PUBLIC raberu::raberu) 13 | add_test(NAME test_raberu COMMAND test_raberu) 14 | -------------------------------------------------------------------------------- /test/integration/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace rbr::literals; 6 | 7 | template 8 | auto replicate( P0 p0, P1 p1 ) 9 | { 10 | auto const params = rbr::settings(p0,p1); 11 | return std::string( params["replication"_kw], params["letter"_kw] ); 12 | } 13 | 14 | int main() 15 | { 16 | std::cout << replicate("replication"_kw = 9, "letter"_kw = 'z' ) << "\n"; 17 | std::cout << replicate("letter"_kw = '!' , "replication"_kw = 3) << "\n"; 18 | } 19 | -------------------------------------------------------------------------------- /test/unit/access.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #define TTS_MAIN 9 | #include 10 | #include "common.hpp" 11 | #include 12 | #include 13 | 14 | TTS_CASE("Check settings(...) operator[t] behavior") 15 | { 16 | using namespace std::literals; 17 | 18 | auto values = rbr::settings(coord_ = "Jane Doe"s, is_modal_); 19 | 20 | TTS_EQUAL(values[coord_] , "Jane Doe"s ); 21 | TTS_EQUAL(values[is_modal_] , true ); 22 | TTS_EQUAL(values[is_transparent_], false ); 23 | }; 24 | 25 | TTS_CASE("Check settings(...) operator[t] constexpr behavior") 26 | { 27 | constexpr auto values = rbr::settings(coord_ = 75ULL, is_transparent_, "value"_kw = 42.69f); 28 | 29 | TTS_CONSTEXPR_EQUAL(values["value"_kw] , 42.69f); 30 | TTS_CONSTEXPR_EQUAL(values[coord_] , 75ULL ); 31 | TTS_CONSTEXPR_EQUAL(values[is_transparent_] , true ); 32 | TTS_CONSTEXPR_EQUAL(values[is_modal_] , false ); 33 | }; 34 | 35 | TTS_CASE("Check settings(...) operator[t | v] behavior") 36 | { 37 | using namespace std::literals; 38 | using namespace rbr::literals; 39 | 40 | auto values = rbr::settings(name_ = "Jane Doe"s, "default_init"_fl, "value"_kw = 65); 41 | 42 | TTS_EQUAL(values[name_ | "Bob Ross"s ], "Jane Doe"s); 43 | TTS_EQUAL(values["default_init"_fl | -99 ], true ); 44 | TTS_EQUAL(values["value"_kw | -9.9 ], 65 ); 45 | 46 | TTS_EQUAL(values["perform_copy"_fl | -99 ], -99); 47 | TTS_EQUAL(values["other_kw"_kw | -9.9], -9.9); 48 | }; 49 | 50 | TTS_CASE("Check settings(...) operator[t | v] constexpr behavior") 51 | { 52 | using namespace rbr::literals; 53 | 54 | constexpr auto values = rbr::settings("default_init"_fl, coord_ = 75ULL); 55 | 56 | TTS_CONSTEXPR_EQUAL(values[coord_ | -99], 75ULL); 57 | TTS_CONSTEXPR_EQUAL(values["default_init"_fl | -99], true); 58 | 59 | TTS_CONSTEXPR_EQUAL(values["perform_copy"_fl | -99], -99); 60 | TTS_CONSTEXPR_EQUAL(values["other_kw"_kw | -9.9], -9.9); 61 | }; 62 | 63 | TTS_CASE("Check settings(...) operator[t | func()] behavior") 64 | { 65 | using namespace std::literals; 66 | using namespace rbr::literals; 67 | 68 | auto values = rbr::settings(name_ = "Jane Doe"s, "default_init"_fl, "value"_kw = 65); 69 | auto or_else = [&]() { return values.size() * values["value"_kw]; }; 70 | 71 | TTS_EQUAL(values[name_ | rbr::call(or_else) ], "Jane Doe"s); 72 | TTS_EQUAL(values["default_init"_fl | rbr::call(or_else) ], true ); 73 | TTS_EQUAL(values["value"_kw | rbr::call(or_else) ], 65 ); 74 | 75 | TTS_EQUAL(values["perform_copy"_fl | rbr::call(or_else) ], 3*65); 76 | TTS_EQUAL(values["other_kw"_kw | rbr::call(or_else) ], 3*65); 77 | }; 78 | 79 | TTS_CASE("Check settings(...) operator[t | func()] constexpr behavior") 80 | { 81 | constexpr auto values = rbr::settings(is_modal_,value_ = 1337.42f); 82 | auto or_else = []() { return 42.69; }; 83 | 84 | TTS_CONSTEXPR_EQUAL(values[is_modal_ | rbr::call(or_else) ], true ); 85 | TTS_CONSTEXPR_EQUAL(values[value_ | rbr::call(or_else) ], 1337.42f ); 86 | 87 | TTS_CONSTEXPR_EQUAL(values["perform_copy"_fl | rbr::call(or_else) ], 42.69); 88 | TTS_CONSTEXPR_EQUAL(values["other_kw"_kw | rbr::call(or_else) ], 42.69); 89 | }; 90 | -------------------------------------------------------------------------------- /test/unit/common.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #pragma once 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace rbr::literals; 15 | 16 | template using bool_ = std::bool_constant; 17 | 18 | using point = std::array; 19 | 20 | struct foo 21 | { 22 | int value = 42; 23 | friend std::ostream& operator<<(std::ostream& os, foo f) { return os << f.value; } 24 | }; 25 | 26 | struct bar 27 | { 28 | double value = 4.2; 29 | friend std::ostream& operator<<(std::ostream& os, bar b) { return os << b.value; } 30 | }; 31 | 32 | template 33 | struct small_type : std::bool_constant<(sizeof(T) < 4)> {}; 34 | 35 | inline constexpr auto custom_ = ::rbr::keyword("custom"_id); 36 | inline constexpr auto coord_ = "coord"_kw; 37 | 38 | inline constexpr auto value_ = ::rbr::keyword("value"_id); 39 | inline constexpr auto name_ = ::rbr::keyword("name"_id); 40 | 41 | inline constexpr auto factor_ = ::rbr::keyword("factor"_id); 42 | 43 | inline constexpr auto is_transparent_ = ::rbr::flag("is_transparent"_id); 44 | inline constexpr auto is_modal_ = "is_modal"_fl; 45 | 46 | struct unrolling : rbr::as_keyword 47 | { 48 | template 49 | constexpr auto operator=(std::integral_constant const&) const noexcept 50 | { 51 | return rbr::option>{}; 52 | } 53 | 54 | std::ostream& display(std::ostream& os, auto v) const { return os << "Unroll Factor: " << v; } 55 | }; 56 | 57 | template inline constexpr auto unroll = (unrolling{} = std::integral_constant{}); 58 | -------------------------------------------------------------------------------- /test/unit/concepts.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #define TTS_MAIN 9 | #include "common.hpp" 10 | #include 11 | #include 12 | 13 | // MSVC does not support incomplete types in concepts (?) 14 | struct key {}; 15 | 16 | TTS_CASE("Check rbr::concepts::keyword concept") 17 | { 18 | using namespace rbr::literals; 19 | 20 | // Direct type 21 | TTS_EXPECT( rbr::concepts::keyword< rbr::flag_keyword > ); 22 | TTS_EXPECT( rbr::concepts::keyword< rbr::any_keyword > ); 23 | TTS_EXPECT( ( rbr::concepts::keyword< rbr::typed_keyword >)); 24 | TTS_EXPECT( ( rbr::concepts::keyword< rbr::checked_keyword>)); 25 | 26 | // Predefined keyword object 27 | TTS_EXPECT( rbr::concepts::keyword< decltype(custom_) > ); 28 | TTS_EXPECT( rbr::concepts::keyword< decltype(coord_ ) > ); 29 | 30 | // Type from polymorphic constructor 31 | TTS_EXPECT( rbr::concepts::keyword< decltype(rbr::keyword("any"_id)) > ); 32 | TTS_EXPECT( rbr::concepts::keyword< decltype(rbr::keyword("small"_id)) > ); 33 | TTS_EXPECT( rbr::concepts::keyword< decltype(rbr::keyword("real_value"_id)) > ); 34 | TTS_EXPECT( rbr::concepts::keyword< decltype(rbr::flag("modal"_id)) > ); 35 | 36 | // Type from literals 37 | TTS_EXPECT( rbr::concepts::keyword< decltype("any"_kw) > ); 38 | TTS_EXPECT( rbr::concepts::keyword< decltype("modal"_fl) > ); 39 | 40 | // Obviously wrong type 41 | TTS_EXPECT_NOT( rbr::concepts::keyword ); 42 | }; 43 | 44 | struct my_little_keyword : rbr::checked_keyword 45 | { 46 | using parent = rbr::checked_keyword; 47 | using parent::operator=; 48 | }; 49 | 50 | TTS_CASE("Check rbr::concepts::option concept") 51 | { 52 | TTS_EXPECT( (rbr::concepts::option , int>>) ); 53 | TTS_EXPECT( (rbr::concepts::option>) ); 54 | TTS_EXPECT( (rbr::concepts::option >) ); 55 | TTS_EXPECT_NOT(rbr::concepts::option ); 56 | }; 57 | 58 | TTS_CASE("Check rbr::exactly concept") 59 | { 60 | using namespace rbr::literals; 61 | 62 | auto param = (coord_ = 9); 63 | 64 | TTS_EXPECT( (rbr::concepts::exactly) ); 65 | TTS_EXPECT( (rbr::concepts::exactly) ); 66 | TTS_EXPECT_NOT( (rbr::concepts::exactly) ); 67 | }; 68 | -------------------------------------------------------------------------------- /test/unit/constraints.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #define TTS_MAIN 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | template 15 | struct small_type : std::bool_constant<(sizeof(T) < 4)> {}; 16 | 17 | using namespace rbr::literals; 18 | 19 | inline constexpr rbr::checked_keyword angle = {}; 20 | inline constexpr auto pattern = rbr::keyword( "pattern"_id); 21 | 22 | TTS_CASE("Check constrained keyword::operator= behavior") 23 | { 24 | rbr::settings s( angle = 3., pattern = 'z'); 25 | TTS_EQUAL( s[angle] , 3. ); 26 | TTS_EQUAL( s[pattern] , 'z' ); 27 | }; 28 | -------------------------------------------------------------------------------- /test/unit/contains.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #define TTS_MAIN 9 | #include "common.hpp" 10 | #include 11 | #include 12 | 13 | TTS_CASE("Check settings(...).contains behavior") 14 | { 15 | using namespace std::literals; 16 | using namespace rbr::literals; 17 | 18 | rbr::settings values( custom_ = foo {}, "surname"_kw = "john"s 19 | , value_ = 3.f, "aligned"_fl,is_transparent_ 20 | ); 21 | 22 | TTS_EXPECT(values.contains(custom_) ); 23 | TTS_EXPECT(values.contains("surname"_kw) ); 24 | TTS_EXPECT(values.contains(value_) ); 25 | TTS_EXPECT(values.contains(is_transparent_) ); 26 | TTS_EXPECT(values.contains("aligned"_fl) ); 27 | 28 | TTS_EXPECT_NOT(values.contains(is_modal_ )); 29 | TTS_EXPECT_NOT(values.contains("compact"_fl )); 30 | }; 31 | 32 | TTS_CASE("Check settings(...).contains constexpr behavior") 33 | { 34 | using namespace std::literals; 35 | using namespace rbr::literals; 36 | 37 | constexpr rbr::settings values("custom"_kw = foo {}, value_ = 3.f, is_modal_); 38 | 39 | TTS_CONSTEXPR_EXPECT(values.contains("custom"_kw) ); 40 | TTS_CONSTEXPR_EXPECT(values.contains(value_ ) ); 41 | TTS_CONSTEXPR_EXPECT(values.contains(is_modal_) ); 42 | 43 | TTS_CONSTEXPR_EXPECT_NOT(values.contains(is_transparent_) ); 44 | TTS_CONSTEXPR_EXPECT_NOT(values.contains("compact"_fl ) ); 45 | }; 46 | 47 | TTS_CASE("Check settings(...).contains_any behavior") 48 | { 49 | using namespace std::literals; 50 | using namespace rbr::literals; 51 | 52 | rbr::settings values( custom_ = foo {}, "surname"_kw = "john"s 53 | , value_ = 3.f, "aligned"_fl,is_transparent_ 54 | ); 55 | 56 | TTS_EXPECT (values.contains_any(custom_, is_transparent_, "compact"_fl) ); 57 | TTS_EXPECT_NOT(values.contains_any(is_modal_, "compact"_fl) ); 58 | }; 59 | 60 | TTS_CASE("Check settings(...).contains_any constexpr behavior") 61 | { 62 | using namespace std::literals; 63 | using namespace rbr::literals; 64 | 65 | constexpr rbr::settings values("custom"_kw = foo {}, value_ = 3.f, is_modal_); 66 | 67 | TTS_CONSTEXPR_EXPECT (values.contains_any(value_, is_modal_, "custom"_kw) ); 68 | TTS_CONSTEXPR_EXPECT_NOT(values.contains_any(is_transparent_, "compact"_fl) ); 69 | }; 70 | 71 | TTS_CASE("Check settings(...).contains_only behavior") 72 | { 73 | using namespace std::literals; 74 | using namespace rbr::literals; 75 | 76 | rbr::settings values( "kw1"_kw = 1, "kw2"_kw = 1, "kw3"_kw = 1 ); 77 | 78 | TTS_EXPECT (values.contains_only("kw1"_kw, "kw2"_kw, "kw3"_kw) ); 79 | TTS_EXPECT (values.contains_only("kw1"_kw, "kw3"_kw, "kw2"_kw) ); 80 | TTS_EXPECT (values.contains_only("kw1"_kw, "kw3"_kw, "kw2"_kw, "xyz"_kw) ); 81 | 82 | TTS_EXPECT_NOT(values.contains_only("kw1"_kw, "kw2"_kw)); 83 | TTS_EXPECT_NOT(values.contains_only("kw1"_kw) ); 84 | TTS_EXPECT_NOT(values.contains_only("a"_kw) ); 85 | TTS_EXPECT_NOT(values.contains_only("a"_kw, "b"_kw) ); 86 | }; 87 | 88 | TTS_CASE("Check settings(...).contains_only constexpr behavior") 89 | { 90 | using namespace std::literals; 91 | using namespace rbr::literals; 92 | 93 | constexpr rbr::settings values( "kw1"_kw = 1, "kw2"_kw = 1, "kw3"_kw = 1 ); 94 | 95 | TTS_CONSTEXPR_EXPECT(values.contains_only("kw1"_kw, "kw2"_kw, "kw3"_kw) ); 96 | TTS_CONSTEXPR_EXPECT(values.contains_only("kw1"_kw, "kw3"_kw, "kw2"_kw) ); 97 | TTS_CONSTEXPR_EXPECT(values.contains_only("kw1"_kw, "kw3"_kw, "kw2"_kw, "xyz"_kw) ); 98 | 99 | TTS_CONSTEXPR_EXPECT_NOT(values.contains_only("kw1"_kw, "kw2"_kw)); 100 | TTS_CONSTEXPR_EXPECT_NOT(values.contains_only("kw1"_kw) ); 101 | TTS_CONSTEXPR_EXPECT_NOT(values.contains_only("a"_kw) ); 102 | TTS_CONSTEXPR_EXPECT_NOT(values.contains_only("a"_kw, "b"_kw) ); 103 | }; 104 | 105 | TTS_CASE("Check settings(...).contains_none behavior") 106 | { 107 | using namespace std::literals; 108 | using namespace rbr::literals; 109 | 110 | rbr::settings values( custom_ = foo {}, "surname"_kw = "john"s 111 | , value_ = 3.f, "aligned"_fl,is_transparent_ 112 | ); 113 | 114 | TTS_EXPECT (values.contains_none(is_modal_, "compact"_fl) ); 115 | TTS_EXPECT_NOT(values.contains_none(value_, is_transparent_) ); 116 | }; 117 | 118 | TTS_CASE("Check settings(...).contains_none constexpr behavior") 119 | { 120 | using namespace std::literals; 121 | using namespace rbr::literals; 122 | 123 | constexpr rbr::settings values("custom"_kw = foo {}, value_ = 3.f, is_modal_); 124 | 125 | TTS_CONSTEXPR_EXPECT (values.contains_none(is_transparent_, "compact"_fl) ); 126 | TTS_CONSTEXPR_EXPECT_NOT(values.contains_none(value_) ); 127 | }; 128 | -------------------------------------------------------------------------------- /test/unit/doc.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #include 9 | #include 10 | #include 11 | 12 | template auto replicate( P0 p0, P1 p1 ) 13 | { 14 | using namespace rbr::literals; 15 | 16 | auto const params = rbr::settings(p0,p1); 17 | return std::string( params["replication"_kw], params["letter"_kw] ); 18 | } 19 | 20 | void scenario_1() 21 | { 22 | using namespace rbr::literals; 23 | 24 | std::cout << "replicate( \"letter\"_kw = 'c' , \"replication\"_kw = 10 ):" << "\n"; 25 | std::cout << replicate( "letter"_kw = 'c' , "replication"_kw = 10 ) << "\n"; 26 | std::cout << "replicate( \"replication\"_kw = 7, \"letter\"_kw = '*' ):" << "\n"; 27 | std::cout << replicate( "replication"_kw = 7, "letter"_kw = '*' ) << "\n"; 28 | } 29 | 30 | int main() 31 | { 32 | scenario_1(); 33 | } 34 | -------------------------------------------------------------------------------- /test/unit/drop.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #define TTS_MAIN 9 | #include "common.hpp" 10 | #include 11 | #include 12 | 13 | TTS_CASE("Check drop constexpr behavior") 14 | { 15 | using namespace std::literals; 16 | using namespace rbr::literals; 17 | 18 | constexpr rbr::settings v ( custom_ = foo {} 19 | , "surname"_kw = 'z' 20 | , value_ = 3.f 21 | , "aligned"_fl 22 | , is_transparent_ 23 | ); 24 | 25 | // clang++-14 debug regression fix 26 | constexpr auto surname = "surname"_kw; 27 | constexpr auto aligned = "aligned"_fl; 28 | 29 | constexpr auto v0 = drop(is_transparent_, v); 30 | TTS_CONSTEXPR_EXPECT (v0.contains(custom_) ); 31 | TTS_CONSTEXPR_EXPECT (v0.contains(surname) ); 32 | TTS_CONSTEXPR_EXPECT (v0.contains(value_) ); 33 | TTS_CONSTEXPR_EXPECT (v0.contains(aligned) ); 34 | TTS_CONSTEXPR_EXPECT_NOT (v0.contains(is_transparent_)); 35 | TTS_CONSTEXPR_EQUAL (v0.size(), 4 ); 36 | 37 | constexpr auto v1 = drop(aligned, v0); 38 | TTS_CONSTEXPR_EXPECT (v1.contains(custom_) ); 39 | TTS_CONSTEXPR_EXPECT (v1.contains(surname) ); 40 | TTS_CONSTEXPR_EXPECT (v1.contains(value_) ); 41 | TTS_CONSTEXPR_EXPECT_NOT (v1.contains(aligned) ); 42 | TTS_CONSTEXPR_EXPECT_NOT (v1.contains(is_transparent_)); 43 | TTS_CONSTEXPR_EQUAL (v1.size(), 3 ); 44 | 45 | constexpr auto v2 = drop(value_, v1); 46 | TTS_CONSTEXPR_EXPECT (v2.contains(custom_) ); 47 | TTS_CONSTEXPR_EXPECT (v2.contains(surname) ); 48 | TTS_CONSTEXPR_EXPECT_NOT (v2.contains(value_) ); 49 | TTS_CONSTEXPR_EXPECT_NOT (v2.contains(aligned) ); 50 | TTS_CONSTEXPR_EXPECT_NOT (v2.contains(is_transparent_)); 51 | TTS_CONSTEXPR_EQUAL (v2.size(), 2 ); 52 | 53 | constexpr auto v3 = drop(surname, v2); 54 | TTS_CONSTEXPR_EXPECT (v3.contains(custom_) ); 55 | TTS_CONSTEXPR_EXPECT_NOT (v3.contains(surname) ); 56 | TTS_CONSTEXPR_EXPECT_NOT (v3.contains(value_) ); 57 | TTS_CONSTEXPR_EXPECT_NOT (v3.contains(aligned) ); 58 | TTS_CONSTEXPR_EXPECT_NOT (v3.contains(is_transparent_)); 59 | TTS_CONSTEXPR_EQUAL (v3.size(), 1 ); 60 | 61 | constexpr auto v4 = drop(custom_, v3); 62 | TTS_CONSTEXPR_EXPECT_NOT (v4.contains(custom_) ); 63 | TTS_CONSTEXPR_EXPECT_NOT (v4.contains(surname) ); 64 | TTS_CONSTEXPR_EXPECT_NOT (v4.contains(value_) ); 65 | TTS_CONSTEXPR_EXPECT_NOT (v4.contains(aligned) ); 66 | TTS_CONSTEXPR_EXPECT_NOT (v4.contains(is_transparent_)); 67 | TTS_CONSTEXPR_EQUAL (v4.size(), 0 ); 68 | }; 69 | 70 | TTS_CASE("Check drop behavior") 71 | { 72 | using namespace std::literals; 73 | using namespace rbr::literals; 74 | 75 | auto alg = "aligned"_fl; 76 | 77 | rbr::settings v ( custom_ = foo {} 78 | , "surname"_kw = "john"s 79 | , value_ = 3.f 80 | , alg 81 | , is_transparent_ 82 | ); 83 | 84 | auto v0 = drop(is_transparent_, v); 85 | TTS_EXPECT (v0.contains(custom_) ); 86 | TTS_EXPECT (v0.contains("surname"_kw) ); 87 | TTS_EXPECT (v0.contains(value_) ); 88 | TTS_EXPECT (v0.contains(alg) ); 89 | TTS_EXPECT_NOT (v0.contains(is_transparent_) ); 90 | TTS_EQUAL (v0.size(), 4 ); 91 | 92 | auto v1 = drop(alg, v0); 93 | TTS_EXPECT (v1.contains(custom_) ); 94 | TTS_EXPECT (v1.contains("surname"_kw) ); 95 | TTS_EXPECT (v1.contains(value_) ); 96 | TTS_EXPECT_NOT (v1.contains(alg) ); 97 | TTS_EXPECT_NOT (v1.contains(is_transparent_) ); 98 | TTS_EQUAL (v1.size(), 3 ); 99 | 100 | auto v2 = drop(value_, v1); 101 | TTS_EXPECT (v2.contains(custom_) ); 102 | TTS_EXPECT (v2.contains("surname"_kw) ); 103 | TTS_EXPECT_NOT (v2.contains(value_) ); 104 | TTS_EXPECT_NOT (v2.contains(alg) ); 105 | TTS_EXPECT_NOT (v2.contains(is_transparent_) ); 106 | TTS_EQUAL (v2.size(), 2 ); 107 | 108 | auto v3 = drop("surname"_kw, v2); 109 | TTS_EXPECT (v3.contains(custom_) ); 110 | TTS_EXPECT_NOT (v3.contains("surname"_kw) ); 111 | TTS_EXPECT_NOT (v3.contains(value_) ); 112 | TTS_EXPECT_NOT (v3.contains(alg) ); 113 | TTS_EXPECT_NOT (v3.contains(is_transparent_) ); 114 | TTS_EQUAL (v3.size(), 1 ); 115 | 116 | auto v4 = drop(custom_, v3); 117 | TTS_EXPECT_NOT (v4.contains(custom_) ); 118 | TTS_EXPECT_NOT (v4.contains("surname"_kw) ); 119 | TTS_EXPECT_NOT (v4.contains(value_) ); 120 | TTS_EXPECT_NOT (v4.contains(alg) ); 121 | TTS_EXPECT_NOT (v4.contains(is_transparent_) ); 122 | TTS_EQUAL (v4.size(), 0 ); 123 | }; 124 | -------------------------------------------------------------------------------- /test/unit/extract_types.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #define TTS_MAIN 9 | #include "common.hpp" 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | TTS_CASE("Check rbr::keywords") 16 | { 17 | using namespace rbr::literals; 18 | 19 | auto opt = rbr::settings( "test"_kw = 1, "second"_kw = 3.5f, "last"_kw = 'z'); 20 | using opt_t = decltype(opt); 21 | 22 | TTS_TYPE_IS ( rbr::result::keywords_t 23 | , (rbr::types< decltype("test"_kw), decltype("second"_kw), decltype("last"_kw) >) 24 | ); 25 | 26 | TTS_EXPR_IS ( (std::tuple{"test"_kw, "second"_kw, "last"_kw}) 27 | , (rbr::result::keywords_t) 28 | ); 29 | 30 | TTS_EQUAL( (std::tuple{"test"_kw, "second"_kw, "last"_kw}), (rbr::keywords(opt))); 31 | }; 32 | 33 | TTS_CASE("Check rbr::values") 34 | { 35 | using namespace rbr::literals; 36 | 37 | auto opt = rbr::settings( "test"_kw = 1, "second"_kw = 3.5f, "last"_kw = 'z'); 38 | using opt_t = decltype(opt); 39 | 40 | TTS_TYPE_IS( rbr::result::values_t , (rbr::types) ); 41 | TTS_TYPE_IS( (rbr::result::values_t), (std::variant)); 42 | TTS_EQUAL ( (std::tuple{1,3.5f,'z'}) , (rbr::values(opt))); 43 | }; 44 | -------------------------------------------------------------------------------- /test/unit/fetch.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #define TTS_MAIN 9 | #include "common.hpp" 10 | #include 11 | #include 12 | 13 | TTS_CASE("Check rbr::fetch behavior on options") 14 | { 15 | using namespace std::literals; 16 | using namespace rbr::literals; 17 | 18 | TTS_EQUAL( (rbr::fetch(coord_ , coord_ = "Jane"s, value_ = 4.2f, is_modal_)) , "Jane"s ); 19 | TTS_EQUAL( (rbr::fetch(value_ , coord_ = "Jane"s, value_ = 4.2f, is_modal_)) , 4.2f ); 20 | TTS_EQUAL( (rbr::fetch(is_modal_, coord_ = "Jane"s, value_ = 4.2f, is_modal_)) , true ); 21 | TTS_EQUAL( (rbr::fetch("flop"_kw | 66., coord_ = "Jane"s, value_ = 4.2f, is_modal_)), 66. ); 22 | 23 | TTS_EXPR_IS ( (rbr::fetch("flop"_kw, coord_ = "Jane"s, value_ = 4.2f, is_modal_)) 24 | , rbr::unknown_key 25 | ); 26 | }; 27 | 28 | TTS_CASE("Check rbr::fetch behavior on settings") 29 | { 30 | using namespace std::literals; 31 | using namespace rbr::literals; 32 | 33 | auto opts = rbr::settings(coord_ = "Jane"s, value_ = 4.2f, is_modal_); 34 | 35 | TTS_EQUAL( (rbr::fetch(coord_ , opts)), "Jane"s ); 36 | TTS_EQUAL( (rbr::fetch(value_ , opts)), 4.2f ); 37 | TTS_EQUAL( (rbr::fetch(is_modal_ , opts)), true ); 38 | TTS_EQUAL( (rbr::fetch("flop"_kw | 66., opts)), 66. ); 39 | 40 | TTS_EXPR_IS( (rbr::fetch("flop"_kw, opts)), rbr::unknown_key ); 41 | }; 42 | 43 | TTS_CASE("Check rbr::fetch_t behavior on options") 44 | { 45 | using namespace std::literals; 46 | using namespace rbr::literals; 47 | 48 | using opt1_t = decltype(coord_ = "Jane Doe"s); 49 | using opt2_t = decltype(value_ = 42.69f); 50 | using opt3_t = decltype(is_modal_); 51 | 52 | TTS_TYPE_IS( (rbr::result::fetch_t), std::string ); 53 | TTS_TYPE_IS( (rbr::result::fetch_t), float ); 54 | TTS_TYPE_IS( (rbr::result::fetch_t), bool ); 55 | TTS_TYPE_IS( (rbr::result::fetch_t<"flop"_kw, opt1_t, opt2_t, opt3_t>), rbr::unknown_key); 56 | }; 57 | 58 | TTS_CASE("Check rbr::fetch_t behavior on settings") 59 | { 60 | using namespace std::literals; 61 | using namespace rbr::literals; 62 | 63 | using opts_t = decltype(rbr::settings(coord_ = "Jane"s, value_ = 4.2f, is_modal_)); 64 | 65 | TTS_TYPE_IS( (rbr::result::fetch_t), std::string ); 66 | TTS_TYPE_IS( (rbr::result::fetch_t), float ); 67 | TTS_TYPE_IS( (rbr::result::fetch_t), bool ); 68 | TTS_TYPE_IS( (rbr::result::fetch_t<"flop"_kw, opts_t>), rbr::unknown_key); 69 | }; 70 | 71 | TTS_CASE("Check keyword fetching behavior") 72 | { 73 | using namespace std::literals; 74 | using namespace rbr::literals; 75 | 76 | TTS_EQUAL( (coord_ (coord_ = "Jane"s, value_ = 4.2f, is_modal_)), "Jane"s ); 77 | TTS_EQUAL( (value_ (coord_ = "Jane"s, value_ = 4.2f, is_modal_)), 4.2f ); 78 | TTS_EQUAL( (is_modal_(coord_ = "Jane"s, value_ = 4.2f, is_modal_)), true ); 79 | TTS_EXPR_IS( ("flop"_kw(coord_ = "Jane"s, value_ = 4.2f, is_modal_)), rbr::unknown_key ); 80 | TTS_EQUAL( (("flop"_kw | 66.)(coord_ = "Jane"s, value_ = 4.2f, is_modal_)), 66. ); 81 | }; 82 | -------------------------------------------------------------------------------- /test/unit/interface.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #define TTS_MAIN 9 | #include "common.hpp" 10 | #include 11 | #include 12 | 13 | constexpr auto 14 | named_interface(rbr::concepts::option auto const &...vs) noexcept 15 | { 16 | rbr::settings s(vs...); 17 | return s[coord_] * s[value_]; 18 | } 19 | 20 | template 21 | constexpr auto filtered_interface(Vs const &...vs) noexcept 22 | requires( rbr::settings::contains_any(coord_, value_) ) 23 | { 24 | rbr::settings s(vs...); 25 | return s[coord_] * s[value_]; 26 | } 27 | 28 | template 29 | constexpr auto restricted_interface(Vs const &...vs) noexcept 30 | requires( rbr::settings::contains_only(coord_, value_) ) 31 | { 32 | rbr::settings s(vs...); 33 | return s[coord_] * s[value_]; 34 | } 35 | 36 | TTS_CASE("Check settings(...) as function interface with named parameters") 37 | { 38 | TTS_EQUAL(named_interface(coord_ = 10, value_ = 3.4f), 34.f); 39 | TTS_EQUAL(named_interface(value_ = 3.4f, coord_ = 10), 34.f); 40 | }; 41 | 42 | TTS_CASE("Check settings(...) as constexpr function interface with named parameters") 43 | { 44 | TTS_CONSTEXPR_EQUAL(named_interface(coord_ = 10, value_ = 3.4f), 34.f); 45 | TTS_CONSTEXPR_EQUAL(named_interface(value_ = 3.4f, coord_ = 10), 34.f); 46 | }; 47 | 48 | TTS_CASE("Check settings(...) as function interface with filtered named parameters") 49 | { 50 | TTS_EQUAL(filtered_interface(coord_ = 10, value_ = 3.4f), 34.f); 51 | TTS_EQUAL(filtered_interface(value_ = 3.4f, coord_ = 10), 34.f); 52 | TTS_EQUAL(filtered_interface(coord_ = 10, value_ = 3.4f, is_modal_), 34.f); 53 | TTS_EQUAL(filtered_interface(coord_ = 10, is_modal_, value_ = 3.4f), 34.f); 54 | }; 55 | 56 | TTS_CASE("Check settings(...) as constexpr function interface with filtered named parameters") 57 | { 58 | TTS_CONSTEXPR_EQUAL(filtered_interface(coord_ = 10, value_ = 3.4f), 34.f); 59 | TTS_CONSTEXPR_EQUAL(filtered_interface(value_ = 3.4f, coord_ = 10), 34.f); 60 | TTS_CONSTEXPR_EQUAL(filtered_interface(coord_ = 10, value_ = 3.4f, is_modal_), 34.f); 61 | TTS_CONSTEXPR_EQUAL(filtered_interface(coord_ = 10, is_modal_, value_ = 3.4f), 34.f); 62 | }; 63 | 64 | TTS_CASE("Check settings(...) as function interface with restricted named parameters") 65 | { 66 | TTS_EQUAL(restricted_interface(coord_ = 10, value_ = 3.4f), 34.f); 67 | TTS_EQUAL(restricted_interface(value_ = 3.4f, coord_ = 10), 34.f); 68 | }; 69 | 70 | TTS_CASE("Check settings(...) as constexpr function interface with restricted named parameters") 71 | { 72 | TTS_CONSTEXPR_EQUAL(restricted_interface(coord_ = 10, value_ = 3.4f), 34.f); 73 | TTS_CONSTEXPR_EQUAL(restricted_interface(value_ = 3.4f, coord_ = 10), 34.f); 74 | }; 75 | -------------------------------------------------------------------------------- /test/unit/merge.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #define TTS_MAIN 9 | #include "common.hpp" 10 | #include 11 | #include 12 | 13 | TTS_CASE("Check merge behavior: large defaults, few options") 14 | { 15 | using namespace std::literals; 16 | 17 | auto defaults = rbr::settings(coord_ = "Jane Doe"s, value_ = 42.69f, is_modal_); 18 | auto opts = rbr::settings(value_ = 956.7f); 19 | 20 | auto merged = rbr::merge(opts, defaults); 21 | 22 | TTS_EQUAL(merged[value_ ], 956.7f ); 23 | TTS_EQUAL(merged[coord_ ], "Jane Doe"s ); 24 | TTS_EQUAL(merged[is_modal_], true ); 25 | 26 | auto nopts = rbr::settings("other"_kw = 1234); 27 | auto merged2 = rbr::merge(nopts, defaults); 28 | 29 | TTS_EQUAL(merged2[value_] , 42.69f ); 30 | TTS_EQUAL(merged2["other"_kw] , 1234 ); 31 | TTS_EQUAL(merged2[coord_] , "Jane Doe"s ); 32 | TTS_EQUAL(merged2[is_modal_] , true ); 33 | }; 34 | 35 | TTS_CASE("Check merge behavior: few defaults, large options") 36 | { 37 | using namespace std::literals; 38 | 39 | auto opts = rbr::settings(coord_ = "Jane Doe"s, value_ = 42.69f, is_modal_); 40 | auto defaults = rbr::settings(value_ = 956.7f); 41 | 42 | auto merged = rbr::merge(opts, defaults); 43 | 44 | TTS_EQUAL(merged[value_ ], 42.69f ); 45 | TTS_EQUAL(merged[coord_ ], "Jane Doe"s ); 46 | TTS_EQUAL(merged[is_modal_], true ); 47 | 48 | auto ndefaults = rbr::settings("other"_kw = 1234); 49 | auto merged2 = rbr::merge( opts, ndefaults); 50 | 51 | TTS_EQUAL(merged2[value_] , 42.69f ); 52 | TTS_EQUAL(merged2["other"_kw] , 1234 ); 53 | TTS_EQUAL(merged2[coord_] , "Jane Doe"s ); 54 | TTS_EQUAL(merged2[is_modal_] , true ); 55 | }; 56 | -------------------------------------------------------------------------------- /test/unit/size.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | RABERU - Fancy Parameters Library 4 | Copyright : RABERU Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #define TTS_MAIN 9 | #include "common.hpp" 10 | #include 11 | #include 12 | 13 | TTS_CASE("Check settings(...) size") 14 | { 15 | using namespace std::literals; 16 | using namespace rbr::literals; 17 | 18 | TTS_EQUAL(rbr::settings("custom"_kw = foo {}).size(), 1); 19 | TTS_EQUAL(rbr::settings("custom"_kw = foo {}, "border"_fl).size(), 2); 20 | TTS_EQUAL(rbr::settings("custom"_kw = foo {}, "name"_kw = "john"s, "border"_fl).size(), 3); 21 | 22 | constexpr auto any = rbr::any_keyword>{}; 23 | auto set = rbr::settings(any = foo {}); 24 | std::cout << set << "\n"; 25 | }; 26 | 27 | TTS_CASE("Check settings(...) constexpr size - named parameters") 28 | { 29 | using namespace std::literals; 30 | using namespace rbr::literals; 31 | 32 | TTS_CONSTEXPR_EQUAL(rbr::settings("custom"_kw = foo{}).size(), 1); 33 | TTS_CONSTEXPR_EQUAL(rbr::settings("custom"_kw = foo{}, "value"_kw = 3.f).size(), 2); 34 | TTS_CONSTEXPR_EQUAL(rbr::settings("custom"_kw = foo{}, "coord"_kw = point{}, "value"_kw = 3.f).size(), 3); 35 | }; 36 | --------------------------------------------------------------------------------