├── .clang-format ├── .github ├── ISSUE_TEMPLATE │ ├── gcl-bug-report.md │ └── gcl-feature-request.md └── workflows │ ├── MSBuild-Windows-CL_latest.yml │ ├── cmake-Ubuntu-clang_latest.yml │ ├── cmake-Ubuntu-gcc_10.yml │ └── cmake-Windows-ClangCL_latest.yml ├── .gitignore ├── CMakeLists.txt ├── CMakeSettings.json ├── GCL_CPP.sln ├── GCL_CPP.vcxproj ├── GCL_CPP.vcxproj.filters ├── LICENSE ├── README.md ├── includes ├── gcl │ ├── algorithms │ │ ├── README.md │ │ ├── algorithms.hpp │ │ ├── maths.hpp │ │ └── ranges.hpp │ ├── compile_time_constant │ │ ├── README.md │ │ ├── algorithms.hpp │ │ ├── algorithms │ │ │ ├── array.hpp │ │ │ └── tuple.hpp │ │ └── ctc.hpp │ ├── concepts.hpp │ ├── container │ │ ├── concepts.hpp │ │ ├── interval_map.hpp │ │ ├── tuple_view.hpp │ │ └── utility.hpp │ ├── cx │ │ ├── array.hpp │ │ ├── crc32_hash.hpp │ │ ├── cx.hpp │ │ ├── typeinfo.hpp │ │ └── unordered_map.hpp │ ├── functional.hpp │ ├── io │ │ ├── concepts.hpp │ │ ├── io.hpp │ │ ├── policy.hpp │ │ ├── serialization.hpp │ │ └── traits.hpp │ ├── mp │ │ ├── cast.hpp │ │ ├── concepts.hpp │ │ ├── function_traits.hpp │ │ ├── meta │ │ │ ├── functional.hpp │ │ │ ├── meta.hpp │ │ │ ├── operations.hpp │ │ │ ├── pack_trait.hpp │ │ │ └── tuple.hpp │ │ ├── mp.hpp │ │ ├── pack_traits.hpp │ │ ├── preprocessor.hpp │ │ ├── type_tag.hpp │ │ ├── type_traits.hpp │ │ ├── utility.hpp │ │ └── value_traits.hpp │ └── pattern │ │ ├── ecs.hpp │ │ └── strong_type.hpp └── gcl_cpp_deprecated │ ├── IO.h │ ├── color.h │ ├── container │ ├── component_aggregator.hpp │ ├── entity_vector.hpp │ ├── linear_vector.hpp │ ├── polymorphic_reference.hpp │ ├── polymorphic_vector.hpp │ └── utility.hpp │ ├── event.hpp │ ├── exception.hpp │ ├── functional.hpp │ ├── introspection.hpp │ ├── maths.h │ ├── mp.hpp │ ├── old │ ├── EventHandler.h │ ├── Experimental.h │ ├── Monitoring.h │ ├── SelfUpdate.h │ ├── TestUtils.h │ ├── control_center.hpp │ ├── filesystem.hpp │ ├── log.hpp │ ├── ownership.hpp │ ├── task.hpp │ └── thread.hpp │ ├── pattern │ ├── ecs.hpp │ └── state_machine.hpp │ ├── preprocessor.hpp │ ├── serialisation.hpp │ ├── signals.hpp │ ├── test.hpp │ ├── tuple_utils.hpp │ ├── type_index.hpp │ └── type_info.hpp └── tests ├── CMakeLists.txt ├── Main.cpp └── gcl └── test ├── container.hpp ├── container ├── component_aggregator.hpp ├── entity_vector.hpp ├── polymorphic_reference.hpp └── polymorphic_vector.hpp ├── event.hpp ├── gcl.hpp ├── introspection.hpp ├── mp.hpp ├── pattern.hpp ├── pattern └── ecs.hpp ├── test.hpp ├── type_index.hpp └── type_info.hpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Microsoft 3 | Language: Cpp 4 | AlignAfterOpenBracket: AlwaysBreak 5 | AlignConsecutiveDeclarations: 'true' 6 | AlignTrailingComments: 'true' 7 | # AllowShortEnumsOnASingleLine : 'true' 8 | AllowShortFunctionsOnASingleLine: InlineOnly 9 | # AllowShortLambdasOnASingleLine: SLS_Inline 10 | AlwaysBreakBeforeMultilineStrings: 'true' 11 | AlwaysBreakTemplateDeclarations: 'Yes' 12 | BinPackArguments: 'false' 13 | BinPackParameters: 'false' 14 | # BreakBeforeConceptDeclarations: 'true' 15 | # IndentRequires: 'true' 16 | SpaceAfterTemplateKeyword: 'true' 17 | SpacesInAngles: 'false' 18 | # BreakBeforeBraces: Allman 19 | BreakBeforeBraces: Custom 20 | BraceWrapping: 21 | AfterEnum: true 22 | AfterClass: false 23 | AfterStruct: false 24 | #BeforeLambdaBody: false 25 | SplitEmptyFunction: false 26 | SplitEmptyRecord: false 27 | 28 | BreakBeforeTernaryOperators: 'true' 29 | BreakConstructorInitializers: BeforeComma 30 | BreakInheritanceList: BeforeComma 31 | Cpp11BracedListStyle: 'true' 32 | NamespaceIndentation: All 33 | FixNamespaceComments: 'false' 34 | PointerAlignment: "Left" 35 | IndentWidth: 4 36 | TabWidth: 4 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/gcl-bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: GCL Bug report 3 | about: Create a report to help us improve GCL components 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### **Component name** 11 | 12 | *(ex : `gcl::mp::function_traits`. use `gcl` if your issue impacts the whole library)* 13 | 14 | ### **Context** 15 | 16 | - OS : *(ex : Ubuntu 20.04)* 17 | - Configuration(s) : *(ex : x64-RelWithDebInfos)* 18 | - Compiler(s) name + release : *(ex : `Clang 11.0.1`)* 19 | - Runtime or compile-time issue ? 20 | - [ ] Compile time issue 21 | - [ ] Runtime issue 22 | - Project build / generation 23 | - [ ] CMake 24 | - [ ] MSVC 25 | - [ ] Direct include `gcl/includes` *(git submodule, CMake FetchContent/ExternalProject_Add, etc.)* 26 | 27 | ### **Describe the bug** 28 | A clear and concise description of what the bug is. 29 | 30 | ### **To Reproduce** 31 | A minimal code example that demonstrates the issue. `Godbolt` links are OK too. 32 | 33 | ### **Expected behavior** 34 | A clear and concise description of what you expected to happen. 35 | 36 | ### **Additional context** 37 | Add any other context about the problem here. 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/gcl-feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: GCL enhancement / feature request 3 | about: Suggest enhancement or new feature your idea about GCL 4 | title: "[REQUEST]" 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### **Scope** 11 | 12 | - [ ] C++ 13 | - [ ] New `gcl` component 14 | - [ ] New language standard support 15 | - [ ] CMake 16 | - [ ] CI 17 | - [ ] Configuration support 18 | - [ ] Compiler support 19 | - [ ] OS support 20 | - [ ] Architecture support 21 | - [ ] Documentation 22 | 23 | ### **Description** 24 | 25 | A clear and concise description of what the suggestion is about. 26 | 27 | *Examples :* 28 | 29 | - `C++` : new `gcl::event` implementation 30 | - `configuration`: Add Windows-MsCL-x64-RelWithDebInfos configuration support)* 31 | 32 | ### **Details** 33 | 34 | Details about your suggestion. 35 | Might contain implementation details, designs, links to external components, etc. 36 | 37 | ### **[optional] Expected behavior** 38 | A clear and concise description of what you expected to happen. 39 | 40 | ### **[optional] Additional context** 41 | Add any other context about the suggestion here here. 42 | -------------------------------------------------------------------------------- /.github/workflows/MSBuild-Windows-CL_latest.yml: -------------------------------------------------------------------------------- 1 | name: MSBuild-Windows-CL_latest 2 | 3 | on: [push, pull_request] 4 | 5 | env: 6 | SOLUTION_FILE_PATH: . 7 | 8 | jobs: 9 | build: 10 | runs-on: windows-latest 11 | 12 | strategy: 13 | matrix: 14 | BUILD_TYPE: [Debug, Release] 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | 19 | - name: Add MSBuild to PATH 20 | uses: microsoft/setup-msbuild@v1 21 | 22 | - name: Restore NuGet packages 23 | working-directory: ${{env.GITHUB_WORKSPACE}} 24 | run: nuget restore ${{env.SOLUTION_FILE_PATH}} 25 | 26 | - name: Build - ${{matrix.BUILD_TYPE}} 27 | working-directory: ${{env.GITHUB_WORKSPACE}} 28 | # Add additional options to the MSBuild command line here (like platform or verbosity level). 29 | # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference 30 | run: msbuild /m /p:Configuration=${{matrix.BUILD_TYPE}} ${{env.SOLUTION_FILE_PATH}} 31 | -------------------------------------------------------------------------------- /.github/workflows/cmake-Ubuntu-clang_latest.yml: -------------------------------------------------------------------------------- 1 | name: cmake-Ubuntu-clang_latest 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | matrix: 12 | BUILD_TYPE: [Debug, Release] 13 | STL_IMPLEMENTATION: [libstdc++, libc++ -lc++abi] 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | 18 | - name: Initialize compiler (Clang, latest) 19 | run: | 20 | sudo apt update 21 | sudo apt install libstdc++-10-dev 22 | sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" 23 | sudo update-alternatives \ 24 | --install /usr/bin/clang clang /usr/bin/clang-12 100 25 | sudo update-alternatives \ 26 | --install /usr/bin/clang++ clang++ /usr/bin/clang++-12 100 27 | sudo apt install libc++1-12 libc++-12-dev libc++abi-12-dev libc++abi1-12 28 | 29 | - name: cmake create build env - ${{matrix.BUILD_TYPE}} - ${{matrix.STL_IMPLEMENTATION}} 30 | run: | 31 | cmake -E make_directory ${{github.workspace}}/out/build/${{matrix.BUILD_TYPE}} 32 | cmake -E make_directory ${{github.workspace}}/out/install/${{matrix.BUILD_TYPE}} 33 | 34 | - name: cmake cache - ${{matrix.BUILD_TYPE}} - ${{matrix.STL_IMPLEMENTATION}} 35 | run: | 36 | cmake \ 37 | -DCMAKE_CXX_FLAGS="-stdlib=${{matrix.STL_IMPLEMENTATION}}" \ 38 | -DGCL_BUILD_TEST:BOOL=TRUE \ 39 | -DCMAKE_BUILD_TYPE:STRING="${{matrix.BUILD_TYPE}}" \ 40 | -DCMAKE_INSTALL_PREFIX:PATH=${{github.workspace}}/out/install/${{matrix.BUILD_TYPE}} \ 41 | -S ${{github.workspace}} \ 42 | -B ${{github.workspace}}/out/build/${{matrix.BUILD_TYPE}} 43 | 44 | env: 45 | CC: clang-12 46 | CXX: clang++-12 47 | 48 | - name: cmake build - ${{matrix.BUILD_TYPE}} - ${{matrix.STL_IMPLEMENTATION}} 49 | run: | 50 | cmake \ 51 | --build ${{github.workspace}}/out/build/${{matrix.BUILD_TYPE}} \ 52 | --config ${{matrix.BUILD_TYPE}} 53 | 54 | #- name: Test 55 | # working-directory: ${{github.workspace}}/build 56 | # shell: bash 57 | # # Execute tests defined by the CMake configuration. 58 | # # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail 59 | # run: ctest -C $BUILD_TYPE 60 | -------------------------------------------------------------------------------- /.github/workflows/cmake-Ubuntu-gcc_10.yml: -------------------------------------------------------------------------------- 1 | name: cmake-Ubuntu-gcc_10 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | matrix: 12 | BUILD_TYPE: [Debug, Release] 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | 17 | - name: Initialize compiler (GCC) 18 | run: | 19 | sudo apt update 20 | sudo apt install gcc-10 g++-10 21 | sudo update-alternatives \ 22 | --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 \ 23 | --slave /usr/bin/g++ g++ /usr/bin/g++-10 \ 24 | --slave /usr/bin/gcov gcov /usr/bin/gcov-10 25 | 26 | - name: cmake create build env - ${{matrix.BUILD_TYPE}} 27 | run: | 28 | cmake -E make_directory ${{github.workspace}}/out/build/${{matrix.BUILD_TYPE}} 29 | cmake -E make_directory ${{github.workspace}}/out/install/${{matrix.BUILD_TYPE}} 30 | 31 | - name: cmake cache - ${{matrix.BUILD_TYPE}} 32 | #shell: bash 33 | #working-directory: ${{github.workspace}}/out/build/${{matrix.BUILD_TYPE}} 34 | run: | 35 | cmake \ 36 | -DGCL_BUILD_TEST:BOOL=TRUE \ 37 | -DCMAKE_BUILD_TYPE:STRING=${{matrix.BUILD_TYPE}} \ 38 | -DCMAKE_INSTALL_PREFIX:PATH=${{github.workspace}}/out/install/${{matrix.BUILD_TYPE}} \ 39 | -S ${{github.workspace}} \ 40 | -B ${{github.workspace}}/out/build/${{matrix.BUILD_TYPE}} 41 | 42 | env: 43 | CC: gcc-10 44 | CXX: g++-10 45 | 46 | - name: cmake build - ${{matrix.BUILD_TYPE}} 47 | #working-directory: ${{github.workspace}}/out/build/${{matrix.BUILD_TYPE}} 48 | run: | 49 | cmake \ 50 | --build ${{github.workspace}}/out/build/${{matrix.BUILD_TYPE}} \ 51 | --config ${{matrix.BUILD_TYPE}} 52 | 53 | #- name: Test 54 | # working-directory: ${{github.workspace}}/build 55 | # shell: bash 56 | # # Execute tests defined by the CMake configuration. 57 | # # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail 58 | # run: ctest -C $BUILD_TYPE 59 | -------------------------------------------------------------------------------- /.github/workflows/cmake-Windows-ClangCL_latest.yml: -------------------------------------------------------------------------------- 1 | name: cmake-Windows-ClangCL 2 | 3 | on: [push, pull_request] 4 | 5 | env: 6 | SOLUTION_FILE_PATH: . 7 | 8 | jobs: 9 | build: 10 | 11 | runs-on: windows-latest 12 | 13 | strategy: 14 | matrix: 15 | BUILD_TYPE: [Debug, Release] 16 | ARCH: [Win32, x64] 17 | GENERATOR: ["Visual Studio 16 2019"] 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | 22 | - name: cmake create build env - ${{matrix.ARCH}} ${{matrix.BUILD_TYPE}} 23 | run: | 24 | cmake -E make_directory ${{github.workspace}}/out/build/${{matrix.ARCH}}/${{matrix.BUILD_TYPE}} 25 | cmake -E make_directory ${{github.workspace}}/out/install/${{matrix.ARCH}}/${{matrix.BUILD_TYPE}} 26 | 27 | - name: cmake cache - ${{matrix.ARCH}} ${{matrix.BUILD_TYPE}} 28 | #working-directory: ${{github.workspace}}/out/build/${{matrix.ARCH}}/${{matrix.BUILD_TYPE}} 29 | run: | 30 | cmake ` 31 | -DGCL_BUILD_TEST:BOOL=TRUE ` 32 | -DCMAKE_BUILD_TYPE:STRING="${{matrix.BUILD_TYPE}}" ` 33 | -DCMAKE_INSTALL_PREFIX:PATH=${{github.workspace}}/out/install/${{matrix.ARCH}}/${{matrix.BUILD_TYPE}} ` 34 | -S ${{github.workspace}} ` 35 | -B ${{github.workspace}}/out/build/${{matrix.ARCH}}/${{matrix.BUILD_TYPE}} ` 36 | -G "${{matrix.GENERATOR}}" ` 37 | -A ${{matrix.ARCH}} ` 38 | -T ClangCL 39 | 40 | - name: cmake build - ${{matrix.ARCH}} ${{matrix.BUILD_TYPE}} 41 | #working-directory: ${{github.workspace}}/out/build/${{matrix.ARCH}}/${{matrix.BUILD_TYPE}} 42 | run: | 43 | cmake ` 44 | --build ${{github.workspace}}/out/build/${{matrix.ARCH}}/${{matrix.BUILD_TYPE}} ` 45 | --config ${{matrix.BUILD_TYPE}} ` 46 | --parallel 10 47 | 48 | #- name: test 49 | # run: cd build ; ctest -j 10 -C Debug --output-on-failure 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # MSVC 2 | *.vs 3 | bin 4 | out 5 | Debug/ 6 | Release/ 7 | *.vcxproj.user 8 | *.idb 9 | *.pdb 10 | 11 | # CMake 12 | build/ 13 | 14 | # Outputs 15 | *.o 16 | *.obj 17 | *.elf 18 | *.lo 19 | *.slo 20 | *.gch 21 | *.pch 22 | *.so 23 | *.so.* 24 | *.dylib 25 | *.dll 26 | *.lai 27 | *.la 28 | *.a 29 | *.lib 30 | 31 | x64 32 | x86 33 | *.exe 34 | *.out 35 | *.app 36 | *.i*86 37 | *.x86_64 38 | *.hex -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(GCL VERSION 2.0 LANGUAGES CXX) 3 | 4 | option(${PROJECT_NAME}_ENABLE_COMPILE_TIME_TESTS "${PROJECT_NAME} : Build compile-time tests ?" OFF) 5 | message(STATUS "${PROJECT_NAME} -- ${PROJECT_NAME}_ENABLE_COMPILE_TIME_TESTS is ${${PROJECT_NAME}_ENABLE_COMPILE_TIME_TESTS}") 6 | if (${${PROJECT_NAME}_ENABLE_COMPILE_TIME_TESTS}) 7 | add_compile_definitions(${PROJECT_NAME}_ENABLE_COMPILE_TIME_TESTS) 8 | endif() 9 | 10 | add_library(gcl_cpp INTERFACE) 11 | target_include_directories(gcl_cpp INTERFACE 12 | ${CMAKE_CURRENT_SOURCE_DIR}/includes 13 | ) 14 | target_compile_features(gcl_cpp INTERFACE 15 | cxx_std_20 16 | # C++11 17 | cxx_lambdas 18 | cxx_noexcept 19 | cxx_auto_type 20 | cxx_constexpr 21 | cxx_static_assert 22 | cxx_alias_templates 23 | cxx_rvalue_references 24 | # C++14 25 | cxx_decltype_auto 26 | cxx_generic_lambdas 27 | cxx_variable_templates 28 | cxx_variadic_templates 29 | cxx_return_type_deduction 30 | cxx_aggregate_default_initializers 31 | ) 32 | 33 | option(${PROJECT_NAME}_BUILD_TEST "${PROJECT_NAME} : Build tests ?" OFF) 34 | message(STATUS "${PROJECT_NAME} -- ${PROJECT_NAME}_BUILD_TEST is ${${PROJECT_NAME}_BUILD_TEST}") 35 | if (${PROJECT_NAME}_BUILD_TEST) 36 | message(STATUS "${PROJECT_NAME} -- ${PROJECT_NAME}_BUILD_TEST -- forcing ${PROJECT_NAME}_ENABLE_COMPILE_TIME_TESTS to ON") 37 | add_compile_definitions(${PROJECT_NAME}_ENABLE_COMPILE_TIME_TESTS) 38 | message(STATUS "${PROJECT_NAME} -- ${PROJECT_NAME}_BUILD_TEST -- forcing ${PROJECT_NAME}_ENABLE_RUNTIME_TESTS to ON") 39 | add_compile_definitions(${PROJECT_NAME}_ENABLE_RUNTIME_TESTS) 40 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests) 41 | endif() 42 | 43 | # todo : include2dot 44 | # todo : dependency graph 45 | # cmake SRC_DIR --graphviz=xxx.dot 46 | # dot -Tpng xxx.dot xxx.pgf 47 | -------------------------------------------------------------------------------- /GCL_CPP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30804.86 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GCL_CPP", "GCL_CPP.vcxproj", "{7D0A45A0-457D-4DDC-85BB-1ADC4522A653}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {7D0A45A0-457D-4DDC-85BB-1ADC4522A653}.Debug|x64.ActiveCfg = Debug|x64 17 | {7D0A45A0-457D-4DDC-85BB-1ADC4522A653}.Debug|x64.Build.0 = Debug|x64 18 | {7D0A45A0-457D-4DDC-85BB-1ADC4522A653}.Debug|x86.ActiveCfg = Debug|Win32 19 | {7D0A45A0-457D-4DDC-85BB-1ADC4522A653}.Debug|x86.Build.0 = Debug|Win32 20 | {7D0A45A0-457D-4DDC-85BB-1ADC4522A653}.Release|x64.ActiveCfg = Release|x64 21 | {7D0A45A0-457D-4DDC-85BB-1ADC4522A653}.Release|x64.Build.0 = Release|x64 22 | {7D0A45A0-457D-4DDC-85BB-1ADC4522A653}.Release|x86.ActiveCfg = Release|Win32 23 | {7D0A45A0-457D-4DDC-85BB-1ADC4522A653}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {936D6F6A-8EC1-4CF0-A70E-28F052AECBA4} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # **GCL C++** 2 | 3 | [![Ubuntu CMake Clang latest](https://github.com/GuillaumeDua/GCL_CPP/actions/workflows/cmake-Ubuntu-clang_latest.yml/badge.svg)](https://github.com/GuillaumeDua/GCL_CPP/actions/workflows/cmake-Ubuntu-clang_latest.yml) 4 | [![Ubuntu CMake GCC 10](https://github.com/GuillaumeDua/GCL_CPP/actions/workflows/cmake-Ubuntu-gcc_10.yml/badge.svg)](https://github.com/GuillaumeDua/GCL_CPP/actions/workflows/cmake-Ubuntu-gcc_10.yml) 5 | [![MSBuild-Windows-CL_latest](https://github.com/GuillaumeDua/GCL_CPP/actions/workflows/MSBuild-Windows-CL_latest.yml/badge.svg)](https://github.com/GuillaumeDua/GCL_CPP/actions/workflows/MSBuild-Windows-CL_latest.yml) 6 | [![Windows CMake ClangCL](https://github.com/GuillaumeDua/GCL_CPP/actions/workflows/cmake-Windows-ClangCL.yml/badge.svg)](https://github.com/GuillaumeDua/GCL_CPP/actions/workflows/cmake-Windows-ClangCL.yml) 7 | 8 | :construction: **WIP** : [see milestone v1 -> v2](https://github.com/GuillaumeDua/GCL_CPP/milestone/2) 9 | 10 | --- 11 | 12 | This **modern-C++**, **header-only library** is a stack of useful and convinient components that make my everyday projects & jobs way easier. 13 | 14 | Each **component** *(spli by namespaces)* aims to be : 15 | 16 | - **easy-to-use** 17 | - **easy-to-maintain** 18 | - **powerful** 19 | 20 | > **NB :** This library is a never-ending WIP, as it matches needs according to the C++ standards and compilers implementations. 21 | > Thus, many components only exists to fill what I consider to be STL holes, and so are likely to disappear when standard features are implemented *-and released-* in the standard and by compilers. 22 | 23 | ## Build 24 | 25 | This library is header-only, meaning you only need to add `includes/gcl` to your include path. 26 | 27 | However, a `CMake` target exposes an `gcl_cpp` INTERFACE library target that you can integrate into your build. 28 | 29 | Currently, the only available option is `gcl_cpp_BUILD_TEST` - which is set to `OFF` by default - that generates a binary to run runtime tests. 30 | 31 | ## Tests 32 | 33 | As this library components are mainly template-metaprogramming or constexpr ones, most of the tests are processed at **`compile-time`**. 34 | 35 | Currently, there is no option to disable compile-time tests. 36 | *If you need such option, create a Github issue, or make a pull-request.* 37 | 38 | As mentioned in the previous section, a CMake target can be generate, when enabling the `gcl_cpp_BUILD_TEST` option. 39 | However, it only cover runtime tests. 40 | 41 | ## Versions 42 | 43 | | Name | Description | 44 | | ---- | ----------- | 45 | | **`v2`** | [WIP/refactoring](https://github.com/GuillaumeDua/GCL_CPP/milestone/2) to only use C++17/2a/20 implementations | 46 | | **`v1`** | **Legacy** tag that still exists for projects that depends on, but is no longer maintained
Offers C++11/14/17 implementations in `gcl` namespace
as well as C++98/03 implementations in `gcl::deprecated` namespace | 47 | 48 | ## Features 49 | 50 | ### table-of-content 51 | 52 | | **component** name | description | 53 | |--------------------|--------------------------------------------------------------------------------------------| 54 | | `mp` | meta-programming elements to provide computation at compile-time | 55 | | `cx` | constexpr elements | 56 | | `ctc` | compile-time constants.
mainly provides algorithms to manipulate `std::array` and `std::tuple` at compile-time | 57 | | `io` | io manipulation, mainly for serialization | 58 | | `container` | containers | 59 | | `pattern` | mid-level design patterns, such as ECS | 60 | | [algorithms](./includes/gcl/algorithms/README.md) | some algorithms | 61 | | `functional` | function-related elements | 62 | | `concepts` | concepts definition. Note that most concepts are defined within components they are related to.
For instance, `gcl::mp::concepts` and `gcl::io::concepts` | 63 | 64 | 65 | ## Compilers support 66 | 67 | This library aims to compile using the following compilers : 68 | 69 | - `GCC` 70 | - `Clang` 71 | - `MsVC-CL` 72 | - `MS Clang-CL` 73 | 74 | *If at some point, a compiler does not support a specific feature, this information will be register as a limitation in-code comment 75 | Also, a warning will be generated at compile-time accordingly.* 76 | 77 | > - Example : `Clang 11.0.0` does not implement `"Lambdas in unevaluated contexts" (P0315R4)` 78 | 79 | ### Currently known limitations 80 | 81 | #### **`Clang`** / **`Clang-CL`** 82 | 83 | | File | Element | Description | 84 | | --------- | ------- | ----------- | 85 | | gcl/mp/pack_traits.hpp | `gcl::mp::type_traits::index_of` | uses an alternative implementation that use recursion, in opposition to other compilers | 86 | | gcl/mp/pack_traits.hpp | `gcl::mp::pack_traits<...>::index_of_v`
`gcl::mp::pack_traits<...>::first_index_of_v`
`gcl::mp::pack_traits<...>::last_index_of_v` | Known limitation of Clang 12.0.0
*Invalid operands to binary expression ('const auto' and 'int')* | 87 | 88 | #### **`Clang-CL`** 89 | 90 | | File | Element | Description | 91 | | --------- | ------- | ----------- | 92 | | gcl/cx/array.hpp | `gcl::cx::array::remove_duplicates_v` | a non-type template parameter cannot have type 'std::array' | 93 | 94 | #### **`GCC`** 95 | 96 | None. 97 | 98 | #### **`MsVC-CL`** 99 | 100 | None. 101 | 102 | ## STL implementations support 103 | 104 | ### **`libstdc++`** 105 | 106 | None. 107 | 108 | ### **`libc++`** 109 | 110 | Broken on release prior to 13 (requires concepts implementations) 111 | 112 | ### About the name 113 | 114 | > `GCL` stands for `Guss's Common Library` 115 | -------------------------------------------------------------------------------- /includes/gcl/algorithms/README.md: -------------------------------------------------------------------------------- 1 | # **GCL C++** : Algorithms 2 | 3 | This component provide - *constexpr* - algorithms used in the `gcl` library implementation. 4 | 5 | ## Details 6 | 7 | | | | 8 | | - | - | 9 | | namespace | `gcl::algorithms` | 10 | | path | `includes/gcl/algorithms` | 11 | 12 | Grouped in : `gcl/algorithms/algorithms.hpp` 13 | 14 | ### **`gcl::algorithms::maths`** 15 | 16 | Grouped in : `gcl/algorithms/algorithms/maths.hpp` 17 | 18 | | Element name | Description | example | 19 | | ------------ | ----------- | ------- | 20 | | maths::distance(T, T) | return the distance between two values | `distance(1, -1) == 2` | 21 | | maths::abs(T) | absolute value with boundary safety
| `abs(-1) == 1` | 22 | 23 | ### **`gcl::algorithms::ranges`** 24 | 25 | Grouped in : `gcl/algorithms/algorithms/ranges.hpp` 26 | 27 | | Element name | Description | example | 28 | | ------------ | ----------- | ------- | 29 | | ranges::is_in_range(Range, input) | return true if `intput` is in `range` | `is_in_range({1,2,3}, 2) == true` | 30 | | ranges::is_in_range(RangeIt, RangeIt, InputIt) | same as above, but using `begin`, `end` iterators | | 31 | -------------------------------------------------------------------------------- /includes/gcl/algorithms/algorithms.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace gcl::algorithms 12 | { 13 | // todo : 14 | // for_each that detected if the projection takes an iterator or value as parameter ? 15 | 16 | // Similar to `std::for_each` by defaut 17 | // but add the ability to project iterator (not values) 18 | // for values, simply use common projections 19 | template 20 | // requires 21 | // std::invocable and 22 | // std::invocable>> 23 | 24 | constexpr UnaryFunction for_each_it( 25 | iterator_type range_begin, iterator_type range_end, UnaryFunction f, Projection proj = {}) 26 | // noexcept(...) 27 | { 28 | static_assert(std::is_invocable_v); 29 | using projection_result_t = std::invoke_result_t; 30 | static_assert(std::is_invocable_v>); 31 | 32 | for (; range_begin != range_end; ++range_begin) 33 | { 34 | auto value = std::invoke(proj, range_begin); 35 | std::invoke(f, std::move(value)); 36 | } 37 | return f; 38 | } 39 | 40 | template 41 | [[nodiscard]] constexpr auto adjacent(container_type& container, iterator_type it) noexcept 42 | -> std::pair 43 | { 44 | if (it == std::cend(container)) 45 | return std::pair{it, it}; 46 | return std::pair{ 47 | it == std::begin(container) ? std::end(container) : std::prev(it), 48 | it == std::end(container) ? it : std::next(it)}; 49 | } 50 | template 51 | [[nodiscard]] constexpr auto adjacent_if(container_type & container, iterator_type it, Predicate predicate) 52 | noexcept(std::is_nothrow_invocable_v) 53 | -> decltype(adjacent(container, it)) { 54 | 55 | auto adjacent_result = adjacent(container, it); 56 | auto transformation = [&](auto & value){ 57 | if (value not_eq std::end(container) and not predicate(*value)) 58 | value = std::end(container); 59 | }; 60 | 61 | [&](std::index_sequence){ 62 | static_assert((std::is_invocable_v(adjacent_result))> && ...)); 63 | ((transformation(std::get(adjacent_result))), ...); 64 | }(std::make_index_sequence>{}); 65 | return adjacent_result; 66 | } 67 | } 68 | 69 | #ifdef GCL_ENABLE_COMPILE_TIME_TESTS 70 | #include 71 | namespace gcl::algorithms::tests 72 | { 73 | consteval void for_each_(){ 74 | 75 | constexpr auto values = std::array{'a', 'b', 'c', 'd'}; 76 | // same as std::for_each 77 | gcl::algorithms::for_each_it( 78 | std::cbegin(values), std::cend(values), [](const auto& value) { }); 79 | // same as std::for_each with projection on it 80 | gcl::algorithms::for_each_it( 81 | std::cbegin(values), 82 | std::cend(values), 83 | [](const auto& projected_element) { const auto& [index, value] = projected_element; }, 84 | [range_begin = std::cbegin(values)](const auto& it) { 85 | return std::pair{std::distance(range_begin, it), *it}; 86 | }); 87 | } 88 | consteval void adjacent_() { 89 | using namespace gcl::algorithms; 90 | { // adjacent(container, const_iterator) 91 | constexpr auto datas = std::array{1,2,3,4}; 92 | static_assert( 93 | adjacent(datas, std::cbegin(datas)) == 94 | std::pair{ std::cend(datas), std::next(std::cbegin(datas)) } 95 | ); 96 | static_assert( 97 | adjacent(datas, std::next(std::cbegin(datas))) == 98 | std::pair{ std::cbegin(datas), std::next(std::cbegin(datas), 2) } 99 | ); 100 | } 101 | { // adjacent(container, iterator) 102 | } 103 | { // adajacent_if(container, const_iterator, Predicate) 104 | 105 | } 106 | { // adajacent_if(container, iterator, Predicate) 107 | 108 | } 109 | } 110 | } 111 | #endif -------------------------------------------------------------------------------- /includes/gcl/algorithms/maths.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace gcl::algorithms::maths 8 | { 9 | template 10 | constexpr auto distance(T x, T y) 11 | { 12 | using value_type = std::conditional_t, std::intmax_t, std::uintmax_t>; 13 | return y >= x ? (value_type{y} - value_type{x}) : (value_type{x} - value_type{y}); 14 | } 15 | 16 | // std::abs is not constexpr yet 17 | template 18 | requires( 19 | (std::is_signed_v and std::numeric_limits::min() >= std::numeric_limits::min() and 20 | std::numeric_limits::max() <= std::numeric_limits::max()) or 21 | not std::is_signed_v) constexpr inline auto abs(T arg) noexcept 22 | { 23 | if constexpr (std::is_signed_v) 24 | { 25 | std::intmax_t value{arg}; 26 | return value < 0 ? -value : value; 27 | } 28 | else 29 | { 30 | return arg; 31 | } 32 | } 33 | } 34 | 35 | #if defined(GCL_ENABLE_COMPILE_TIME_TESTS) 36 | namespace gcl::algorithms::tests::maths 37 | { 38 | static_assert(gcl::algorithms::maths::distance(0, 0) == 0); 39 | static_assert(gcl::algorithms::maths::distance(-1, 1) == 2); 40 | static_assert(gcl::algorithms::maths::distance(1, -1) == 2); 41 | constexpr unsigned char uchar_zero{0}; 42 | static_assert( 43 | gcl::algorithms::maths::distance(uchar_zero, std::numeric_limits::max()) == 44 | std::numeric_limits::max()); 45 | 46 | static_assert(gcl::algorithms::maths::abs(-1) == 1); 47 | static_assert(gcl::algorithms::maths::abs(1) == 1); 48 | } 49 | #endif -------------------------------------------------------------------------------- /includes/gcl/algorithms/ranges.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace gcl::algorithms::ranges 12 | { 13 | template 14 | requires 15 | requires { typename std::common_type_t; } 16 | auto merge_uniques(const Ts & ... names) { 17 | using value_type = typename std::common_type_t; 18 | auto value = std::unordered_set{}; 19 | (value.insert(std::cbegin(names), std::cend(names)), ...); 20 | return std::vector { 21 | std::move_iterator{std::begin(value)}, 22 | std::move_iterator{std::end(value)} 23 | }; 24 | } 25 | 26 | template 27 | constexpr bool is_in_range(RangeIterator range_begin, RangeIterator range_end, InputIterator input) 28 | { 29 | using range_category = typename std::iterator_traits::iterator_category; 30 | static_assert(std::is_base_of_v); 31 | using input_category = typename std::iterator_traits::iterator_category; 32 | static_assert(std::is_base_of_v); 33 | 34 | if constexpr ( 35 | std::is_base_of_v and 36 | std::is_base_of_v) 37 | { 38 | if (range_begin > range_end) 39 | throw std::out_of_range{"gcl::algorithms::ranges::is_in_range"}; 40 | return input >= range_begin and input <= range_end; 41 | } 42 | else 43 | { // UB if range_begin > range_end 44 | static_assert(std::equality_comparable_with); 45 | while (range_begin != range_end) 46 | { 47 | if (input == range_begin) 48 | return true; 49 | ++range_begin; 50 | } 51 | return false; 52 | } 53 | } 54 | template 55 | constexpr bool is_in_range(const Range & range_value, InputIterator input) 56 | { 57 | return is_in_range(std::begin(range_value), std::end(range_value), input); 58 | } 59 | } 60 | 61 | #if defined(GCL_ENABLE_RUNTIME_TESTS) 62 | #include 63 | #include 64 | namespace gcl::algorithms::tests::ranges 65 | { 66 | void is_in_range() { 67 | auto map_value = std::map{}; 68 | std::generate_n(std::inserter(map_value, std::end(map_value)), 9, [i = 0]() mutable { 69 | return decltype(map_value)::value_type{i, i++}; 70 | }); 71 | if (not gcl::algorithms::ranges::is_in_range(std::cbegin(map_value), std::cend(map_value), map_value.find(5))) 72 | throw std::runtime_error{""}; 73 | if (gcl::algorithms::ranges::is_in_range(std::cbegin(map_value), std::cend(map_value), std::cend(map_value))) 74 | throw std::runtime_error{""}; 75 | } 76 | } 77 | namespace gcl::algorithms::tests::ranges 78 | { 79 | void test() { is_in_range(); 80 | } 81 | } 82 | #endif -------------------------------------------------------------------------------- /includes/gcl/compile_time_constant/README.md: -------------------------------------------------------------------------------- 1 | # **GCL C++** : Compile-time constant (ctc) 2 | 3 | This component provide - *ctc* - algorithms to manipulate compile-time elements like `std::array` and `std::tuple`. 4 | 5 | ## Details 6 | 7 | | | | 8 | | - | - | 9 | | namespace | `gcl::ctc` | 10 | | path | `includes/gcl/compile_time_constant` | 11 | 12 | Grouped in : `gcl/compile_time_constant/ctc.hpp` 13 | 14 | ### **`gcl::ctc::algorithms`** 15 | 16 | Grouped in `gcl/compile_time_constant/algorithms.hpp` 17 | 18 | #### **`gcl::ctc::algorithms::array`** 19 | 20 | Grouped in `gcl/compile_time_constant/algorithms/array.hpp` 21 | 22 | | Element name | Description | example | 23 | | ------------ | ----------- | ------- | 24 | | `deduplicate()` | return a `std::array` that contains deduplicated values,
where `T` is `std::common_type_t` and `N` the count of unique values | `deduplicate<1,2,3,1,2,3,2>() == std::array{1,2,3}` | 25 | | `deduplicate(const Ts... values)` | return a `std::pair`, where :
- first is an `std::array` with T is `std::common_type_t` and N is `sizeof...(Ts)`
- `second` is the position of the last unique element in `first` | see example below | 26 | | `shrink(std::array)` | return a new `std::array`, where `N_p` equal to `N`, and elements up to `N` as content | see example below | 27 | 28 | Example : 29 | 30 | ```cpp 31 | #include 32 | // or gcl/compile_time_constant/algorithms.hpp 33 | // or gcl/compile_time_constant/algorithms/array.hpp 34 | 35 | namespace ctc_array_algorithms = gcl::ctc::algorithms::array; 36 | constexpr auto values = []() consteval 37 | { 38 | constexpr auto deduplicate_result = 39 | ctc_array_algorithms::deduplicate(1, 2.0f, 1.0f, 2, 3, 4, 4e0, 0x4, char{1}, 5, 1, 2, 3); // common type : double 40 | constexpr auto deduplicated_values = 41 | std::get<0>(deduplicate_result); // structure-binding not allowed in constant-expression 42 | constexpr auto last_unique = std::get<1>(deduplicate_result); 43 | return ctc_array_algorithms::shrink(deduplicated_values); 44 | } 45 | (); 46 | constexpr auto expected_result = std::array{1, 2, 3, 4, 5}; 47 | static_assert(std::is_same_v); 48 | static_assert(values == expected_result); 49 | ``` 50 | 51 | ### **`gcl::ctc::algorithms::tuple`** 52 | 53 | | Element name | Description | example | 54 | | ------------ | ----------- | ------- | 55 | | tuple::tuple_to_std_array(TupleType value) | convert `value` into a | `is_in_range({1,2,3}, 2) == true` | 56 | 57 | -------------------------------------------------------------------------------- /includes/gcl/compile_time_constant/algorithms.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // experimental compile-time-constant operations 4 | 5 | #include 6 | #include 7 | -------------------------------------------------------------------------------- /includes/gcl/compile_time_constant/algorithms/array.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace gcl::ctc::algorithms::array 12 | { 13 | template 14 | consteval auto deduplicate_size(std::array values_as_array) 15 | { 16 | std::ranges::sort(values_as_array); 17 | // auto size = std::ranges::size(values_as_array) - std::ranges::distance(std::ranges::unique(values_as_array)); 18 | // // clang does not support it yet 19 | auto size = std::distance( 20 | std::begin(values_as_array), std::unique(std::begin(values_as_array), std::end(values_as_array))); 21 | return size; 22 | } 23 | template 24 | requires gcl::concepts::have_common_type consteval auto deduplicate_size(Ts... values) 25 | { 26 | return deduplicate_size(std::array{values...}); 27 | } 28 | template 29 | requires concepts::have_common_type consteval auto deduplicate() 30 | { 31 | auto values_as_array = std::array{values...}; 32 | std::sort(std::begin(values_as_array), std::end(values_as_array)); 33 | for (auto it = std::ranges::adjacent_find(values_as_array); it != std::end(values_as_array); 34 | it = std::ranges::adjacent_find(values_as_array)) 35 | { 36 | auto end = it; 37 | while (*end == *it) 38 | end++; 39 | std::copy(std::next(end), std::end(values_as_array), std::next(it)); 40 | } 41 | 42 | constexpr auto return_size = deduplicate_size(values...); 43 | using element_type = std::common_type_t; 44 | using return_type = std::array; 45 | return_type return_value; 46 | std::copy(std::cbegin(values_as_array), std::cbegin(values_as_array) + return_size, std::begin(return_value)); 47 | return return_value; 48 | } 49 | template 50 | requires concepts::have_common_type consteval auto deduplicate(const Ts... values_arg) 51 | { 52 | using element_type = std::common_type_t; 53 | auto values = std::array{static_cast(values_arg)...}; 54 | 55 | // deduplication 56 | std::sort(std::begin(values), std::end(values)); 57 | for (auto it = std::ranges::adjacent_find(std::begin(values), std::end(values)); it != std::ranges::end(values); 58 | it = std::ranges::adjacent_find(std::next(it), std::end(values))) 59 | { 60 | auto end = it; 61 | while (end != std::end(values) && *end == *it) 62 | ++end; 63 | std::copy(end, std::end(values), std::next(it)); 64 | } 65 | // std::unique() 66 | auto unique_end = [&values]() constexpr //consteval (Clang does not allow consteval in constant expression) 67 | { 68 | std::size_t i{1}; 69 | while (i < std::size(values) and values.at(i - 1) < values.at(i)) 70 | i++; 71 | return i; 72 | } 73 | (); 74 | 75 | return std::pair{values, unique_end}; 76 | } 77 | template 78 | consteval auto shrink(std::array value) 79 | { 80 | using return_type = std::array; 81 | return_type return_value; 82 | std::copy(std::cbegin(value), std::cbegin(value) + end_index, std::begin(return_value)); 83 | return return_value; 84 | } 85 | } 86 | 87 | #if defined(GCL_ENABLE_COMPILE_TIME_TESTS) 88 | namespace gcl::ctc::tests::algorithms::array::deduplicate 89 | { 90 | // MSVC/CL does not consider deduplicate calls as constexpr ... 91 | // static_assert(gcl::ctc::deduplicate<'b', 'a', 'c', 'a', 'c', 'b', 'b'>() == std::array{'a', 'b', 'c'}); 92 | 93 | [[maybe_unused]] static void by_values() 94 | { 95 | namespace ctc_array_algorithms = gcl::ctc::algorithms::array; 96 | constexpr auto values = []() consteval 97 | { 98 | constexpr auto deduplicate_result = ctc_array_algorithms::deduplicate(1, 2, 1, 2, 3, 4, 5, 1, 2, 3); 99 | constexpr auto deduplicated_values = 100 | std::get<0>(deduplicate_result); // structure-binding not allowed in constant-expression 101 | constexpr auto last_unique = std::get<1>(deduplicate_result); 102 | return ctc_array_algorithms::shrink(deduplicated_values); 103 | } 104 | (); 105 | constexpr auto expected_result = std::array{1, 2, 3, 4, 5}; 106 | static_assert(std::is_same_v); 107 | static_assert(values == expected_result); 108 | } 109 | [[maybe_unused]] static void by_values_heterogenous() 110 | { 111 | namespace ctc_array_algorithms = gcl::ctc::algorithms::array; 112 | constexpr auto values = []() consteval 113 | { 114 | constexpr auto deduplicate_result = 115 | ctc_array_algorithms::deduplicate(1, 2.0f, 1.0f, 2, 3, 4, 4e0, 0x4, char{1}, 5, 1, 2, 3); 116 | constexpr auto deduplicated_values = 117 | std::get<0>(deduplicate_result); // structure-binding not allowed in constant-expression 118 | constexpr auto last_unique = std::get<1>(deduplicate_result); 119 | return ctc_array_algorithms::shrink(deduplicated_values); 120 | } 121 | (); 122 | constexpr auto expected_result = std::array{1, 2, 3, 4, 5}; 123 | static_assert(std::is_same_v); 124 | static_assert(values == expected_result); 125 | } 126 | } 127 | #endif -------------------------------------------------------------------------------- /includes/gcl/compile_time_constant/ctc.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include -------------------------------------------------------------------------------- /includes/gcl/concepts.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace gcl::concepts 7 | { 8 | template 9 | concept pointer = (std::is_pointer::value); 10 | 11 | template 12 | concept function = 13 | std::is_function_v or std::is_function_v> or std::is_member_function_pointer_v; 14 | 15 | template 16 | concept have_common_type = requires() 17 | { 18 | std::common_type_t{}; 19 | }; 20 | } 21 | 22 | #if defined(GCL_ENABLE_COMPILE_TIME_TESTS) 23 | namespace gcl::concepts::tests 24 | { 25 | static_assert(gcl::concepts::pointer); 26 | static_assert(not gcl::concepts::pointer); 27 | 28 | void func() {} 29 | struct A { 30 | void func(){}; 31 | void const_func() const {}; 32 | static void static_func(){}; 33 | }; 34 | constexpr void function() 35 | { 36 | static_assert(gcl::concepts::function); 37 | static_assert(gcl::concepts::function); 38 | static_assert(gcl::concepts::function); 39 | static_assert(gcl::concepts::function); 40 | } 41 | } 42 | #endif -------------------------------------------------------------------------------- /includes/gcl/container/concepts.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace gcl::container::concepts 10 | { 11 | template 12 | concept resizable = requires 13 | { 14 | {std::declval().resize(std::declval())}; 15 | }; 16 | 17 | template 18 | concept LegacyForwardIterator = 19 | std::constructible_from 20 | and std::is_lvalue_reference_v> 21 | and std::same_as< 22 | std::remove_cvref_t>, 23 | typename std::indirectly_readable_traits::value_type 24 | > 25 | and requires(T value) { 26 | { value++ } -> std::convertible_to; 27 | { *value++ } -> std::same_as>; 28 | }; 29 | 30 | template 31 | concept Container = 32 | std::regular 33 | and std::swappable 34 | and requires (T value) { // very naive container requirements 35 | typename T::value_type; 36 | typename T::reference; 37 | typename T::const_reference; 38 | typename T::iterator; 39 | typename T::const_iterator; 40 | typename T::difference_type; 41 | typename T::size_type; 42 | 43 | { std::begin(value) } -> std::same_as; 44 | { std::end(value) } -> std::same_as; 45 | { std::cbegin(value) } -> std::same_as; 46 | { std::cend(value) } -> std::same_as; 47 | 48 | { std::size(value) } -> std::same_as; 49 | { std::empty(value) } -> std::convertible_to; 50 | } 51 | and LegacyForwardIterator 52 | and LegacyForwardIterator 53 | and std::convertible_to 54 | and std::same_as< 55 | typename T::difference_type, 56 | typename std::iterator_traits::difference_type 57 | > 58 | and std::same_as< 59 | typename T::difference_type, 60 | typename std::iterator_traits::difference_type 61 | > 62 | ; 63 | } 64 | -------------------------------------------------------------------------------- /includes/gcl/container/tuple_view.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace gcl::container::details 7 | { 8 | template 9 | concept TupleType = requires { 10 | std::tuple_size_v>; 11 | }; 12 | template 13 | concept StorageType = TupleType and gcl::mp::type_traits::has_unique_ttps_v; 14 | } 15 | namespace gcl::container 16 | { 17 | template 18 | requires gcl::mp::type_traits::are_unique_ttps_v using tuple_view_type = 19 | std::tuple...>; 20 | template 21 | requires gcl::mp::type_traits::are_unique_ttps_v using tuple_const_view_type = 22 | std::tuple>...>; 23 | 24 | template 25 | constexpr auto make_tuple_view(details::StorageType auto& storage) 26 | requires requires { 27 | ((std::get(storage)), ...); 28 | } 29 | { 30 | using result_type = tuple_view_type; 31 | return result_type{std::get(storage)...}; 32 | } 33 | template 34 | constexpr auto make_tuple_view(const details::StorageType auto& storage) 35 | requires requires { 36 | ((std::get(storage)), ...); 37 | } 38 | { 39 | using result_type = tuple_const_view_type; 40 | return result_type{std::get(storage)...}; 41 | } 42 | } 43 | 44 | #if defined(GCL_ENABLE_COMPILE_TIME_TESTS) 45 | namespace gcl::container::test 46 | { 47 | template 48 | struct feature { 49 | 50 | using signature_type = std::tuple; 51 | 52 | constexpr void process(std::tuple&& args) 53 | { 54 | [&args](std::index_sequence) { ((++std::get(args)), ...); } 55 | (std::make_index_sequence()); 56 | } 57 | }; 58 | consteval void tuple_view_ref() 59 | { 60 | auto features_available = std::tuple{42, 'A', double{13}}; 61 | auto process_dispatcher = [](auto& value, auto& features_container) constexpr { 62 | auto features_requested = [&features_container]