Compare commits
	
		
			197 Commits
		
	
	
		
			f077a29cf0
			...
			ff5dbaf
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ff5dbaffc0 | |||
| b56d581e4b | |||
| aa661aaaa7 | |||
| cc3f430bab | |||
| 139db5b03b | |||
| 7d0e5c80bd | |||
| f716ad9dd1 | |||
| 671772a20e | |||
| b0173f6d68 | |||
| 3da5872df8 | |||
| 3deb6e8469 | |||
| 0c674e0137 | |||
| 7948d820c3 | |||
| 5aac3422aa | |||
| e8eaa7a232 | |||
| 04b3382029 | |||
| 7fe6df5889 | |||
| 2647c85323 | |||
| 93140231c6 | |||
| e76e56e025 | |||
| b1062e701e | |||
| e72aebc043 | |||
| 865dfa994f | |||
| 25be42e308 | |||
| c6a0df409d | |||
| a15a9af2b3 | |||
| ca6909b64a | |||
| 5af8cfa879 | |||
| f701b7d2f8 | |||
| 852f2a6343 | |||
| 7359e30c3e | |||
| 5effe64474 | |||
| 61accfe184 | |||
| 2f44996edc | |||
| b1fe064484 | |||
| 18ca88a0d4 | |||
| 565aa4b7eb | |||
| b117da5ccf | |||
| 8eb4892b49 | |||
| 82fe4c3dd7 | |||
| 78b0e9a77f | |||
| 7fa6aa7ac2 | |||
| 20b4cdc5f1 | |||
| 7c576dd4d0 | |||
| f6cda522ca | |||
| 3d2f5b644b | |||
| 9ace11a0e2 | |||
| 6104d3b6d1 | |||
| f637c7c942 | |||
| afb886ea7c | |||
| 74129cabef | |||
| be8ceb861c | |||
| da0f59a3f5 | |||
| 000254320e | |||
| 2fac7206d2 | |||
| e8234f2a4a | |||
| a0ba0b39d8 | |||
| 845967cf12 | |||
| 92b58cbfa9 | |||
| 5a0651eaf0 | |||
| 14fcaf1d7e | |||
| 5a0252d8d0 | |||
| 9c0ffd38ce | |||
| b2ae9530a4 | |||
| ae1fb0fde3 | |||
| 35ebbbef93 | |||
| 83e200df43 | |||
| 260d3b7818 | |||
| 4ebffd8c63 | |||
| 8923e09b36 | |||
| ec4195f18a | |||
| 062ad7ae80 | |||
| aad07611c7 | |||
| 0dcb66f143 | |||
| 331c25b0e6 | |||
| e50844be06 | |||
| 4dd7c98c1a | |||
| 63bad2e99a | |||
| 9ddeea3d06 | |||
| b95f0498b6 | |||
| 7495a50723 | |||
| 1cdde5170b | |||
| 4248d1d9ab | |||
| 4f02c2b55b | |||
| 05d1648209 | |||
| fd9d14d00c | |||
| 4e4f62dd20 | |||
| cdc4284cb5 | |||
| bedbacddde | |||
| 32a8dba185 | |||
| d6e5051b15 | |||
| 780a67a40d | |||
| 0c7fff3029 | |||
| e7db39d20a | |||
| 869edb8d84 | |||
| dce42b866a | |||
| da19b0ac31 | |||
| bc090bdaa8 | |||
| 2a5937652e | |||
| b9d4f594ce | |||
| c79068c561 | |||
| e7095a1849 | |||
| 3f78e17888 | |||
| 897253e1d6 | |||
| cd28b26761 | |||
| a3126d581b | |||
| 1da4a12104 | |||
| 8725bafbdb | |||
| c24dc45e93 | |||
| 62b00a4bd6 | |||
| f1f67fe1ba | |||
| 621327bf55 | |||
| 9dabdd32fa | |||
| b479db4989 | |||
| 8633c5eafd | |||
| 440489f228 | |||
| bb824a9fb7 | |||
| c98dd8a584 | |||
| e12d7b1458 | |||
| 58edc97787 | |||
| ca6853e2c0 | |||
| fc90106d83 | |||
| 89bc11eca7 | |||
| 5c4c397f6c | |||
| da774e10e8 | |||
| 2f8eca71a4 | |||
| 90ce4bda4e | |||
| 4afe39dacc | |||
| dd316d2589 | |||
| 644725478f | |||
| 12e8b5d6c4 | |||
| f5c7261805 | |||
| 73ee0f905b | |||
| 0b46b891c2 | |||
| d131b5a02f | |||
| 9d9a486537 | |||
| 610ed10011 | |||
| 4edab11616 | |||
| 4d48f9d237 | |||
| 6df0417667 | |||
| bd9bbf67d4 | |||
| 8cab1307ab | |||
| 5bfc429450 | |||
| 7a7b55bebf | |||
| b4eda033c6 | |||
| c9672bf352 | |||
| 5547ff6d2b | |||
| ea8cc85c61 | |||
| 5ecec26731 | |||
| 01fddd19cd | |||
| e362af8271 | |||
| 2dba4f8fbb | |||
| bdfe44399a | |||
| 67653bbe50 | |||
| a144459e8d | |||
| d725ed8cd0 | |||
| 3cd551098b | |||
| 87d7eb69af | |||
| 95b77cb696 | |||
| 2e28ad7bb9 | |||
| 75f78f8c7f | |||
| ef59386e5c | |||
| c0b57c30bd | |||
| 42b3866753 | |||
| aff239377d | |||
| 3aaa1b0350 | |||
| 823a4ae189 | |||
| 40cd04f9dd | |||
| 6a979d31a0 | |||
| 56f7db9ae6 | |||
| d5e2dd2e1f | |||
| 93e5bb867b | |||
| 4cd295065b | |||
| 5a9aacc603 | |||
| 082c4febdf | |||
| a848a01527 | |||
| 3a1c15f313 | |||
| e92c7cbfa0 | |||
| 4d09e1fd4a | |||
| 07765b4ad7 | |||
| 88f6091665 | |||
| f66b8d3ea2 | |||
| a0122d38f2 | |||
| e4d2987c54 | |||
| dec0d4ec41 | |||
| b8e444eaa8 | |||
| b38ea75e56 | |||
| 8613511928 | |||
| 7650d0ff23 | |||
| 4ec6a26d91 | |||
| efa781e9ba | |||
| 41d0fc02c3 | |||
| 227425b90e | |||
| 5568b70d31 | |||
| 5c7231b7a3 | |||
| 310a099f14 | |||
| df9fc529e2 | 
							
								
								
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					github: Green-Sky
 | 
				
			||||||
							
								
								
									
										228
									
								
								.github/workflows/cd.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								.github/workflows/cd.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,228 @@
 | 
				
			|||||||
 | 
					name: ContinuousDelivery
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					on:
 | 
				
			||||||
 | 
					  push:
 | 
				
			||||||
 | 
					    branches: [ master ]
 | 
				
			||||||
 | 
					  pull_request:
 | 
				
			||||||
 | 
					    branches: [ master ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					env:
 | 
				
			||||||
 | 
					  BUILD_TYPE: Release
 | 
				
			||||||
 | 
					  BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					  linux-ubuntu:
 | 
				
			||||||
 | 
					    timeout-minutes: 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runs-on: ubuntu-20.04
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        submodules: recursive
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Install Dependencies
 | 
				
			||||||
 | 
					      run: sudo apt update && sudo apt -y install libsodium-dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Configure CMake
 | 
				
			||||||
 | 
					      run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Build
 | 
				
			||||||
 | 
					      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: temp test
 | 
				
			||||||
 | 
					      run: ${{github.workspace}}/build/bin/mono_time_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Determine tag name
 | 
				
			||||||
 | 
					      id: tag
 | 
				
			||||||
 | 
					      shell: bash
 | 
				
			||||||
 | 
					      # taken from llama.cpp
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        SHORT_HASH="$(git rev-parse --short=7 HEAD)"
 | 
				
			||||||
 | 
					        if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then
 | 
				
			||||||
 | 
					          echo "name=${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					          SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-')
 | 
				
			||||||
 | 
					          echo "name=${SAFE_NAME}-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Compress artifacts
 | 
				
			||||||
 | 
					      shell: bash
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        tar -czvf ${{ github.event.repository.name }}-${{ steps.tag.outputs.name }}-${{ runner.os }}-ubuntu20.04-x86_64.tar.gz -C ${{github.workspace}}/build/bin/ .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - uses: actions/upload-artifact@v4
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        # TODO: simpler name?
 | 
				
			||||||
 | 
					        name: ${{ github.event.repository.name }}-${{ steps.tag.outputs.name }}-${{ runner.os }}-ubuntu20.04-x86_64
 | 
				
			||||||
 | 
					        # TODO: do propper packing
 | 
				
			||||||
 | 
					        path: |
 | 
				
			||||||
 | 
					          ${{github.workspace}}/${{ github.event.repository.name }}-${{ steps.tag.outputs.name }}-${{ runner.os }}-ubuntu20.04-x86_64.tar.gz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  windows:
 | 
				
			||||||
 | 
					    timeout-minutes: 15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runs-on: windows-2019
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        submodules: recursive
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Install Dependencies
 | 
				
			||||||
 | 
					      run: vcpkg install libsodium:x64-windows-static pthreads:x64-windows-static
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # setup vs env
 | 
				
			||||||
 | 
					    - uses: ilammy/msvc-dev-cmd@v1
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        arch: amd64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Configure CMake
 | 
				
			||||||
 | 
					      run: cmake -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Build
 | 
				
			||||||
 | 
					      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: temp test
 | 
				
			||||||
 | 
					      run: ${{github.workspace}}/build/bin/mono_time_test.exe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Determine tag name
 | 
				
			||||||
 | 
					      id: tag
 | 
				
			||||||
 | 
					      shell: bash
 | 
				
			||||||
 | 
					      # taken from llama.cpp
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        SHORT_HASH="$(git rev-parse --short=7 HEAD)"
 | 
				
			||||||
 | 
					        if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then
 | 
				
			||||||
 | 
					          echo "name=${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					          SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-')
 | 
				
			||||||
 | 
					          echo "name=${SAFE_NAME}-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Compress artifacts
 | 
				
			||||||
 | 
					      shell: powershell
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        Compress-Archive -Path ${{github.workspace}}/build/bin/* -Destination ${{ github.event.repository.name }}-${{ steps.tag.outputs.name }}-${{ runner.os }}-msvc-x86_64.zip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - uses: actions/upload-artifact@v4
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        # TODO: simpler name?
 | 
				
			||||||
 | 
					        name: ${{ github.event.repository.name }}-${{ steps.tag.outputs.name }}-${{ runner.os }}-msvc-x86_64
 | 
				
			||||||
 | 
					        # TODO: do propper packing
 | 
				
			||||||
 | 
					        path: |
 | 
				
			||||||
 | 
					          ${{github.workspace}}/${{ github.event.repository.name }}-${{ steps.tag.outputs.name }}-${{ runner.os }}-msvc-x86_64.zip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  windows-asan:
 | 
				
			||||||
 | 
					    timeout-minutes: 15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runs-on: windows-2019
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        submodules: recursive
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Install Dependencies
 | 
				
			||||||
 | 
					      run: vcpkg install libsodium:x64-windows-static pthreads:x64-windows-static
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # setup vs env
 | 
				
			||||||
 | 
					    - uses: ilammy/msvc-dev-cmd@v1
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        arch: amd64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Configure CMake
 | 
				
			||||||
 | 
					      run: cmake -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -DTOMATO_ASAN=ON -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Build
 | 
				
			||||||
 | 
					      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: temp test
 | 
				
			||||||
 | 
					      run: ${{github.workspace}}/build/bin/mono_time_test.exe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Determine tag name
 | 
				
			||||||
 | 
					      id: tag
 | 
				
			||||||
 | 
					      shell: bash
 | 
				
			||||||
 | 
					      # taken from llama.cpp
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        SHORT_HASH="$(git rev-parse --short=7 HEAD)"
 | 
				
			||||||
 | 
					        if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then
 | 
				
			||||||
 | 
					          echo "name=${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					          SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-')
 | 
				
			||||||
 | 
					          echo "name=${SAFE_NAME}-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Compress artifacts
 | 
				
			||||||
 | 
					      shell: powershell
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        Compress-Archive -Path ${{github.workspace}}/build/bin/* -Destination ${{ github.event.repository.name }}-${{ steps.tag.outputs.name }}-${{ runner.os }}-msvc-asan-x86_64.zip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - uses: actions/upload-artifact@v4
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        # TODO: simpler name?
 | 
				
			||||||
 | 
					        name: ${{ github.event.repository.name }}-${{ steps.tag.outputs.name }}-${{ runner.os }}-msvc-asan-x86_64
 | 
				
			||||||
 | 
					        # TODO: do propper packing
 | 
				
			||||||
 | 
					        path: |
 | 
				
			||||||
 | 
					          ${{github.workspace}}/${{ github.event.repository.name }}-${{ steps.tag.outputs.name }}-${{ runner.os }}-msvc-asan-x86_64.zip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  release:
 | 
				
			||||||
 | 
					    if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    needs:
 | 
				
			||||||
 | 
					      - linux-ubuntu
 | 
				
			||||||
 | 
					      - windows
 | 
				
			||||||
 | 
					      - windows-asan
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    permissions:
 | 
				
			||||||
 | 
					      contents: write
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        submodules: recursive
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Determine tag name
 | 
				
			||||||
 | 
					      id: tag
 | 
				
			||||||
 | 
					      shell: bash
 | 
				
			||||||
 | 
					      # taken from llama.cpp
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        SHORT_HASH="$(git rev-parse --short=7 HEAD)"
 | 
				
			||||||
 | 
					        if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then
 | 
				
			||||||
 | 
					          echo "name=${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					          SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-')
 | 
				
			||||||
 | 
					          echo "name=${SAFE_NAME}-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Download artifacts
 | 
				
			||||||
 | 
					      id: download-artifact
 | 
				
			||||||
 | 
					      uses: actions/download-artifact@v4
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        path: ./artifacts/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Create release
 | 
				
			||||||
 | 
					      env:
 | 
				
			||||||
 | 
					        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
				
			||||||
 | 
					        tag: ${{ steps.tag.outputs.name }}
 | 
				
			||||||
 | 
					      shell: bash
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        gh release create "$tag" \
 | 
				
			||||||
 | 
					            --repo="$GITHUB_REPOSITORY" \
 | 
				
			||||||
 | 
					            --title="nightly ${tag#v}" \
 | 
				
			||||||
 | 
					            --notes="nightly build" \
 | 
				
			||||||
 | 
					            --prerelease
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Upload artifacts
 | 
				
			||||||
 | 
					      env:
 | 
				
			||||||
 | 
					        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
				
			||||||
 | 
					        tag: ${{ steps.tag.outputs.name }}
 | 
				
			||||||
 | 
					      shell: bash
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        ls -laR ./artifacts
 | 
				
			||||||
 | 
					        gh release upload "$tag" ./artifacts/*/* \
 | 
				
			||||||
 | 
					            --repo="$GITHUB_REPOSITORY"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										80
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					name: ContinuousIntegration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					on:
 | 
				
			||||||
 | 
					  push:
 | 
				
			||||||
 | 
					    branches: [ master ]
 | 
				
			||||||
 | 
					  pull_request:
 | 
				
			||||||
 | 
					    branches: [ master ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					env:
 | 
				
			||||||
 | 
					  BUILD_TYPE: Debug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					  linux:
 | 
				
			||||||
 | 
					    timeout-minutes: 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        submodules: recursive
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Install Dependencies
 | 
				
			||||||
 | 
					      run: sudo apt update && sudo apt -y install libsodium-dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Configure CMake
 | 
				
			||||||
 | 
					      run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Build
 | 
				
			||||||
 | 
					      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: temp test
 | 
				
			||||||
 | 
					      run: ${{github.workspace}}/build/bin/mono_time_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  macos:
 | 
				
			||||||
 | 
					    timeout-minutes: 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runs-on: macos-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        submodules: recursive
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Install Dependencies
 | 
				
			||||||
 | 
					      run: brew install libsodium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Configure CMake
 | 
				
			||||||
 | 
					      run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Build
 | 
				
			||||||
 | 
					      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  windows:
 | 
				
			||||||
 | 
					    timeout-minutes: 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runs-on: windows-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        submodules: recursive
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Install Dependencies
 | 
				
			||||||
 | 
					      run: vcpkg install libsodium:x64-windows-static pthreads:x64-windows-static
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # setup vs env
 | 
				
			||||||
 | 
					    - uses: ilammy/msvc-dev-cmd@v1
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        arch: amd64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Configure CMake
 | 
				
			||||||
 | 
					      run: cmake -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Build
 | 
				
			||||||
 | 
					      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: temp test
 | 
				
			||||||
 | 
					      run: ${{github.workspace}}/build/bin/mono_time_test.exe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										26
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					.vs/
 | 
				
			||||||
 | 
					*.o
 | 
				
			||||||
 | 
					*.swp
 | 
				
			||||||
 | 
					~*
 | 
				
			||||||
 | 
					*~
 | 
				
			||||||
 | 
					.idea/
 | 
				
			||||||
 | 
					cmake-build-debug/
 | 
				
			||||||
 | 
					cmake-build-debugandtest/
 | 
				
			||||||
 | 
					cmake-build-release/
 | 
				
			||||||
 | 
					*.stackdump
 | 
				
			||||||
 | 
					*.coredump
 | 
				
			||||||
 | 
					compile_commands.json
 | 
				
			||||||
 | 
					/build*
 | 
				
			||||||
 | 
					/result*
 | 
				
			||||||
 | 
					.clangd
 | 
				
			||||||
 | 
					.cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					.AppleDouble
 | 
				
			||||||
 | 
					.LSOverride
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CMakeLists.txt.user*
 | 
				
			||||||
 | 
					CMakeCache.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*.tox
 | 
				
			||||||
 | 
					imgui.ini
 | 
				
			||||||
							
								
								
									
										4
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					[submodule "external/toxcore/c-toxcore/third_party/cmp"]
 | 
				
			||||||
 | 
						path = external/toxcore/c-toxcore/third_party/cmp
 | 
				
			||||||
 | 
						url = https://github.com/camgunz/cmp.git
 | 
				
			||||||
 | 
						shallow = true
 | 
				
			||||||
[submodule "external/solanaceae_toxcore"]
 | 
					[submodule "external/solanaceae_toxcore"]
 | 
				
			||||||
	path = external/solanaceae_toxcore
 | 
						path = external/solanaceae_toxcore
 | 
				
			||||||
	url = https://github.com/Green-Sky/solanaceae_toxcore.git
 | 
						url = https://github.com/Green-Sky/solanaceae_toxcore.git
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										67
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
				
			|||||||
 | 
					cmake_minimum_required(VERSION 3.14...3.24 FATAL_ERROR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# cmake setup begin
 | 
				
			||||||
 | 
					project(tomato)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(CMAKE_POSITION_INDEPENDENT_CODE ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# defaulting to debug mode, if not specified
 | 
				
			||||||
 | 
					if (NOT CMAKE_BUILD_TYPE)
 | 
				
			||||||
 | 
						set(CMAKE_BUILD_TYPE "Debug")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# setup my vim ycm :D
 | 
				
			||||||
 | 
					set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# more paths
 | 
				
			||||||
 | 
					set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
 | 
				
			||||||
 | 
					set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
 | 
				
			||||||
 | 
					set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option(TOMATO_ASAN "Build tomato with asan (gcc/clang/msvc)" OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (TOMATO_ASAN)
 | 
				
			||||||
 | 
						if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
 | 
				
			||||||
 | 
							if (NOT WIN32) # exclude mingw
 | 
				
			||||||
 | 
								link_libraries(-fsanitize=address)
 | 
				
			||||||
 | 
								#link_libraries(-fsanitize=address,undefined)
 | 
				
			||||||
 | 
								#link_libraries(-fsanitize=undefined)
 | 
				
			||||||
 | 
								message("II enabled ASAN")
 | 
				
			||||||
 | 
							else()
 | 
				
			||||||
 | 
								message("!! can not enable ASAN on this platform (gcc/clang + win)")
 | 
				
			||||||
 | 
							endif()
 | 
				
			||||||
 | 
						elseif (MSVC)
 | 
				
			||||||
 | 
							add_compile_options("/fsanitize=address")
 | 
				
			||||||
 | 
							message("II enabled ASAN")
 | 
				
			||||||
 | 
						else()
 | 
				
			||||||
 | 
							message("!! can not enable ASAN on this platform")
 | 
				
			||||||
 | 
						endif()
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# external libs
 | 
				
			||||||
 | 
					add_subdirectory(./external) # before increasing warn levels, sad :(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(CMAKE_CXX_EXTENSIONS OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# bump up warning levels appropriately for clang, gcc & msvc
 | 
				
			||||||
 | 
					if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
 | 
				
			||||||
 | 
						add_compile_options(
 | 
				
			||||||
 | 
							-Wall -Wextra # Reasonable and standard
 | 
				
			||||||
 | 
							-Wpedantic # Warn if non-standard C++ is used
 | 
				
			||||||
 | 
							-Wunused # Warn on anything being unused
 | 
				
			||||||
 | 
							#-Wconversion # Warn on type conversions that may lose data
 | 
				
			||||||
 | 
							#-Wsign-conversion # Warn on sign conversions
 | 
				
			||||||
 | 
							-Wshadow # Warn if a variable declaration shadows one from a parent context
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
 | 
				
			||||||
 | 
						if (MSVC)
 | 
				
			||||||
 | 
							string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
 | 
				
			||||||
 | 
						else()
 | 
				
			||||||
 | 
							set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
 | 
				
			||||||
 | 
						endif()
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# cmake setup end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_subdirectory(./src)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								external/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								external/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							@@ -12,3 +12,9 @@ add_subdirectory(./toxcore)
 | 
				
			|||||||
add_subdirectory(./solanaceae_toxcore)
 | 
					add_subdirectory(./solanaceae_toxcore)
 | 
				
			||||||
add_subdirectory(./solanaceae_tox)
 | 
					add_subdirectory(./solanaceae_tox)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_subdirectory(./sdl)
 | 
				
			||||||
 | 
					add_subdirectory(./imgui)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_subdirectory(./stb)
 | 
				
			||||||
 | 
					add_subdirectory(./libwebp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										41
									
								
								external/entt/entt/.clang-format
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								external/entt/entt/.clang-format
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					BasedOnStyle: llvm
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					AccessModifierOffset: -4
 | 
				
			||||||
 | 
					AlignEscapedNewlines: DontAlign
 | 
				
			||||||
 | 
					AllowShortBlocksOnASingleLine: Empty
 | 
				
			||||||
 | 
					AllowShortEnumsOnASingleLine: true
 | 
				
			||||||
 | 
					AllowShortFunctionsOnASingleLine: Empty
 | 
				
			||||||
 | 
					AllowShortIfStatementsOnASingleLine: WithoutElse
 | 
				
			||||||
 | 
					AllowShortLoopsOnASingleLine: true
 | 
				
			||||||
 | 
					AlwaysBreakTemplateDeclarations: Yes
 | 
				
			||||||
 | 
					BreakBeforeBinaryOperators: NonAssignment
 | 
				
			||||||
 | 
					BreakBeforeTernaryOperators: true
 | 
				
			||||||
 | 
					ColumnLimit: 0
 | 
				
			||||||
 | 
					DerivePointerAlignment: false
 | 
				
			||||||
 | 
					IncludeCategories:
 | 
				
			||||||
 | 
					  - Regex: '<[[:alnum:]_]+>'
 | 
				
			||||||
 | 
					    Priority: 1
 | 
				
			||||||
 | 
					  - Regex: '<(gtest|gmock)/'
 | 
				
			||||||
 | 
					    Priority: 2
 | 
				
			||||||
 | 
					  - Regex: '<[[:alnum:]_./]+>'
 | 
				
			||||||
 | 
					    Priority: 3
 | 
				
			||||||
 | 
					  - Regex: '<entt/'
 | 
				
			||||||
 | 
					    Priority: 4
 | 
				
			||||||
 | 
					  - Regex: '.*'
 | 
				
			||||||
 | 
					    Priority: 5
 | 
				
			||||||
 | 
					IndentPPDirectives: AfterHash
 | 
				
			||||||
 | 
					IndentWidth: 4
 | 
				
			||||||
 | 
					KeepEmptyLinesAtTheStartOfBlocks: false
 | 
				
			||||||
 | 
					Language: Cpp
 | 
				
			||||||
 | 
					PointerAlignment: Right
 | 
				
			||||||
 | 
					SpaceAfterCStyleCast: false
 | 
				
			||||||
 | 
					SpaceAfterTemplateKeyword: false
 | 
				
			||||||
 | 
					SpaceAroundPointerQualifiers: After
 | 
				
			||||||
 | 
					SpaceBeforeCaseColon: false
 | 
				
			||||||
 | 
					SpaceBeforeCtorInitializerColon: false
 | 
				
			||||||
 | 
					SpaceBeforeInheritanceColon: false
 | 
				
			||||||
 | 
					SpaceBeforeParens: Never
 | 
				
			||||||
 | 
					SpaceBeforeRangeBasedForLoopColon: false
 | 
				
			||||||
 | 
					Standard: Latest
 | 
				
			||||||
 | 
					TabWidth: 4
 | 
				
			||||||
 | 
					UseTab: Never
 | 
				
			||||||
							
								
								
									
										4
									
								
								external/entt/entt/.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								external/entt/entt/.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					# These are supported funding model platforms
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					github: skypjack
 | 
				
			||||||
 | 
					custom: https://www.paypal.me/skypjack
 | 
				
			||||||
							
								
								
									
										61
									
								
								external/entt/entt/.github/workflows/analyzer.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								external/entt/entt/.github/workflows/analyzer.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					name: analyzer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					on:
 | 
				
			||||||
 | 
					  push:
 | 
				
			||||||
 | 
					    branches:
 | 
				
			||||||
 | 
					      - master
 | 
				
			||||||
 | 
					      - wip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  iwyu:
 | 
				
			||||||
 | 
					    timeout-minutes: 30
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    env:
 | 
				
			||||||
 | 
					      IWYU: 0.19
 | 
				
			||||||
 | 
					      LLVM: 15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					    continue-on-error: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					    - name: Install llvm/clang
 | 
				
			||||||
 | 
					      # see: https://apt.llvm.org/
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
 | 
				
			||||||
 | 
					        sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-$LLVM main"
 | 
				
			||||||
 | 
					        sudo apt update
 | 
				
			||||||
 | 
					        sudo apt remove -y "llvm*"
 | 
				
			||||||
 | 
					        sudo apt remove -y "libclang-dev*"
 | 
				
			||||||
 | 
					        sudo apt remove -y "clang*"
 | 
				
			||||||
 | 
					        sudo apt install -y llvm-$LLVM-dev
 | 
				
			||||||
 | 
					        sudo apt install -y libclang-$LLVM-dev
 | 
				
			||||||
 | 
					        sudo apt install -y clang-$LLVM
 | 
				
			||||||
 | 
					    - name: Compile iwyu
 | 
				
			||||||
 | 
					      # see: https://github.com/include-what-you-use/include-what-you-use
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        git clone https://github.com/include-what-you-use/include-what-you-use.git --branch $IWYU --depth 1
 | 
				
			||||||
 | 
					        mkdir include-what-you-use/build
 | 
				
			||||||
 | 
					        cd include-what-you-use/build
 | 
				
			||||||
 | 
					        cmake -DCMAKE_C_COMPILER=clang-$LLVM \
 | 
				
			||||||
 | 
					              -DCMAKE_CXX_COMPILER=clang++-$LLVM \
 | 
				
			||||||
 | 
					              -DCMAKE_INSTALL_PREFIX=./ \
 | 
				
			||||||
 | 
					              ..
 | 
				
			||||||
 | 
					        make -j4
 | 
				
			||||||
 | 
					        bin/include-what-you-use --version
 | 
				
			||||||
 | 
					    - name: Compile tests
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        export PATH=$PATH:${GITHUB_WORKSPACE}/build/include-what-you-use/build/bin
 | 
				
			||||||
 | 
					        cmake -DCMAKE_C_COMPILER=clang-$LLVM \
 | 
				
			||||||
 | 
					              -DCMAKE_CXX_COMPILER=clang++-$LLVM \
 | 
				
			||||||
 | 
					              -DENTT_BUILD_TESTING=ON \
 | 
				
			||||||
 | 
					              -DENTT_BUILD_BENCHMARK=ON \
 | 
				
			||||||
 | 
					              -DENTT_BUILD_EXAMPLE=ON \
 | 
				
			||||||
 | 
					              -DENTT_BUILD_LIB=ON \
 | 
				
			||||||
 | 
					              -DENTT_BUILD_SNAPSHOT=ON \
 | 
				
			||||||
 | 
					              -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="include-what-you-use;-Xiwyu;--mapping_file=${GITHUB_WORKSPACE}/entt.imp;-Xiwyu;--no_fwd_decls;-Xiwyu;--verbose=1" \
 | 
				
			||||||
 | 
					              ..
 | 
				
			||||||
 | 
					        make -j4
 | 
				
			||||||
							
								
								
									
										144
									
								
								external/entt/entt/.github/workflows/build.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								external/entt/entt/.github/workflows/build.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,144 @@
 | 
				
			|||||||
 | 
					name: build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					on: [push, pull_request]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  linux:
 | 
				
			||||||
 | 
					    timeout-minutes: 15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        os: [ubuntu-latest, ubuntu-20.04]
 | 
				
			||||||
 | 
					        compiler:
 | 
				
			||||||
 | 
					          - { pkg: g++, exe: 'g++', version: 7 }
 | 
				
			||||||
 | 
					          - { pkg: g++, exe: 'g++', version: 8 }
 | 
				
			||||||
 | 
					          - { pkg: g++, exe: 'g++', version: 9 }
 | 
				
			||||||
 | 
					          - { pkg: g++, exe: 'g++', version: 10 }
 | 
				
			||||||
 | 
					          - { pkg: g++, exe: 'g++', version: 11 }
 | 
				
			||||||
 | 
					          - { pkg: g++, exe: 'g++', version: 12 }
 | 
				
			||||||
 | 
					          - { pkg: clang, exe: 'clang++', version: 8 }
 | 
				
			||||||
 | 
					          - { pkg: clang, exe: 'clang++', version: 9 }
 | 
				
			||||||
 | 
					          - { pkg: clang, exe: 'clang++', version: 10 }
 | 
				
			||||||
 | 
					          - { pkg: clang, exe: 'clang++', version: 11 }
 | 
				
			||||||
 | 
					          - { pkg: clang, exe: 'clang++', version: 12 }
 | 
				
			||||||
 | 
					          - { pkg: clang, exe: 'clang++', version: 13 }
 | 
				
			||||||
 | 
					          - { pkg: clang, exe: 'clang++', version: 14 }
 | 
				
			||||||
 | 
					        exclude:
 | 
				
			||||||
 | 
					          - os: ubuntu-latest
 | 
				
			||||||
 | 
					            compiler: { pkg: g++, exe: 'g++', version: 7 }
 | 
				
			||||||
 | 
					          - os: ubuntu-latest
 | 
				
			||||||
 | 
					            compiler: { pkg: g++, exe: 'g++', version: 8 }
 | 
				
			||||||
 | 
					          - os: ubuntu-latest
 | 
				
			||||||
 | 
					            compiler: { pkg: g++, exe: 'g++', version: 9 }
 | 
				
			||||||
 | 
					          - os: ubuntu-latest
 | 
				
			||||||
 | 
					            compiler: { pkg: clang, exe: 'clang++', version: 8 }
 | 
				
			||||||
 | 
					          - os: ubuntu-latest
 | 
				
			||||||
 | 
					            compiler: { pkg: clang, exe: 'clang++', version: 9 }
 | 
				
			||||||
 | 
					          - os: ubuntu-latest
 | 
				
			||||||
 | 
					            compiler: { pkg: clang, exe: 'clang++', version: 10 }
 | 
				
			||||||
 | 
					          - os: ubuntu-latest
 | 
				
			||||||
 | 
					            compiler: { pkg: clang, exe: 'clang++', version: 11 }
 | 
				
			||||||
 | 
					          - os: ubuntu-20.04
 | 
				
			||||||
 | 
					            compiler: { pkg: g++, exe: 'g++', version: 10 }
 | 
				
			||||||
 | 
					          - os: ubuntu-20.04
 | 
				
			||||||
 | 
					            compiler: { pkg: g++, exe: 'g++', version: 11 }
 | 
				
			||||||
 | 
					          - os: ubuntu-20.04
 | 
				
			||||||
 | 
					            compiler: { pkg: g++, exe: 'g++', version: 12 }
 | 
				
			||||||
 | 
					          - os: ubuntu-20.04
 | 
				
			||||||
 | 
					            compiler: { pkg: clang, exe: 'clang++', version: 12 }
 | 
				
			||||||
 | 
					          - os: ubuntu-20.04
 | 
				
			||||||
 | 
					            compiler: { pkg: clang, exe: 'clang++', version: 13 }
 | 
				
			||||||
 | 
					          - os: ubuntu-20.04
 | 
				
			||||||
 | 
					            compiler: { pkg: clang, exe: 'clang++', version: 14 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runs-on: ${{ matrix.os }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					    - name: Install compiler
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        sudo apt update
 | 
				
			||||||
 | 
					        sudo apt install -y ${{ matrix.compiler.pkg }}-${{ matrix.compiler.version }}
 | 
				
			||||||
 | 
					    - name: Compile tests
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      env:
 | 
				
			||||||
 | 
					        CXX: ${{ matrix.compiler.exe }}-${{ matrix.compiler.version }}
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        cmake -DENTT_BUILD_TESTING=ON -DENTT_BUILD_LIB=ON -DENTT_BUILD_EXAMPLE=ON ..
 | 
				
			||||||
 | 
					        make -j4
 | 
				
			||||||
 | 
					    - name: Run tests
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      env:
 | 
				
			||||||
 | 
					        CTEST_OUTPUT_ON_FAILURE: 1
 | 
				
			||||||
 | 
					      run: ctest --timeout 30 -C Debug -j4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  windows:
 | 
				
			||||||
 | 
					    timeout-minutes: 15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        toolset: [default, v141, v142, clang-cl]
 | 
				
			||||||
 | 
					        include:
 | 
				
			||||||
 | 
					          - toolset: v141
 | 
				
			||||||
 | 
					            toolset_option: -T"v141"
 | 
				
			||||||
 | 
					          - toolset: v142
 | 
				
			||||||
 | 
					            toolset_option: -T"v142"
 | 
				
			||||||
 | 
					          - toolset: clang-cl
 | 
				
			||||||
 | 
					            toolset_option: -T"ClangCl"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runs-on: windows-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					    - name: Compile tests
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        cmake -DENTT_BUILD_TESTING=ON -DENTT_BUILD_LIB=ON -DENTT_BUILD_EXAMPLE=ON ${{ matrix.toolset_option }} ..
 | 
				
			||||||
 | 
					        cmake --build . -j 4
 | 
				
			||||||
 | 
					    - name: Run tests
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      env:
 | 
				
			||||||
 | 
					        CTEST_OUTPUT_ON_FAILURE: 1
 | 
				
			||||||
 | 
					      run: ctest --timeout 30 -C Debug -j4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  macos:
 | 
				
			||||||
 | 
					    timeout-minutes: 15
 | 
				
			||||||
 | 
					    runs-on: macOS-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					    - name: Compile tests
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        cmake -DENTT_BUILD_TESTING=ON -DENTT_BUILD_LIB=ON -DENTT_BUILD_EXAMPLE=ON ..
 | 
				
			||||||
 | 
					        make -j4
 | 
				
			||||||
 | 
					    - name: Run tests
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      env:
 | 
				
			||||||
 | 
					        CTEST_OUTPUT_ON_FAILURE: 1
 | 
				
			||||||
 | 
					      run: ctest --timeout 30 -C Debug -j4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  extra:
 | 
				
			||||||
 | 
					    timeout-minutes: 15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        os: [windows-latest, macOS-latest, ubuntu-latest]
 | 
				
			||||||
 | 
					        id_type: ["std::uint32_t", "std::uint64_t"]
 | 
				
			||||||
 | 
					        cxx_std: [cxx_std_17, cxx_std_20]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runs-on: ${{ matrix.os }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					    - name: Compile tests
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        cmake -DENTT_BUILD_TESTING=ON -DENTT_CXX_STD=${{ matrix.cxx_std }} -DENTT_ID_TYPE=${{ matrix.id_type }} ..
 | 
				
			||||||
 | 
					        cmake --build . -j 4
 | 
				
			||||||
 | 
					    - name: Run tests
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      env:
 | 
				
			||||||
 | 
					        CTEST_OUTPUT_ON_FAILURE: 1
 | 
				
			||||||
 | 
					      run: ctest --timeout 30 -C Debug -j4
 | 
				
			||||||
							
								
								
									
										38
									
								
								external/entt/entt/.github/workflows/coverage.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								external/entt/entt/.github/workflows/coverage.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					name: coverage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					on: [push, pull_request]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  codecov:
 | 
				
			||||||
 | 
					    timeout-minutes: 15
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					    - name: Compile tests
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      env:
 | 
				
			||||||
 | 
					        CXXFLAGS: "--coverage -fno-elide-constructors -fno-inline -fno-default-inline"
 | 
				
			||||||
 | 
					        CXX: g++
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        cmake -DENTT_BUILD_TESTING=ON -DENTT_BUILD_LIB=ON -DENTT_BUILD_EXAMPLE=ON ..
 | 
				
			||||||
 | 
					        make -j4
 | 
				
			||||||
 | 
					    - name: Run tests
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      env:
 | 
				
			||||||
 | 
					        CTEST_OUTPUT_ON_FAILURE: 1
 | 
				
			||||||
 | 
					      run: ctest --timeout 30 -C Debug -j4
 | 
				
			||||||
 | 
					    - name: Collect data
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        sudo apt install lcov
 | 
				
			||||||
 | 
					        lcov -c -d . -o coverage.info
 | 
				
			||||||
 | 
					        lcov -l coverage.info
 | 
				
			||||||
 | 
					    - name: Upload coverage to Codecov
 | 
				
			||||||
 | 
					      uses: codecov/codecov-action@v3
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        token: ${{ secrets.CODECOV_TOKEN }}
 | 
				
			||||||
 | 
					        files: build/coverage.info
 | 
				
			||||||
 | 
					        name: EnTT
 | 
				
			||||||
 | 
					        fail_ci_if_error: true
 | 
				
			||||||
							
								
								
									
										39
									
								
								external/entt/entt/.github/workflows/deploy.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								external/entt/entt/.github/workflows/deploy.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					name: deploy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					on:
 | 
				
			||||||
 | 
					  release:
 | 
				
			||||||
 | 
					    types: published
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  homebrew-entt:
 | 
				
			||||||
 | 
					    timeout-minutes: 5
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    env:
 | 
				
			||||||
 | 
					      GH_REPO: homebrew-entt
 | 
				
			||||||
 | 
					      FORMULA: entt.rb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					    - name: Clone repository
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      env:
 | 
				
			||||||
 | 
					        PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
 | 
				
			||||||
 | 
					      run: git clone https://$GITHUB_ACTOR:$PERSONAL_ACCESS_TOKEN@github.com/$GITHUB_ACTOR/$GH_REPO.git
 | 
				
			||||||
 | 
					    - name: Prepare formula
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        cd $GH_REPO
 | 
				
			||||||
 | 
					        curl "https://github.com/${{ github.repository }}/archive/${{ github.ref }}.tar.gz" --location --fail --silent --show-error --output archive.tar.gz
 | 
				
			||||||
 | 
					        sed -i -e '/url/s/".*"/"'$(echo "https://github.com/${{ github.repository }}/archive/${{ github.ref }}.tar.gz" | sed -e 's/[\/&]/\\&/g')'"/' $FORMULA
 | 
				
			||||||
 | 
					        sed -i -e '/sha256/s/".*"/"'$(openssl sha256 archive.tar.gz | cut -d " " -f 2)'"/' $FORMULA
 | 
				
			||||||
 | 
					    - name: Update remote
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        cd $GH_REPO
 | 
				
			||||||
 | 
					        git config --local user.email "action@github.com"
 | 
				
			||||||
 | 
					        git config --local user.name "$GITHUB_ACTOR"
 | 
				
			||||||
 | 
					        git add $FORMULA
 | 
				
			||||||
 | 
					        git commit -m "Update to ${{ github.ref }}"
 | 
				
			||||||
 | 
					        git push origin master
 | 
				
			||||||
							
								
								
									
										31
									
								
								external/entt/entt/.github/workflows/sanitizer.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								external/entt/entt/.github/workflows/sanitizer.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					name: sanitizer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					on: [push, pull_request]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  clang:
 | 
				
			||||||
 | 
					    timeout-minutes: 15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        compiler: [clang++]
 | 
				
			||||||
 | 
					        id_type: ["std::uint32_t", "std::uint64_t"]
 | 
				
			||||||
 | 
					        cxx_std: [cxx_std_17, cxx_std_20]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					    - name: Compile tests
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      env:
 | 
				
			||||||
 | 
					        CXX: ${{ matrix.compiler }}
 | 
				
			||||||
 | 
					      run: |
 | 
				
			||||||
 | 
					        cmake -DENTT_USE_SANITIZER=ON -DENTT_BUILD_TESTING=ON -DENTT_BUILD_LIB=ON -DENTT_BUILD_EXAMPLE=ON -DENTT_CXX_STD=${{ matrix.cxx_std }} -DENTT_ID_TYPE=${{ matrix.id_type }} ..
 | 
				
			||||||
 | 
					        make -j4
 | 
				
			||||||
 | 
					    - name: Run tests
 | 
				
			||||||
 | 
					      working-directory: build
 | 
				
			||||||
 | 
					      env:
 | 
				
			||||||
 | 
					        CTEST_OUTPUT_ON_FAILURE: 1
 | 
				
			||||||
 | 
					      run: ctest --timeout 30 -C Debug -j4
 | 
				
			||||||
							
								
								
									
										13
									
								
								external/entt/entt/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								external/entt/entt/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					# Conan
 | 
				
			||||||
 | 
					conan/test_package/build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# IDEs
 | 
				
			||||||
 | 
					*.user
 | 
				
			||||||
 | 
					.idea
 | 
				
			||||||
 | 
					.vscode
 | 
				
			||||||
 | 
					.vs
 | 
				
			||||||
 | 
					CMakeSettings.json
 | 
				
			||||||
 | 
					cpp.hint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Bazel
 | 
				
			||||||
 | 
					/bazel-*
 | 
				
			||||||
							
								
								
									
										56
									
								
								external/entt/entt/AUTHORS
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								external/entt/entt/AUTHORS
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					# Author
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					skypjack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Contributors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					alexames
 | 
				
			||||||
 | 
					BenediktConze
 | 
				
			||||||
 | 
					bjadamson
 | 
				
			||||||
 | 
					ceeac
 | 
				
			||||||
 | 
					ColinH
 | 
				
			||||||
 | 
					corystegel
 | 
				
			||||||
 | 
					Croydon
 | 
				
			||||||
 | 
					cschreib
 | 
				
			||||||
 | 
					cugone
 | 
				
			||||||
 | 
					dbacchet
 | 
				
			||||||
 | 
					dBagrat
 | 
				
			||||||
 | 
					djarek
 | 
				
			||||||
 | 
					DNKpp
 | 
				
			||||||
 | 
					DonKult
 | 
				
			||||||
 | 
					drglove
 | 
				
			||||||
 | 
					eliasdaler
 | 
				
			||||||
 | 
					erez-o
 | 
				
			||||||
 | 
					eugeneko
 | 
				
			||||||
 | 
					gale83
 | 
				
			||||||
 | 
					ghost
 | 
				
			||||||
 | 
					grdowns
 | 
				
			||||||
 | 
					Green-Sky
 | 
				
			||||||
 | 
					Innokentiy-Alaytsev
 | 
				
			||||||
 | 
					Kerndog73
 | 
				
			||||||
 | 
					Koward
 | 
				
			||||||
 | 
					Lawrencemm
 | 
				
			||||||
 | 
					markand
 | 
				
			||||||
 | 
					mhammerc
 | 
				
			||||||
 | 
					Milerius
 | 
				
			||||||
 | 
					Minimonium
 | 
				
			||||||
 | 
					morbo84
 | 
				
			||||||
 | 
					m-waka
 | 
				
			||||||
 | 
					netpoetica
 | 
				
			||||||
 | 
					NixAJ
 | 
				
			||||||
 | 
					Oortonaut
 | 
				
			||||||
 | 
					Paolo-Oliverio
 | 
				
			||||||
 | 
					pgruenbacher
 | 
				
			||||||
 | 
					prowolf
 | 
				
			||||||
 | 
					Qix-
 | 
				
			||||||
 | 
					stefanofiorentino
 | 
				
			||||||
 | 
					suVrik
 | 
				
			||||||
 | 
					szunhammer
 | 
				
			||||||
 | 
					The5-1
 | 
				
			||||||
 | 
					vblanco20-1
 | 
				
			||||||
 | 
					willtunnels
 | 
				
			||||||
 | 
					WizardIke
 | 
				
			||||||
 | 
					WoLfulus 
 | 
				
			||||||
 | 
					w1th0utnam3
 | 
				
			||||||
 | 
					xissburg
 | 
				
			||||||
 | 
					zaucy
 | 
				
			||||||
							
								
								
									
										14
									
								
								external/entt/entt/BUILD.bazel
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								external/entt/entt/BUILD.bazel
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					_msvc_copts = ["/std:c++17"]	
 | 
				
			||||||
 | 
					_gcc_copts = ["-std=c++17"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cc_library(
 | 
				
			||||||
 | 
					    name = "entt",
 | 
				
			||||||
 | 
					    visibility = ["//visibility:public"],
 | 
				
			||||||
 | 
					    strip_include_prefix = "src",
 | 
				
			||||||
 | 
					    hdrs = glob(["src/**/*.h", "src/**/*.hpp"]),
 | 
				
			||||||
 | 
					    copts = select({
 | 
				
			||||||
 | 
					      "@bazel_tools//src/conditions:windows": _msvc_copts,
 | 
				
			||||||
 | 
					      "@bazel_tools//src/conditions:windows_msvc": _msvc_copts,
 | 
				
			||||||
 | 
					      "//conditions:default": _gcc_copts,
 | 
				
			||||||
 | 
					    }),
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										325
									
								
								external/entt/entt/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										325
									
								
								external/entt/entt/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,325 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# EnTT
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cmake_minimum_required(VERSION 3.15.7)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Read project version
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(ENTT_VERSION_REGEX "#define ENTT_VERSION_.*[ \t]+(.+)")
 | 
				
			||||||
 | 
					file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/src/entt/config/version.h" ENTT_VERSION REGEX ${ENTT_VERSION_REGEX})
 | 
				
			||||||
 | 
					list(TRANSFORM ENTT_VERSION REPLACE ${ENTT_VERSION_REGEX} "\\1")
 | 
				
			||||||
 | 
					string(JOIN "." ENTT_VERSION ${ENTT_VERSION})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Project configuration
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					project(
 | 
				
			||||||
 | 
					    EnTT
 | 
				
			||||||
 | 
					    VERSION ${ENTT_VERSION}
 | 
				
			||||||
 | 
					    DESCRIPTION "Gaming meets modern C++ - a fast and reliable entity-component system (ECS) and much more"
 | 
				
			||||||
 | 
					    HOMEPAGE_URL "https://github.com/skypjack/entt"
 | 
				
			||||||
 | 
					    LANGUAGES C CXX
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(NOT CMAKE_BUILD_TYPE)
 | 
				
			||||||
 | 
					    set(CMAKE_BUILD_TYPE Debug)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message(VERBOSE "*")
 | 
				
			||||||
 | 
					message(VERBOSE "* ${PROJECT_NAME} v${PROJECT_VERSION} (${CMAKE_BUILD_TYPE})")
 | 
				
			||||||
 | 
					message(VERBOSE "* Copyright (c) 2017-2023 Michele Caini <michele.caini@gmail.com>")
 | 
				
			||||||
 | 
					message(VERBOSE "*")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# CMake stuff
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Compiler stuff
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option(ENTT_USE_LIBCPP "Use libc++ by adding -stdlib=libc++ flag if available." OFF)
 | 
				
			||||||
 | 
					option(ENTT_USE_SANITIZER "Enable sanitizers by adding -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined flags if available." OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(ENTT_USE_LIBCPP)
 | 
				
			||||||
 | 
					    if(NOT WIN32)
 | 
				
			||||||
 | 
					        include(CheckCXXSourceCompiles)
 | 
				
			||||||
 | 
					        include(CMakePushCheckState)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cmake_push_check_state()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -stdlib=libc++")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        check_cxx_source_compiles("
 | 
				
			||||||
 | 
					            #include<type_traits>
 | 
				
			||||||
 | 
					            int main() { return std::is_same_v<int, char>; }
 | 
				
			||||||
 | 
					        " ENTT_HAS_LIBCPP)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cmake_pop_check_state()
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(NOT ENTT_HAS_LIBCPP)
 | 
				
			||||||
 | 
					        message(VERBOSE "The option ENTT_USE_LIBCPP is set but libc++ is not available. The flag will not be added to the target.")
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(ENTT_USE_SANITIZER)
 | 
				
			||||||
 | 
					    if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
 | 
				
			||||||
 | 
					        set(ENTT_HAS_SANITIZER TRUE CACHE BOOL "" FORCE)
 | 
				
			||||||
 | 
					        mark_as_advanced(ENTT_HAS_SANITIZER)
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(NOT ENTT_HAS_SANITIZER)
 | 
				
			||||||
 | 
					        message(VERBOSE "The option ENTT_USE_SANITIZER is set but sanitizer support is not available. The flags will not be added to the target.")
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Add EnTT target
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option(ENTT_INCLUDE_HEADERS "Add all EnTT headers to the EnTT target." OFF)
 | 
				
			||||||
 | 
					option(ENTT_INCLUDE_NATVIS "Add EnTT natvis files to the EnTT target." OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(ENTT_INCLUDE_NATVIS)
 | 
				
			||||||
 | 
					    if(MSVC)
 | 
				
			||||||
 | 
					        set(ENTT_HAS_NATVIS TRUE CACHE BOOL "" FORCE)
 | 
				
			||||||
 | 
					        mark_as_advanced(ENTT_HAS_NATVIS)
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(NOT ENTT_HAS_NATVIS)
 | 
				
			||||||
 | 
					        message(VERBOSE "The option ENTT_INCLUDE_NATVIS is set but natvis files are not supported. They will not be added to the target.")
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include(GNUInstallDirs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_library(EnTT INTERFACE)
 | 
				
			||||||
 | 
					add_library(EnTT::EnTT ALIAS EnTT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_include_directories(
 | 
				
			||||||
 | 
					    EnTT
 | 
				
			||||||
 | 
					    INTERFACE
 | 
				
			||||||
 | 
					        $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src>
 | 
				
			||||||
 | 
					        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_compile_features(EnTT INTERFACE cxx_std_17)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(ENTT_INCLUDE_HEADERS)
 | 
				
			||||||
 | 
					    target_sources(
 | 
				
			||||||
 | 
					        EnTT
 | 
				
			||||||
 | 
					        INTERFACE
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/config/config.h>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/config/macro.h>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/config/version.h>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/container/dense_map.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/container/dense_set.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/container/fwd.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/algorithm.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/any.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/attribute.h>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/compressed_pair.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/enum.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/family.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/fwd.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/hashed_string.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/ident.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/iterator.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/memory.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/monostate.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/tuple.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/type_info.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/type_traits.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/utility.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/component.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/entity.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/fwd.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/group.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/handle.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/mixin.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/helper.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/observer.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/organizer.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/registry.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/runtime_view.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/snapshot.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/sparse_set.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/storage.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/view.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/graph/adjacency_matrix.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/graph/dot.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/graph/flow.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/graph/fwd.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/locator/locator.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/adl_pointer.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/container.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/context.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/factory.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/fwd.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/meta.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/node.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/pointer.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/policy.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/range.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/resolve.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/template.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/type_traits.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/utility.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/platform/android-ndk-r17.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/poly/fwd.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/poly/poly.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/process/fwd.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/process/process.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/process/scheduler.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/resource/cache.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/resource/fwd.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/resource/loader.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/resource/resource.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/signal/delegate.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/signal/dispatcher.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/signal/emitter.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/signal/fwd.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/signal/sigh.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entt.hpp>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/fwd.hpp>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(ENTT_HAS_NATVIS)
 | 
				
			||||||
 | 
					    target_sources(
 | 
				
			||||||
 | 
					        EnTT
 | 
				
			||||||
 | 
					        INTERFACE
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/config.natvis>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/container.natvis>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/core.natvis>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/entity.natvis>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/graph.natvis>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/locator.natvis>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/meta.natvis>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/platform.natvis>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/poly.natvis>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/process.natvis>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/resource.natvis>
 | 
				
			||||||
 | 
					            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/signal.natvis>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(ENTT_HAS_SANITIZER)
 | 
				
			||||||
 | 
					    target_compile_options(EnTT INTERFACE $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined>)
 | 
				
			||||||
 | 
					    target_link_libraries(EnTT INTERFACE $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined>)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(ENTT_HAS_LIBCPP)
 | 
				
			||||||
 | 
					    target_compile_options(EnTT BEFORE INTERFACE -stdlib=libc++)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Install pkg-config file
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include(JoinPaths)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(EnTT_PKGCONFIG ${CMAKE_CURRENT_BINARY_DIR}/entt.pc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					join_paths(EnTT_PKGCONFIG_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					configure_file(
 | 
				
			||||||
 | 
					    ${EnTT_SOURCE_DIR}/cmake/in/entt.pc.in
 | 
				
			||||||
 | 
					    ${EnTT_PKGCONFIG}
 | 
				
			||||||
 | 
					    @ONLY
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install(
 | 
				
			||||||
 | 
					    FILES ${EnTT_PKGCONFIG}
 | 
				
			||||||
 | 
					    DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Install EnTT
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include(CMakePackageConfigHelpers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install(
 | 
				
			||||||
 | 
					    TARGETS EnTT
 | 
				
			||||||
 | 
					    EXPORT EnTTTargets
 | 
				
			||||||
 | 
					    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					write_basic_package_version_file(
 | 
				
			||||||
 | 
					    EnTTConfigVersion.cmake
 | 
				
			||||||
 | 
					    VERSION ${PROJECT_VERSION}
 | 
				
			||||||
 | 
					    COMPATIBILITY AnyNewerVersion
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					configure_package_config_file(
 | 
				
			||||||
 | 
					    ${EnTT_SOURCE_DIR}/cmake/in/EnTTConfig.cmake.in
 | 
				
			||||||
 | 
					    EnTTConfig.cmake
 | 
				
			||||||
 | 
					    INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/EnTT/cmake
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export(
 | 
				
			||||||
 | 
					    EXPORT EnTTTargets
 | 
				
			||||||
 | 
					    FILE ${CMAKE_CURRENT_BINARY_DIR}/EnTTTargets.cmake
 | 
				
			||||||
 | 
					    NAMESPACE EnTT::
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install(
 | 
				
			||||||
 | 
					    EXPORT EnTTTargets
 | 
				
			||||||
 | 
					    FILE EnTTTargets.cmake
 | 
				
			||||||
 | 
					    DESTINATION ${CMAKE_INSTALL_LIBDIR}/EnTT/cmake
 | 
				
			||||||
 | 
					    NAMESPACE EnTT::
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install(
 | 
				
			||||||
 | 
					    FILES
 | 
				
			||||||
 | 
					        ${PROJECT_BINARY_DIR}/EnTTConfig.cmake
 | 
				
			||||||
 | 
					        ${PROJECT_BINARY_DIR}/EnTTConfigVersion.cmake
 | 
				
			||||||
 | 
					    DESTINATION ${CMAKE_INSTALL_LIBDIR}/EnTT/cmake
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install(DIRECTORY src/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export(PACKAGE EnTT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Tests
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option(ENTT_BUILD_TESTING "Enable building tests." OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(ENTT_BUILD_TESTING)
 | 
				
			||||||
 | 
					    option(ENTT_FIND_GTEST_PACKAGE "Enable finding gtest package." OFF)
 | 
				
			||||||
 | 
					    option(ENTT_BUILD_BENCHMARK "Build benchmark." OFF)
 | 
				
			||||||
 | 
					    option(ENTT_BUILD_EXAMPLE "Build examples." OFF)
 | 
				
			||||||
 | 
					    option(ENTT_BUILD_LIB "Build lib tests." OFF)
 | 
				
			||||||
 | 
					    option(ENTT_BUILD_SNAPSHOT "Build snapshot test with Cereal." OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    set(ENTT_ID_TYPE std::uint32_t CACHE STRING "Type of identifiers to use for the tests")
 | 
				
			||||||
 | 
					    set(ENTT_CXX_STD cxx_std_17 CACHE STRING "C++ standard revision to use for the tests")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    include(CTest)
 | 
				
			||||||
 | 
					    enable_testing()
 | 
				
			||||||
 | 
					    add_subdirectory(test)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Documentation
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option(ENTT_BUILD_DOCS "Enable building with documentation." OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(ENTT_BUILD_DOCS)
 | 
				
			||||||
 | 
					    find_package(Doxygen 1.8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(DOXYGEN_FOUND)
 | 
				
			||||||
 | 
					        add_subdirectory(docs)
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
							
								
								
									
										43
									
								
								external/entt/entt/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								external/entt/entt/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					# Contributing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					First of all, thank you very much for taking the time to contribute to the
 | 
				
			||||||
 | 
					`EnTT` library.<br/>
 | 
				
			||||||
 | 
					How to do it mostly depends on the type of contribution:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* If you have a question, **please** ensure there isn't already an answer for
 | 
				
			||||||
 | 
					  you by searching on GitHub under
 | 
				
			||||||
 | 
					  [issues](https://github.com/skypjack/entt/issues). Do not forget to search
 | 
				
			||||||
 | 
					  also through the closed ones. If you are unable to find a proper answer, feel
 | 
				
			||||||
 | 
					  free to [open a new issue](https://github.com/skypjack/entt/issues/new).
 | 
				
			||||||
 | 
					  Usually, questions are marked as such and closed in a few days.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* If you want to fix a typo in the inline documentation or in the README file,
 | 
				
			||||||
 | 
					  if you want to add some new sections or if you want to help me with the
 | 
				
			||||||
 | 
					  language by reviewing what I wrote so far (I'm not a native speaker after
 | 
				
			||||||
 | 
					  all), **please** open a new
 | 
				
			||||||
 | 
					  [pull request](https://github.com/skypjack/entt/pulls) with your changes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* If you found a bug, **please** ensure there isn't already an answer for you by
 | 
				
			||||||
 | 
					  searching on GitHub under [issues](https://github.com/skypjack/entt/issues).
 | 
				
			||||||
 | 
					  If you are unable to find an open issue addressing the problem, feel free to
 | 
				
			||||||
 | 
					  [open a new one](https://github.com/skypjack/entt/issues/new). **Please**, do
 | 
				
			||||||
 | 
					  not forget to carefully describe how to reproduce the problem, then add all
 | 
				
			||||||
 | 
					  the information about the system on which you are experiencing it and point
 | 
				
			||||||
 | 
					  out the version of `EnTT` you are using (tag or commit).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* If you found a bug and you wrote a patch to fix it, open a new
 | 
				
			||||||
 | 
					  [pull request](https://github.com/skypjack/entt/pulls) with your code.
 | 
				
			||||||
 | 
					  **Please**, add some tests to avoid regressions in future if possible, it
 | 
				
			||||||
 | 
					  would be really appreciated. Note that the `EnTT` library has a
 | 
				
			||||||
 | 
					  [coverage at 100%](https://coveralls.io/github/skypjack/entt?branch=master)
 | 
				
			||||||
 | 
					  (at least it was at 100% at the time I wrote this file) and this is the reason
 | 
				
			||||||
 | 
					  for which you can be confident with using it in a production environment.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* If you want to propose a new feature and you know how to code it, **please**
 | 
				
			||||||
 | 
					  do not issue directly a pull request. Before to do it,
 | 
				
			||||||
 | 
					  [create a new issue](https://github.com/skypjack/entt/issues/new) to discuss
 | 
				
			||||||
 | 
					  your proposal. Other users could be interested in your idea and the discussion
 | 
				
			||||||
 | 
					  that will follow can refine it and therefore give us a better solution.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* If you want to request a new feature, I'm available for hiring. Take a look at
 | 
				
			||||||
 | 
					  [my profile](https://github.com/skypjack) and feel free to write me.
 | 
				
			||||||
							
								
								
									
										21
									
								
								external/entt/entt/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								external/entt/entt/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					The MIT License (MIT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2017-2023 Michele Caini, author of EnTT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					copy of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					copy or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					SOFTWARE.
 | 
				
			||||||
							
								
								
									
										428
									
								
								external/entt/entt/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										428
									
								
								external/entt/entt/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,428 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					[](https://github.com/skypjack/entt/actions)
 | 
				
			||||||
 | 
					[](https://codecov.io/gh/skypjack/entt)
 | 
				
			||||||
 | 
					[](https://godbolt.org/z/zxW73f)
 | 
				
			||||||
 | 
					[](https://vcpkg.link/ports/entt)
 | 
				
			||||||
 | 
					[](https://skypjack.github.io/entt/)
 | 
				
			||||||
 | 
					[](https://gitter.im/skypjack/entt)
 | 
				
			||||||
 | 
					[](https://discord.gg/5BjPWBd)
 | 
				
			||||||
 | 
					[](https://www.paypal.me/skypjack)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> `EnTT` has been a dream so far, we haven't found a single bug to date and it's
 | 
				
			||||||
 | 
					> super easy to work with
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
					> -- Every EnTT User Ever
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` is a header-only, tiny and easy to use library for game programming and
 | 
				
			||||||
 | 
					much more written in **modern C++**.<br/>
 | 
				
			||||||
 | 
					[Among others](https://github.com/skypjack/entt/wiki/EnTT-in-Action), it's used
 | 
				
			||||||
 | 
					in [**Minecraft**](https://minecraft.net/en-us/attribution/) by Mojang, the
 | 
				
			||||||
 | 
					[**ArcGIS Runtime SDKs**](https://developers.arcgis.com/arcgis-runtime/) by Esri
 | 
				
			||||||
 | 
					and the amazing [**Ragdoll**](https://ragdolldynamics.com/).<br/>
 | 
				
			||||||
 | 
					If you don't see your project in the list, please open an issue, submit a PR or
 | 
				
			||||||
 | 
					add the [#entt](https://github.com/topics/entt) tag to your _topics_! :+1:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Do you want to **keep up with changes** or do you have a **question** that
 | 
				
			||||||
 | 
					doesn't require you to open an issue?<br/>
 | 
				
			||||||
 | 
					Join the [gitter channel](https://gitter.im/skypjack/entt) and the
 | 
				
			||||||
 | 
					[discord server](https://discord.gg/5BjPWBd), meet other users like you. The
 | 
				
			||||||
 | 
					more we are, the better for everyone.<br/>
 | 
				
			||||||
 | 
					Don't forget to check the
 | 
				
			||||||
 | 
					[FAQs](https://github.com/skypjack/entt/wiki/Frequently-Asked-Questions) and the
 | 
				
			||||||
 | 
					[wiki](https://github.com/skypjack/entt/wiki) too. Your answers may already be
 | 
				
			||||||
 | 
					there.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Do you want to support `EnTT`? Consider becoming a
 | 
				
			||||||
 | 
					[**sponsor**](https://github.com/users/skypjack/sponsorship).
 | 
				
			||||||
 | 
					Many thanks to [these people](https://skypjack.github.io/sponsorship/) and
 | 
				
			||||||
 | 
					**special** thanks to:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[](https://mojang.com)
 | 
				
			||||||
 | 
					[](https://img.ly/)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Introduction](#introduction)
 | 
				
			||||||
 | 
					  * [Code Example](#code-example)
 | 
				
			||||||
 | 
					  * [Motivation](#motivation)
 | 
				
			||||||
 | 
					  * [Performance](#performance)
 | 
				
			||||||
 | 
					* [Integration](#integration)
 | 
				
			||||||
 | 
					  * [Requirements](#requirements)
 | 
				
			||||||
 | 
					  * [CMake](#cmake)
 | 
				
			||||||
 | 
					  * [Natvis support](#natvis-support)
 | 
				
			||||||
 | 
					  * [Packaging Tools](#packaging-tools)
 | 
				
			||||||
 | 
					  * [pkg-config](#pkg-config)
 | 
				
			||||||
 | 
					* [Documentation](#documentation)
 | 
				
			||||||
 | 
					* [Tests](#tests)
 | 
				
			||||||
 | 
					* [EnTT in Action](#entt-in-action)
 | 
				
			||||||
 | 
					* [Contributors](#contributors)
 | 
				
			||||||
 | 
					* [License](#license)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The entity-component-system (also known as _ECS_) is an architectural pattern
 | 
				
			||||||
 | 
					used mostly in game development. For further details:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Entity Systems Wiki](http://entity-systems.wikidot.com/)
 | 
				
			||||||
 | 
					* [Evolve Your Hierarchy](http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/)
 | 
				
			||||||
 | 
					* [ECS on Wikipedia](https://en.wikipedia.org/wiki/Entity%E2%80%93component%E2%80%93system)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This project started off as a pure entity-component system. Over time the
 | 
				
			||||||
 | 
					codebase has grown as more and more classes and functionalities were added.<br/>
 | 
				
			||||||
 | 
					Here is a brief, yet incomplete list of what it offers today:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Built-in **RTTI system** mostly similar to the standard one.
 | 
				
			||||||
 | 
					* A `constexpr` utility for human-readable **resource names**.
 | 
				
			||||||
 | 
					* Minimal **configuration system** built using the monostate pattern.
 | 
				
			||||||
 | 
					* Incredibly fast **entity-component system** with its own _pay for what you
 | 
				
			||||||
 | 
					  use_ policy, unconstrained component types with optional pointer stability and
 | 
				
			||||||
 | 
					  hooks for storage customization.
 | 
				
			||||||
 | 
					* Views and groups to iterate entities and components and allow different access
 | 
				
			||||||
 | 
					  patterns, from **perfect SoA** to fully random.
 | 
				
			||||||
 | 
					* A lot of **facilities** built on top of the entity-component system to help
 | 
				
			||||||
 | 
					  the users and avoid reinventing the wheel.
 | 
				
			||||||
 | 
					* General purpose **execution graph builder** for optimal scheduling.
 | 
				
			||||||
 | 
					* The smallest and most basic implementation of a **service locator** ever seen.
 | 
				
			||||||
 | 
					* A built-in, non-intrusive and macro-free runtime **reflection system**.
 | 
				
			||||||
 | 
					* **Static polymorphism** made simple and within everyone's reach.
 | 
				
			||||||
 | 
					* A few homemade containers, like a sparse set based **hash map**.
 | 
				
			||||||
 | 
					* A **cooperative scheduler** for processes of any type.
 | 
				
			||||||
 | 
					* All that is needed for **resource management** (cache, loaders, handles).
 | 
				
			||||||
 | 
					* Delegates, **signal handlers** and a tiny event dispatcher.
 | 
				
			||||||
 | 
					* A general purpose **event emitter** as a CRTP idiom based class template.
 | 
				
			||||||
 | 
					* And **much more**! Check out the
 | 
				
			||||||
 | 
					  [**wiki**](https://github.com/skypjack/entt/wiki).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Consider this list a work in progress as well as the project. The whole API is
 | 
				
			||||||
 | 
					fully documented in-code for those who are brave enough to read it.<br/>
 | 
				
			||||||
 | 
					Please, do note that all tools are also DLL-friendly now and run smoothly across
 | 
				
			||||||
 | 
					boundaries.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					One thing known to most is that `EnTT` is also used in **Minecraft**.<br/>
 | 
				
			||||||
 | 
					Given that the game is available literally everywhere, I can confidently say 
 | 
				
			||||||
 | 
					that the library has been sufficiently tested on every platform that can come to 
 | 
				
			||||||
 | 
					mind.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Code Example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					#include <entt/entt.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct position {
 | 
				
			||||||
 | 
					    float x;
 | 
				
			||||||
 | 
					    float y;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct velocity {
 | 
				
			||||||
 | 
					    float dx;
 | 
				
			||||||
 | 
					    float dy;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void update(entt::registry ®istry) {
 | 
				
			||||||
 | 
					    auto view = registry.view<const position, velocity>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // use a callback
 | 
				
			||||||
 | 
					    view.each([](const auto &pos, auto &vel) { /* ... */ });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // use an extended callback
 | 
				
			||||||
 | 
					    view.each([](const auto entity, const auto &pos, auto &vel) { /* ... */ });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // use a range-for
 | 
				
			||||||
 | 
					    for(auto [entity, pos, vel]: view.each()) {
 | 
				
			||||||
 | 
					        // ...
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // use forward iterators and get only the components of interest
 | 
				
			||||||
 | 
					    for(auto entity: view) {
 | 
				
			||||||
 | 
					        auto &vel = view.get<velocity>(entity);
 | 
				
			||||||
 | 
					        // ...
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() {
 | 
				
			||||||
 | 
					    entt::registry registry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for(auto i = 0u; i < 10u; ++i) {
 | 
				
			||||||
 | 
					        const auto entity = registry.create();
 | 
				
			||||||
 | 
					        registry.emplace<position>(entity, i * 1.f, i * 1.f);
 | 
				
			||||||
 | 
					        if(i % 2 == 0) { registry.emplace<velocity>(entity, i * .1f, i * .1f); }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    update(registry);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Motivation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I started developing `EnTT` for the _wrong_ reason: my goal was to design an
 | 
				
			||||||
 | 
					entity-component system to beat another well known open source library both in
 | 
				
			||||||
 | 
					terms of performance and possibly memory usage.<br/>
 | 
				
			||||||
 | 
					In the end, I did it, but it wasn't very satisfying. Actually it wasn't
 | 
				
			||||||
 | 
					satisfying at all. The fastest and nothing more, fairly little indeed. When I
 | 
				
			||||||
 | 
					realized it, I tried hard to keep intact the great performance of `EnTT` and to
 | 
				
			||||||
 | 
					add all the features I wanted to see in *my own library* at the same time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Nowadays, `EnTT` is finally what I was looking for: still faster than its
 | 
				
			||||||
 | 
					_competitors_, lower memory usage in the average case, a really good API and an
 | 
				
			||||||
 | 
					amazing set of features. And even more, of course.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Performance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The proposed entity-component system is incredibly fast to iterate entities and
 | 
				
			||||||
 | 
					components, this is a fact. Some compilers make a lot of optimizations because
 | 
				
			||||||
 | 
					of how `EnTT` works, some others aren't that good. In general, if we consider
 | 
				
			||||||
 | 
					real world cases, `EnTT` is somewhere between a bit and much faster than many of
 | 
				
			||||||
 | 
					the other solutions around, although I couldn't check them all for obvious
 | 
				
			||||||
 | 
					reasons.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you are interested, you can compile the `benchmark` test in release mode (to
 | 
				
			||||||
 | 
					enable compiler optimizations, otherwise it would make little sense) by setting
 | 
				
			||||||
 | 
					the `ENTT_BUILD_BENCHMARK` option of `CMake` to `ON`, then evaluate yourself
 | 
				
			||||||
 | 
					whether you're satisfied with the results or not.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Honestly I got tired of updating the README file whenever there is an
 | 
				
			||||||
 | 
					improvement.<br/>
 | 
				
			||||||
 | 
					There are already a lot of projects out there that use `EnTT` as a basis for
 | 
				
			||||||
 | 
					comparison (this should already tell you a lot). Many of these benchmarks are
 | 
				
			||||||
 | 
					completely wrong, many others are simply incomplete, good at omitting some
 | 
				
			||||||
 | 
					information and using the wrong function to compare a given feature. Certainly
 | 
				
			||||||
 | 
					there are also good ones but they age quickly if nobody updates them, especially
 | 
				
			||||||
 | 
					when the library they are dealing with is actively developed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The choice to use `EnTT` should be based on its carefully designed API, its
 | 
				
			||||||
 | 
					set of features and the general performance, **not** because some single
 | 
				
			||||||
 | 
					benchmark shows it to be the fastest tool available.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In the future I'll likely try to get even better performance while still adding
 | 
				
			||||||
 | 
					new features, mainly for fun.<br/>
 | 
				
			||||||
 | 
					If you want to contribute and/or have suggestions, feel free to make a PR or
 | 
				
			||||||
 | 
					open an issue to discuss your idea.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Integration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` is a header-only library. This means that including the `entt.hpp` header
 | 
				
			||||||
 | 
					is enough to include the library as a whole and use it. For those who are
 | 
				
			||||||
 | 
					interested only in the entity-component system, consider to include the sole
 | 
				
			||||||
 | 
					`entity/registry.hpp` header instead.<br/>
 | 
				
			||||||
 | 
					It's a matter of adding the following line to the top of a file:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					#include <entt/entt.hpp>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Use the line below to include only the entity-component system instead:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					#include <entt/entity/registry.hpp>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Then pass the proper `-I` argument to the compiler to add the `src` directory to
 | 
				
			||||||
 | 
					the include paths.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Requirements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To be able to use `EnTT`, users must provide a full-featured compiler that
 | 
				
			||||||
 | 
					supports at least C++17.<br/>
 | 
				
			||||||
 | 
					The requirements below are mandatory to compile the tests and to extract the
 | 
				
			||||||
 | 
					documentation:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `CMake` version 3.7 or later.
 | 
				
			||||||
 | 
					* `Doxygen` version 1.8 or later.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Alternatively, [Bazel](https://bazel.build) is also supported as a build system
 | 
				
			||||||
 | 
					(credits to [zaucy](https://github.com/zaucy) who offered to maintain it).<br/>
 | 
				
			||||||
 | 
					In the documentation below I'll still refer to `CMake`, this being the official
 | 
				
			||||||
 | 
					build system of the library.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## CMake
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To use `EnTT` from a `CMake` project, just link an existing target to the
 | 
				
			||||||
 | 
					`EnTT::EnTT` alias.<br/>
 | 
				
			||||||
 | 
					The library offers everything you need for locating (as in `find_package`),
 | 
				
			||||||
 | 
					embedding (as in `add_subdirectory`), fetching (as in `FetchContent`) or using
 | 
				
			||||||
 | 
					it in many of the ways that you can think of and that involve `CMake`.<br/>
 | 
				
			||||||
 | 
					Covering all possible cases would require a treaty and not a simple README file,
 | 
				
			||||||
 | 
					but I'm confident that anyone reading this section also knows what it's about
 | 
				
			||||||
 | 
					and can use `EnTT` from a `CMake` project without problems.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Natvis support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When using `CMake`, just enable the option `ENTT_INCLUDE_NATVIS` and enjoy
 | 
				
			||||||
 | 
					it.<br/>
 | 
				
			||||||
 | 
					Otherwise, most of the tools are covered via Natvis and all files can be found
 | 
				
			||||||
 | 
					in the `natvis` directory, divided by module.<br/>
 | 
				
			||||||
 | 
					If you spot errors or have suggestions, any contribution is welcome!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Packaging Tools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` is available for some of the most known packaging tools. In particular:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [`Conan`](https://github.com/conan-io/conan-center-index), the C/C++ Package
 | 
				
			||||||
 | 
					  Manager for Developers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [`vcpkg`](https://github.com/Microsoft/vcpkg), Microsoft VC++ Packaging
 | 
				
			||||||
 | 
					  Tool.<br/>
 | 
				
			||||||
 | 
					  You can download and install `EnTT` in just a few simple steps:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					  $ git clone https://github.com/Microsoft/vcpkg.git
 | 
				
			||||||
 | 
					  $ cd vcpkg
 | 
				
			||||||
 | 
					  $ ./bootstrap-vcpkg.sh
 | 
				
			||||||
 | 
					  $ ./vcpkg integrate install
 | 
				
			||||||
 | 
					  $ vcpkg install entt
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Or you can use the `experimental` feature to test the latest changes:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					  vcpkg install entt[experimental] --head
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The `EnTT` port in `vcpkg` is kept up to date by Microsoft team members and
 | 
				
			||||||
 | 
					  community contributors.<br/>
 | 
				
			||||||
 | 
					  If the version is out of date, please
 | 
				
			||||||
 | 
					  [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the
 | 
				
			||||||
 | 
					  `vcpkg` repository.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [`Homebrew`](https://github.com/skypjack/homebrew-entt), the missing package
 | 
				
			||||||
 | 
					  manager for macOS.<br/>
 | 
				
			||||||
 | 
					  Available as a homebrew formula. Just type the following to install it:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					  brew install skypjack/entt/entt
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [`build2`](https://build2.org), build toolchain for developing and packaging C
 | 
				
			||||||
 | 
					  and C++ code.<br/>
 | 
				
			||||||
 | 
					  In order to use the [`entt`](https://cppget.org/entt) package in a `build2`
 | 
				
			||||||
 | 
					  project, add the following line or a similar one to the `manifest` file:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					  depends: entt ^3.0.0
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Also check that the configuration refers to a valid repository, so that the
 | 
				
			||||||
 | 
					  package can be found by `build2`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * [`cppget.org`](https://cppget.org), the open-source community central
 | 
				
			||||||
 | 
					    repository, accessible as `https://pkg.cppget.org/1/stable`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * [Package source repository](https://github.com/build2-packaging/entt):
 | 
				
			||||||
 | 
					    accessible as either `https://github.com/build2-packaging/entt.git` or
 | 
				
			||||||
 | 
					    `ssh://git@github.com/build2-packaging/entt.git`.
 | 
				
			||||||
 | 
					    Feel free to [report issues](https://github.com/build2-packaging/entt) with
 | 
				
			||||||
 | 
					    this package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Both can be used with `bpkg add-repo` or added in a project
 | 
				
			||||||
 | 
					  `repositories.manifest`. See the official
 | 
				
			||||||
 | 
					  [documentation](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml#guide-repositories)
 | 
				
			||||||
 | 
					  for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Consider this list a work in progress and help me to make it longer if you like.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## pkg-config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` also supports `pkg-config` (for some definition of _supports_ at least).
 | 
				
			||||||
 | 
					A suitable file called `entt.pc` is generated and installed in a proper
 | 
				
			||||||
 | 
					directory when running `CMake`.<br/>
 | 
				
			||||||
 | 
					This should also make it easier to use with tools such as `Meson` or similar.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Documentation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The documentation is based on [doxygen](http://www.doxygen.nl/). To build it:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $ cd build
 | 
				
			||||||
 | 
					    $ cmake .. -DENTT_BUILD_DOCS=ON
 | 
				
			||||||
 | 
					    $ make
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The API reference is created in HTML format in the `build/docs/html` directory.
 | 
				
			||||||
 | 
					To navigate it with your favorite browser:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $ cd build
 | 
				
			||||||
 | 
					    $ your_favorite_browser docs/html/index.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					The same version is also available [online](https://skypjack.github.io/entt/)
 | 
				
			||||||
 | 
					for the latest release, that is the last stable tag.<br/>
 | 
				
			||||||
 | 
					Moreover, there exists a [wiki](https://github.com/skypjack/entt/wiki) dedicated
 | 
				
			||||||
 | 
					to the project where users can find all related documentation pages.
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To compile and run the tests, `EnTT` requires *googletest*.<br/>
 | 
				
			||||||
 | 
					`cmake` downloads and compiles the library before compiling anything else. In
 | 
				
			||||||
 | 
					order to build the tests, set the `CMake` option `ENTT_BUILD_TESTING` to `ON`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To build the most basic set of tests:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `$ cd build`
 | 
				
			||||||
 | 
					* `$ cmake -DENTT_BUILD_TESTING=ON ..`
 | 
				
			||||||
 | 
					* `$ make`
 | 
				
			||||||
 | 
					* `$ make test`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note that benchmarks are not part of this set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# EnTT in Action
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` is widely used in private and commercial applications. I cannot even
 | 
				
			||||||
 | 
					mention most of them because of some signatures I put on some documents time
 | 
				
			||||||
 | 
					ago. Fortunately, there are also people who took the time to implement open
 | 
				
			||||||
 | 
					source projects based on `EnTT` and did not hold back when it came to
 | 
				
			||||||
 | 
					documenting them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Here](https://github.com/skypjack/entt/wiki/EnTT-in-Action) you can find an
 | 
				
			||||||
 | 
					incomplete list of games, applications and articles that can be used as a
 | 
				
			||||||
 | 
					reference.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you know of other resources out there that are about `EnTT`, feel free to
 | 
				
			||||||
 | 
					open an issue or a PR and I'll be glad to add them to the list.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Contributors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Requests for features, PRs, suggestions ad feedback are highly appreciated.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you find you can help and want to contribute to the project with your
 | 
				
			||||||
 | 
					experience or you do want to get part of the project for some other reason, feel
 | 
				
			||||||
 | 
					free to contact me directly (you can find the mail in the
 | 
				
			||||||
 | 
					[profile](https://github.com/skypjack)).<br/>
 | 
				
			||||||
 | 
					I can't promise that each and every contribution will be accepted, but I can
 | 
				
			||||||
 | 
					assure that I'll do my best to take them all as soon as possible.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you decide to participate, please see the guidelines for
 | 
				
			||||||
 | 
					[contributing](CONTRIBUTING.md) before to create issues or pull
 | 
				
			||||||
 | 
					requests.<br/>
 | 
				
			||||||
 | 
					Take also a look at the
 | 
				
			||||||
 | 
					[contributors list](https://github.com/skypjack/entt/blob/master/AUTHORS) to
 | 
				
			||||||
 | 
					know who has participated so far.
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Code and documentation Copyright (c) 2017-2023 Michele Caini.<br/>
 | 
				
			||||||
 | 
					Colorful logo Copyright (c) 2018-2021 Richard Caseres.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Code released under
 | 
				
			||||||
 | 
					[the MIT license](https://github.com/skypjack/entt/blob/master/LICENSE).<br/>
 | 
				
			||||||
 | 
					Documentation released under
 | 
				
			||||||
 | 
					[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).<br/>
 | 
				
			||||||
 | 
					All logos released under
 | 
				
			||||||
 | 
					[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).
 | 
				
			||||||
							
								
								
									
										26
									
								
								external/entt/entt/TODO
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								external/entt/entt/TODO
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					EXAMPLES
 | 
				
			||||||
 | 
					* filter on runtime values/variables (not only types)
 | 
				
			||||||
 | 
					* support to polymorphic types (see #859)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DOC:
 | 
				
			||||||
 | 
					* custom storage/view
 | 
				
			||||||
 | 
					* examples (and credits) from @alanjfs :)
 | 
				
			||||||
 | 
					* update entity doc when the storage based model is in place
 | 
				
			||||||
 | 
					* in-place O(1) release/destroy for non-orphaned entities, out-of-sync model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TODO (high prio):
 | 
				
			||||||
 | 
					* check natvis files (periodically :)
 | 
				
			||||||
 | 
					* resource cache: avoid using shared ptr with loader and the others
 | 
				
			||||||
 | 
					* further optimize exclusion lists in multi type views (no existence check)
 | 
				
			||||||
 | 
					* further improve the snapshot stuff, ie component functions
 | 
				
			||||||
 | 
					* use fixture for storage tests to reduce loc number and duplication as much as possible
 | 
				
			||||||
 | 
					* basic_view<...>::reach(...)
 | 
				
			||||||
 | 
					* doc: bump entities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WIP:
 | 
				
			||||||
 | 
					* get rid of observers, storage based views made them pointless - document alternatives
 | 
				
			||||||
 | 
					* exploit the tombstone mechanism to allow enabling/disabling entities (see bump, compact and clear for further details)
 | 
				
			||||||
 | 
					* process scheduler: reviews, use free lists internally
 | 
				
			||||||
 | 
					* deprecate non-owning groups in favor of owning views and view packs, introduce lazy owning views
 | 
				
			||||||
 | 
					* bring nested groups back in place (see bd34e7f)
 | 
				
			||||||
 | 
					* work stealing job system (see #100) + mt scheduler based on const awareness for types
 | 
				
			||||||
							
								
								
									
										1
									
								
								external/entt/entt/WORKSPACE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								external/entt/entt/WORKSPACE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					workspace(name = "com_github_skypjack_entt")
 | 
				
			||||||
							
								
								
									
										2
									
								
								external/entt/entt/build/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								external/entt/entt/build/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					*
 | 
				
			||||||
 | 
					!.gitignore
 | 
				
			||||||
							
								
								
									
										5
									
								
								external/entt/entt/cmake/in/EnTTConfig.cmake.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								external/entt/entt/cmake/in/EnTTConfig.cmake.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					@PACKAGE_INIT@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(EnTT_VERSION "@PROJECT_VERSION@")
 | 
				
			||||||
 | 
					include("${CMAKE_CURRENT_LIST_DIR}/EnTTTargets.cmake")
 | 
				
			||||||
 | 
					check_required_components("@PROJECT_NAME@")
 | 
				
			||||||
							
								
								
									
										8
									
								
								external/entt/entt/cmake/in/entt.pc.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								external/entt/entt/cmake/in/entt.pc.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					prefix=@CMAKE_INSTALL_PREFIX@
 | 
				
			||||||
 | 
					includedir=@EnTT_PKGCONFIG_INCLUDEDIR@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Name: EnTT
 | 
				
			||||||
 | 
					Description: Gaming meets modern C++
 | 
				
			||||||
 | 
					Url: https://github.com/skypjack/entt
 | 
				
			||||||
 | 
					Version: @ENTT_VERSION@
 | 
				
			||||||
 | 
					Cflags: -I${includedir}
 | 
				
			||||||
							
								
								
									
										23
									
								
								external/entt/entt/cmake/modules/JoinPaths.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								external/entt/entt/cmake/modules/JoinPaths.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					# This module provides function for joining paths
 | 
				
			||||||
 | 
					# known from most languages
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# SPDX-License-Identifier: (MIT OR CC0-1.0)
 | 
				
			||||||
 | 
					# Copyright 2020 Jan Tojnar
 | 
				
			||||||
 | 
					# https://github.com/jtojnar/cmake-snips
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Modelled after Python<6F>s os.path.join
 | 
				
			||||||
 | 
					# https://docs.python.org/3.7/library/os.path.html#os.path.join
 | 
				
			||||||
 | 
					# Windows not supported
 | 
				
			||||||
 | 
					function(join_paths joined_path first_path_segment)
 | 
				
			||||||
 | 
					    set(temp_path "${first_path_segment}")
 | 
				
			||||||
 | 
					    foreach(current_segment IN LISTS ARGN)
 | 
				
			||||||
 | 
					        if(NOT ("${current_segment}" STREQUAL ""))
 | 
				
			||||||
 | 
					            if(IS_ABSOLUTE "${current_segment}")
 | 
				
			||||||
 | 
					                set(temp_path "${current_segment}")
 | 
				
			||||||
 | 
					            else()
 | 
				
			||||||
 | 
					                set(temp_path "${temp_path}/${current_segment}")
 | 
				
			||||||
 | 
					            endif()
 | 
				
			||||||
 | 
					        endif()
 | 
				
			||||||
 | 
					    endforeach()
 | 
				
			||||||
 | 
					    set(${joined_path} "${temp_path}" PARENT_SCOPE)
 | 
				
			||||||
 | 
					endfunction()
 | 
				
			||||||
							
								
								
									
										37
									
								
								external/entt/entt/conan/build.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								external/entt/entt/conan/build.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					from cpt.packager import ConanMultiPackager
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    username = os.getenv("GITHUB_ACTOR")
 | 
				
			||||||
 | 
					    tag_version = os.getenv("GITHUB_REF")
 | 
				
			||||||
 | 
					    tag_package = os.getenv("GITHUB_REPOSITORY")
 | 
				
			||||||
 | 
					    login_username = os.getenv("CONAN_LOGIN_USERNAME")
 | 
				
			||||||
 | 
					    package_version = tag_version.replace("refs/tags/v", "")
 | 
				
			||||||
 | 
					    package_name = tag_package.replace("skypjack/", "")
 | 
				
			||||||
 | 
					    reference = "{}/{}".format(package_name, package_version)
 | 
				
			||||||
 | 
					    channel = os.getenv("CONAN_CHANNEL", "stable")
 | 
				
			||||||
 | 
					    upload = os.getenv("CONAN_UPLOAD")
 | 
				
			||||||
 | 
					    stable_branch_pattern = os.getenv("CONAN_STABLE_BRANCH_PATTERN", r"v\d+\.\d+\.\d+.*")
 | 
				
			||||||
 | 
					    test_folder = os.getenv("CPT_TEST_FOLDER", os.path.join("conan", "test_package"))
 | 
				
			||||||
 | 
					    upload_only_when_stable = os.getenv("CONAN_UPLOAD_ONLY_WHEN_STABLE", True)
 | 
				
			||||||
 | 
					    disable_shared = os.getenv("CONAN_DISABLE_SHARED_BUILD", "False")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    builder = ConanMultiPackager(username=username,
 | 
				
			||||||
 | 
					                                 reference=reference,
 | 
				
			||||||
 | 
					                                 channel=channel,
 | 
				
			||||||
 | 
					                                 login_username=login_username,
 | 
				
			||||||
 | 
					                                 upload=upload,
 | 
				
			||||||
 | 
					                                 stable_branch_pattern=stable_branch_pattern,
 | 
				
			||||||
 | 
					                                 upload_only_when_stable=upload_only_when_stable,
 | 
				
			||||||
 | 
					                                 test_folder=test_folder)
 | 
				
			||||||
 | 
					    builder.add()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    filtered_builds = []
 | 
				
			||||||
 | 
					    for settings, options, env_vars, build_requires, reference in builder.items:
 | 
				
			||||||
 | 
					        if disable_shared == "False" or not options["{}:shared".format(package_name)]:
 | 
				
			||||||
 | 
					             filtered_builds.append([settings, options, env_vars, build_requires])
 | 
				
			||||||
 | 
					    builder.builds = filtered_builds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    builder.run()
 | 
				
			||||||
							
								
								
									
										7
									
								
								external/entt/entt/conan/ci/build.sh
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								external/entt/entt/conan/ci/build.sh
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set -e
 | 
				
			||||||
 | 
					set -x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					conan user
 | 
				
			||||||
 | 
					python conan/build.py
 | 
				
			||||||
							
								
								
									
										6
									
								
								external/entt/entt/conan/ci/install.sh
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								external/entt/entt/conan/ci/install.sh
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set -e
 | 
				
			||||||
 | 
					set -x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pip install -U conan_package_tools conan
 | 
				
			||||||
							
								
								
									
										13
									
								
								external/entt/entt/conan/test_package/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								external/entt/entt/conan/test_package/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					cmake_minimum_required(VERSION 3.7.2)
 | 
				
			||||||
 | 
					project(test_package)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(CMAKE_VERBOSE_MAKEFILE TRUE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(CMAKE_CXX_STANDARD 17)
 | 
				
			||||||
 | 
					set(CMAKE_CXX_STANDARD_REQUIRED ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
 | 
				
			||||||
 | 
					conan_basic_setup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_executable(${PROJECT_NAME} test_package.cpp)
 | 
				
			||||||
 | 
					target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS})
 | 
				
			||||||
							
								
								
									
										19
									
								
								external/entt/entt/conan/test_package/conanfile.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								external/entt/entt/conan/test_package/conanfile.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from conans import ConanFile, CMake
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestPackageConan(ConanFile):
 | 
				
			||||||
 | 
					    settings = "os", "compiler", "build_type", "arch"
 | 
				
			||||||
 | 
					    generators = "cmake"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def build(self):
 | 
				
			||||||
 | 
					        cmake = CMake(self)
 | 
				
			||||||
 | 
					        cmake.configure()
 | 
				
			||||||
 | 
					        cmake.build()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test(self):
 | 
				
			||||||
 | 
					        bin_path = os.path.join("bin", "test_package")
 | 
				
			||||||
 | 
					        self.run(bin_path, run_environment=True)
 | 
				
			||||||
							
								
								
									
										56
									
								
								external/entt/entt/conan/test_package/test_package.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								external/entt/entt/conan/test_package/test_package.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					#include <entt/entt.hpp>
 | 
				
			||||||
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct position {
 | 
				
			||||||
 | 
					    float x;
 | 
				
			||||||
 | 
					    float y;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct velocity {
 | 
				
			||||||
 | 
					    float dx;
 | 
				
			||||||
 | 
					    float dy;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void update(entt::registry ®istry) {
 | 
				
			||||||
 | 
					    auto view = registry.view<position, velocity>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for(auto entity: view) {
 | 
				
			||||||
 | 
					        // gets only the components that are going to be used ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto &vel = view.get<velocity>(entity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vel.dx = 0.;
 | 
				
			||||||
 | 
					        vel.dy = 0.;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // ...
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void update(std::uint64_t dt, entt::registry ®istry) {
 | 
				
			||||||
 | 
					    registry.view<position, velocity>().each([dt](auto &pos, auto &vel) {
 | 
				
			||||||
 | 
					        // gets all the components of the view at once ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        pos.x += vel.dx * dt;
 | 
				
			||||||
 | 
					        pos.y += vel.dy * dt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // ...
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() {
 | 
				
			||||||
 | 
					    entt::registry registry;
 | 
				
			||||||
 | 
					    std::uint64_t dt = 16;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for(auto i = 0; i < 10; ++i) {
 | 
				
			||||||
 | 
					        auto entity = registry.create();
 | 
				
			||||||
 | 
					        registry.emplace<position>(entity, i * 1.f, i * 1.f);
 | 
				
			||||||
 | 
					        if(i % 2 == 0) { registry.emplace<velocity>(entity, i * .1f, i * .1f); }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    update(dt, registry);
 | 
				
			||||||
 | 
					    update(registry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return EXIT_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								external/entt/entt/conanfile.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								external/entt/entt/conanfile.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					from conans import ConanFile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class EnttConan(ConanFile):
 | 
				
			||||||
 | 
					    name = "entt"
 | 
				
			||||||
 | 
					    description = "Gaming meets modern C++ - a fast and reliable entity-component system (ECS) and much more "
 | 
				
			||||||
 | 
					    topics = ("conan," "entt", "gaming", "entity", "ecs")
 | 
				
			||||||
 | 
					    url = "https://github.com/skypjack/entt"
 | 
				
			||||||
 | 
					    homepage = url
 | 
				
			||||||
 | 
					    author = "Michele Caini <michele.caini@gmail.com>"
 | 
				
			||||||
 | 
					    license = "MIT"
 | 
				
			||||||
 | 
					    exports = ["LICENSE"]
 | 
				
			||||||
 | 
					    exports_sources = ["src/*"]
 | 
				
			||||||
 | 
					    no_copy_source = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def package(self):
 | 
				
			||||||
 | 
					        self.copy(pattern="LICENSE", dst="licenses")
 | 
				
			||||||
 | 
					        self.copy(pattern="*", dst="include", src="src", keep_path=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def package_info(self):
 | 
				
			||||||
 | 
					        if not self.in_local_cache:
 | 
				
			||||||
 | 
					            self.cpp_info.includedirs = ["src"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def package_id(self):
 | 
				
			||||||
 | 
					        self.info.header_only()
 | 
				
			||||||
							
								
								
									
										54
									
								
								external/entt/entt/docs/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								external/entt/entt/docs/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# Doxygen configuration (documentation)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FetchContent_Declare(
 | 
				
			||||||
 | 
					    doxygen-awesome-css
 | 
				
			||||||
 | 
					    GIT_REPOSITORY https://github.com/jothepro/doxygen-awesome-css
 | 
				
			||||||
 | 
					    GIT_TAG main
 | 
				
			||||||
 | 
					    GIT_SHALLOW 1
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FetchContent_GetProperties(doxygen-awesome-css)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(NOT doxygen-awesome-css_POPULATED)
 | 
				
			||||||
 | 
					    FetchContent_Populate(doxygen-awesome-css)
 | 
				
			||||||
 | 
					    set(doxygen-awesome-css_INCLUDE_DIR ${doxygen-awesome-css_SOURCE_DIR})
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(DOXY_SOURCE_DIRECTORY ${EnTT_SOURCE_DIR}/src)
 | 
				
			||||||
 | 
					set(DOXY_CSS_DIRECTORY ${doxygen-awesome-css_INCLUDE_DIR})
 | 
				
			||||||
 | 
					set(DOXY_DOCS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
 | 
				
			||||||
 | 
					set(DOXY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					configure_file(doxy.in doxy.cfg @ONLY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_custom_target(
 | 
				
			||||||
 | 
					    docs ALL
 | 
				
			||||||
 | 
					    COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.cfg
 | 
				
			||||||
 | 
					    WORKING_DIRECTORY ${EnTT_SOURCE_DIR}
 | 
				
			||||||
 | 
					    VERBATIM
 | 
				
			||||||
 | 
					    SOURCES
 | 
				
			||||||
 | 
					        dox/extra.dox
 | 
				
			||||||
 | 
					        md/config.md
 | 
				
			||||||
 | 
					        md/container.md
 | 
				
			||||||
 | 
					        md/core.md
 | 
				
			||||||
 | 
					        md/entity.md
 | 
				
			||||||
 | 
					        md/faq.md
 | 
				
			||||||
 | 
					        md/lib.md
 | 
				
			||||||
 | 
					        md/links.md
 | 
				
			||||||
 | 
					        md/locator.md
 | 
				
			||||||
 | 
					        md/meta.md
 | 
				
			||||||
 | 
					        md/poly.md
 | 
				
			||||||
 | 
					        md/process.md
 | 
				
			||||||
 | 
					        md/reference.md
 | 
				
			||||||
 | 
					        md/resource.md
 | 
				
			||||||
 | 
					        md/signal.md
 | 
				
			||||||
 | 
					        md/unreal.md
 | 
				
			||||||
 | 
					        doxy.in
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install(
 | 
				
			||||||
 | 
					    DIRECTORY ${DOXY_OUTPUT_DIRECTORY}/html
 | 
				
			||||||
 | 
					    DESTINATION share/${PROJECT_NAME}-${PROJECT_VERSION}/
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										5
									
								
								external/entt/entt/docs/dox/extra.dox
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								external/entt/entt/docs/dox/extra.dox
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @namespace entt
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @brief `EnTT` default namespace.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
							
								
								
									
										2726
									
								
								external/entt/entt/docs/doxy.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2726
									
								
								external/entt/entt/docs/doxy.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										120
									
								
								external/entt/entt/docs/md/config.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								external/entt/entt/docs/md/config.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,120 @@
 | 
				
			|||||||
 | 
					# Crash Course: configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Introduction](#introduction)
 | 
				
			||||||
 | 
					* [Definitions](#definitions)
 | 
				
			||||||
 | 
					  * [ENTT_NOEXCEPTION](#entt_noexception)
 | 
				
			||||||
 | 
					  * [ENTT_USE_ATOMIC](#entt_use_atomic)
 | 
				
			||||||
 | 
					  * [ENTT_ID_TYPE](#entt_id_type)
 | 
				
			||||||
 | 
					  * [ENTT_SPARSE_PAGE](#entt_sparse_page)
 | 
				
			||||||
 | 
					  * [ENTT_PACKED_PAGE](#entt_packed_page)
 | 
				
			||||||
 | 
					  * [ENTT_ASSERT](#entt_assert)
 | 
				
			||||||
 | 
					    * [ENTT_ASSERT_CONSTEXPR](#entt_assert_constexpr)
 | 
				
			||||||
 | 
					    * [ENTT_DISABLE_ASSERT](#entt_disable_assert)
 | 
				
			||||||
 | 
					  * [ENTT_NO_ETO](#entt_no_eto)
 | 
				
			||||||
 | 
					  * [ENTT_STANDARD_CPP](#entt_standard_cpp)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` has become almost completely customizable over time, in many
 | 
				
			||||||
 | 
					respects. These variables are just one of the many ways to customize how it
 | 
				
			||||||
 | 
					works.<br/>
 | 
				
			||||||
 | 
					In the vast majority of cases, users will have no interest in changing the
 | 
				
			||||||
 | 
					default parameters. For all other cases, the list of possible configurations
 | 
				
			||||||
 | 
					with which it's possible to adjust the behavior of the library at runtime can be
 | 
				
			||||||
 | 
					found below.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Definitions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All options are intended as parameters to the compiler (or user-defined macros
 | 
				
			||||||
 | 
					within the compilation units, if preferred).<br/>
 | 
				
			||||||
 | 
					Each parameter can result in internal library definitions. It's not recommended
 | 
				
			||||||
 | 
					to try to also modify these definitions, since there is no guarantee that they
 | 
				
			||||||
 | 
					will remain stable over time unlike the options below.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## ENTT_NOEXCEPTION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Define this variable without assigning any value to it to turn off exception
 | 
				
			||||||
 | 
					handling in `EnTT`.<br/>
 | 
				
			||||||
 | 
					This is roughly equivalent to setting the compiler flag `-fno-exceptions` but is
 | 
				
			||||||
 | 
					also limited to this library only.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## ENTT_USE_ATOMIC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In general, `EnTT` doesn't offer primitives to support multi-threading. Many of
 | 
				
			||||||
 | 
					the features can be split over multiple threads without any explicit control and
 | 
				
			||||||
 | 
					the user is the one who knows if a synchronization point is required.<br/>
 | 
				
			||||||
 | 
					However, some features aren't easily accessible to users and are made
 | 
				
			||||||
 | 
					thread-safe by means of this definition.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## ENTT_ID_TYPE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`entt::id_type` is directly controlled by this definition and widely used within
 | 
				
			||||||
 | 
					the library.<br/>
 | 
				
			||||||
 | 
					By default, its type is `std::uint32_t`. However, users can define a different
 | 
				
			||||||
 | 
					default type if necessary.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## ENTT_SPARSE_PAGE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's known that the ECS module of `EnTT` is based on _sparse sets_. What is less
 | 
				
			||||||
 | 
					known perhaps is that the sparse arrays are paged to reduce memory usage.<br/>
 | 
				
			||||||
 | 
					Default size of pages (that is, the number of elements they contain) is 4096 but
 | 
				
			||||||
 | 
					users can adjust it if appropriate. In all case, the chosen value **must** be a
 | 
				
			||||||
 | 
					power of 2.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## ENTT_PACKED_PAGE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As it happens with sparse arrays, packed arrays are also paginated. However, in
 | 
				
			||||||
 | 
					this case the aim isn't to reduce memory usage but to have pointer stability
 | 
				
			||||||
 | 
					upon component creation.<br/>
 | 
				
			||||||
 | 
					Default size of pages (that is, the number of elements they contain) is 1024 but
 | 
				
			||||||
 | 
					users can adjust it if appropriate. In all case, the chosen value **must** be a
 | 
				
			||||||
 | 
					power of 2.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## ENTT_ASSERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For performance reasons, `EnTT` doesn't use exceptions or any other control
 | 
				
			||||||
 | 
					structures. In fact, it offers many features that result in undefined behavior
 | 
				
			||||||
 | 
					if not used correctly.<br/>
 | 
				
			||||||
 | 
					To get around this, the library relies on a lot of asserts for the purpose of
 | 
				
			||||||
 | 
					detecting errors in debug builds. By default, it uses `assert` internally. Users
 | 
				
			||||||
 | 
					are allowed to overwrite its behavior by setting this variable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### ENTT_ASSERT_CONSTEXPR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usually, an assert within a `constexpr` function isn't a big deal. However, in
 | 
				
			||||||
 | 
					case of extreme customizations, it might be useful to differentiate.<br/>
 | 
				
			||||||
 | 
					For this purpose, `EnTT` introduces an admittedly badly named variable to make
 | 
				
			||||||
 | 
					the job easier in this regard. By default, this variable forwards its arguments
 | 
				
			||||||
 | 
					to `ENTT_ASSERT`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### ENTT_DISABLE_ASSERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Assertions may in turn affect performance to an extent when enabled. Whether
 | 
				
			||||||
 | 
					`ENTT_ASSERT` and `ENTT_ASSERT_CONSTEXPR` are redefined or not, all asserts can
 | 
				
			||||||
 | 
					be disabled at once by means of this definition.<br/>
 | 
				
			||||||
 | 
					Note that `ENTT_DISABLE_ASSERT` takes precedence over the redefinition of the
 | 
				
			||||||
 | 
					other variables and is therefore meant to disable all controls no matter what.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## ENTT_NO_ETO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In order to reduce memory consumption and increase performance, empty types are
 | 
				
			||||||
 | 
					never instantiated nor stored by the ECS module of `EnTT`.<br/>
 | 
				
			||||||
 | 
					Use this variable to treat these types like all others and therefore to create a
 | 
				
			||||||
 | 
					dedicated storage for them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## ENTT_STANDARD_CPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` mixes non-standard language features with others that are perfectly
 | 
				
			||||||
 | 
					compliant to offer some of its functionalities.<br/>
 | 
				
			||||||
 | 
					This definition prevents the library from using non-standard techniques, that
 | 
				
			||||||
 | 
					is, functionalities that aren't fully compliant with the standard C++.<br/>
 | 
				
			||||||
 | 
					While there are no known portability issues at the time of this writing, this
 | 
				
			||||||
 | 
					should make the library fully portable anyway if needed.
 | 
				
			||||||
							
								
								
									
										66
									
								
								external/entt/entt/docs/md/container.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								external/entt/entt/docs/md/container.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					# Crash Course: containers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Introduction](#introduction)
 | 
				
			||||||
 | 
					* [Containers](#containers)
 | 
				
			||||||
 | 
					  * [Dense map](#dense-map)
 | 
				
			||||||
 | 
					  * [Dense set](#dense-set)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The standard C++ library offers a wide range of containers and it's really
 | 
				
			||||||
 | 
					difficult to do better (although it's very easy to do worse, as many examples
 | 
				
			||||||
 | 
					available online demonstrate).<br/>
 | 
				
			||||||
 | 
					`EnTT` doesn't try in any way to replace what is offered by the standard. Quite
 | 
				
			||||||
 | 
					the opposite, given the widespread use that is made of standard containers.<br/>
 | 
				
			||||||
 | 
					However, the library also tries to fill a gap in features and functionalities by
 | 
				
			||||||
 | 
					making available some containers initially developed for internal use.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This section of the library is likely to grow larger over time. However, for the
 | 
				
			||||||
 | 
					moment it's quite small and mainly aimed at satisfying some internal needs.<br/>
 | 
				
			||||||
 | 
					For all containers made available, full test coverage and stability over time is
 | 
				
			||||||
 | 
					guaranteed as usual.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Containers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Dense map
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The dense map made available in `EnTT` is a hash map that aims to return a
 | 
				
			||||||
 | 
					packed array of elements, so as to reduce the number of jumps in memory during
 | 
				
			||||||
 | 
					iterations.<br/>
 | 
				
			||||||
 | 
					The implementation is based on _sparse sets_ and each bucket is identified by an
 | 
				
			||||||
 | 
					implicit list within the packed array itself.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The interface is very close to its counterpart in the standard library, that is,
 | 
				
			||||||
 | 
					the `std::unordered_map` class.<br/>
 | 
				
			||||||
 | 
					However, both local and non-local iterators returned by a dense map belong to
 | 
				
			||||||
 | 
					the input iterator category although they respectively model the concepts of a
 | 
				
			||||||
 | 
					_forward iterator_ type and a _random access iterator_ type.<br/>
 | 
				
			||||||
 | 
					This is because they return a pair of references rather than a reference to a
 | 
				
			||||||
 | 
					pair. In other words, dense maps return a so called _proxy iterator_ the value
 | 
				
			||||||
 | 
					type of which is:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `std::pair<const Key &, Type &>` for non-const iterator types.
 | 
				
			||||||
 | 
					* `std::pair<const Key &, const Type &>` for const iterator types.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is quite different from what any standard library map returns and should be
 | 
				
			||||||
 | 
					taken into account when looking for a drop-in replacement.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Dense set
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The dense set made available in `EnTT` is a hash set that aims to return a
 | 
				
			||||||
 | 
					packed array of elements, so as to reduce the number of jumps in memory during
 | 
				
			||||||
 | 
					iterations.<br/>
 | 
				
			||||||
 | 
					The implementation is based on _sparse sets_ and each bucket is identified by an
 | 
				
			||||||
 | 
					implicit list within the packed array itself.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The interface is in all respects similar to its counterpart in the standard
 | 
				
			||||||
 | 
					library, that is, the `std::unordered_set` class.<br/>
 | 
				
			||||||
 | 
					Therefore, there is no need to go into the API description.
 | 
				
			||||||
							
								
								
									
										986
									
								
								external/entt/entt/docs/md/core.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										986
									
								
								external/entt/entt/docs/md/core.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,986 @@
 | 
				
			|||||||
 | 
					# Crash Course: core functionalities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Introduction](#introduction)
 | 
				
			||||||
 | 
					* [Any as in any type](#any-as-in-any-type)
 | 
				
			||||||
 | 
					  * [Small buffer optimization](#small-buffer-optimization)
 | 
				
			||||||
 | 
					  * [Alignment requirement](#alignment-requirement)
 | 
				
			||||||
 | 
					* [Compressed pair](#compressed-pair)
 | 
				
			||||||
 | 
					* [Enum as bitmask](#enum-as-bitmask)
 | 
				
			||||||
 | 
					* [Hashed strings](#hashed-strings)
 | 
				
			||||||
 | 
					  * [Wide characters](wide-characters)
 | 
				
			||||||
 | 
					  * [Conflicts](#conflicts)
 | 
				
			||||||
 | 
					* [Iterators](#iterators)
 | 
				
			||||||
 | 
					  * [Input iterator pointer](#input-iterator-pointer)
 | 
				
			||||||
 | 
					  * [Iota iterator](#iota-iterator)
 | 
				
			||||||
 | 
					  * [Iterable adaptor](#iterable-adaptor)
 | 
				
			||||||
 | 
					* [Memory](#memory)
 | 
				
			||||||
 | 
					  * [Power of two and fast modulus](#power-of-two-and-fast-modulus)
 | 
				
			||||||
 | 
					  * [Allocator aware unique pointers](#allocator-aware-unique-pointers)
 | 
				
			||||||
 | 
					* [Monostate](#monostate)
 | 
				
			||||||
 | 
					* [Type support](#type-support)
 | 
				
			||||||
 | 
					  * [Built-in RTTI support](#built-in-rtti-support)
 | 
				
			||||||
 | 
					    * [Type info](#type-info)
 | 
				
			||||||
 | 
					    * [Almost unique identifiers](#almost-unique-identifiers)
 | 
				
			||||||
 | 
					  * [Type traits](#type-traits)
 | 
				
			||||||
 | 
					    * [Size of](#size-of)
 | 
				
			||||||
 | 
					    * [Is applicable](#is-applicable)
 | 
				
			||||||
 | 
					    * [Constness as](#constness-as)
 | 
				
			||||||
 | 
					    * [Member class type](#member-class-type)
 | 
				
			||||||
 | 
					    * [N-th argument](#n-th-argument)
 | 
				
			||||||
 | 
					    * [Integral constant](#integral-constant)
 | 
				
			||||||
 | 
					    * [Tag](#tag)
 | 
				
			||||||
 | 
					    * [Type list and value list](#type-list-and-value-list)
 | 
				
			||||||
 | 
					* [Unique sequential identifiers](#unique-sequential-identifiers)
 | 
				
			||||||
 | 
					  * [Compile-time generator](#compile-time-generator)
 | 
				
			||||||
 | 
					  * [Runtime generator](#runtime-generator)
 | 
				
			||||||
 | 
					* [Utilities](#utilities)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` comes with a bunch of core functionalities mostly used by the other parts
 | 
				
			||||||
 | 
					of the library.<br/>
 | 
				
			||||||
 | 
					Many of these tools are also useful in everyday work. Therefore, it's worth
 | 
				
			||||||
 | 
					describing them so as not to reinvent the wheel in case of need.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Any as in any type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` offers its own `any` type. It may seem redundant considering that C++17
 | 
				
			||||||
 | 
					introduced `std::any`, but it is not (hopefully).<br/>
 | 
				
			||||||
 | 
					First of all, the _type_ returned by an `std::any` is a const reference to an
 | 
				
			||||||
 | 
					`std::type_info`, an implementation defined class that's not something everyone
 | 
				
			||||||
 | 
					wants to see in a software. Furthermore, there is no way to bind it to the type
 | 
				
			||||||
 | 
					system of the library and therefore with its integrated RTTI support.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `any` API is very similar to that of its most famous counterpart, mainly
 | 
				
			||||||
 | 
					because this class serves the same purpose of being an opaque container for any
 | 
				
			||||||
 | 
					type of value.<br/>
 | 
				
			||||||
 | 
					Instances also minimize the number of allocations by relying on a well known
 | 
				
			||||||
 | 
					technique called _small buffer optimization_ and a fake vtable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Creating an object of the `any` type, whether empty or not, is trivial:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// an empty container
 | 
				
			||||||
 | 
					entt::any empty{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// a container for an int
 | 
				
			||||||
 | 
					entt::any any{0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// in place construction
 | 
				
			||||||
 | 
					entt::any in_place{std::in_place_type<int>, 42};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Alternatively, the `make_any` function serves the same purpose but requires to
 | 
				
			||||||
 | 
					always be explicit about the type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::any any = entt::make_any<int>(42);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In both cases, the `any` class takes the burden of destroying the contained
 | 
				
			||||||
 | 
					element when required, regardless of the storage strategy used for the specific
 | 
				
			||||||
 | 
					object.<br/>
 | 
				
			||||||
 | 
					Furthermore, an instance of `any` isn't tied to an actual type. Therefore, the
 | 
				
			||||||
 | 
					wrapper is reconfigured when it's assigned a new object of a type other than
 | 
				
			||||||
 | 
					the one it contains.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There is also a way to directly assign a value to the variable contained by an
 | 
				
			||||||
 | 
					`entt::any`, without necessarily replacing it. This is especially useful when
 | 
				
			||||||
 | 
					the object is used in _aliasing mode_, as described below:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::any any{42};
 | 
				
			||||||
 | 
					entt::any value{3};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// assigns by copy
 | 
				
			||||||
 | 
					any.assign(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// assigns by move
 | 
				
			||||||
 | 
					any.assign(std::move(value));
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `any` class performs a check on the type information and whether or not the
 | 
				
			||||||
 | 
					original type was copy or move assignable, as appropriate.<br/>
 | 
				
			||||||
 | 
					In all cases, the `assign` function returns a boolean value that is true in case
 | 
				
			||||||
 | 
					of success and false otherwise.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When in doubt about the type of object contained, the `type` member function
 | 
				
			||||||
 | 
					returns a const reference to the `type_info` associated with its element, or
 | 
				
			||||||
 | 
					`type_id<void>()` if the container is empty.<br/>
 | 
				
			||||||
 | 
					The type is also used internally when comparing two `any` objects:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					if(any == empty) { /* ... */ }
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this case, before proceeding with a comparison, it's verified that the _type_
 | 
				
			||||||
 | 
					of the two objects is actually the same.<br/>
 | 
				
			||||||
 | 
					Refer to the `EnTT` type system documentation for more details about how
 | 
				
			||||||
 | 
					`type_info` works and the possible risks of a comparison.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A particularly interesting feature of this class is that it can also be used as
 | 
				
			||||||
 | 
					an opaque container for const and non-const references:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					int value = 42;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					entt::any any{std::in_place_type<int &>(value)};
 | 
				
			||||||
 | 
					entt::any cany = entt::make_any<const int &>(value);
 | 
				
			||||||
 | 
					entt::any fwd = entt::forward_as_any(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					any.emplace<const int &>(value);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In other words, whenever `any` is explicitly told to construct an _alias_, it
 | 
				
			||||||
 | 
					acts as a pointer to the original instance rather than making a copy of it or
 | 
				
			||||||
 | 
					moving it internally. The contained object is never destroyed and users must
 | 
				
			||||||
 | 
					ensure that its lifetime exceeds that of the container.<br/>
 | 
				
			||||||
 | 
					Similarly, it's possible to create non-owning copies of `any` from an existing
 | 
				
			||||||
 | 
					object:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// aliasing constructor
 | 
				
			||||||
 | 
					entt::any ref = other.as_ref();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this case, it doesn't matter if the original container actually holds an
 | 
				
			||||||
 | 
					object or is as a reference for unmanaged elements already. The new instance
 | 
				
			||||||
 | 
					thus created doesn't create copies and only serves as a reference for the
 | 
				
			||||||
 | 
					original item.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's worth mentioning that, while everything works transparently when it comes
 | 
				
			||||||
 | 
					to non-const references, there are some exceptions when it comes to const
 | 
				
			||||||
 | 
					references.<br/>
 | 
				
			||||||
 | 
					In particular, the `data` member function invoked on a non-const instance of
 | 
				
			||||||
 | 
					`any` that wraps a const reference returns a null pointer in all cases.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To cast an instance of `any` to a type, the library offers a set of `any_cast`
 | 
				
			||||||
 | 
					functions in all respects similar to their most famous counterparts.<br/>
 | 
				
			||||||
 | 
					The only difference is that, in the case of `EnTT`, they won't raise exceptions
 | 
				
			||||||
 | 
					but will only trigger an assert in debug mode, otherwise resulting in undefined
 | 
				
			||||||
 | 
					behavior in case of misuse in release mode.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Small buffer optimization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `any` class uses a technique called _small buffer optimization_ to reduce
 | 
				
			||||||
 | 
					the number of allocations where possible.<br/>
 | 
				
			||||||
 | 
					The default reserved size for an instance of `any` is `sizeof(double[2])`.
 | 
				
			||||||
 | 
					However, this is also configurable if needed. In fact, `any` is defined as an
 | 
				
			||||||
 | 
					alias for `basic_any<Len>`, where `Len` is the size above.<br/>
 | 
				
			||||||
 | 
					Users can easily set a custom size or define their own aliases:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					using my_any = entt::basic_any<sizeof(double[4])>;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This feature, in addition to allowing the choice of a size that best suits the
 | 
				
			||||||
 | 
					needs of an application, also offers the possibility of forcing dynamic creation
 | 
				
			||||||
 | 
					of objects during construction.<br/>
 | 
				
			||||||
 | 
					In other terms, if the size is 0, `any` suppresses the small buffer optimization
 | 
				
			||||||
 | 
					and always dynamically allocates objects (except for aliasing cases).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Alignment requirement
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The alignment requirement is optional and by default the most stringent (the
 | 
				
			||||||
 | 
					largest) for any object whose size is at most equal to the one provided.<br/>
 | 
				
			||||||
 | 
					It's provided as an optional second parameter following the desired size for the
 | 
				
			||||||
 | 
					internal storage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					using my_any = entt::basic_any<sizeof(double[4]), alignof(double[4])>;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `basic_any` class template inspects the alignment requirements in each case,
 | 
				
			||||||
 | 
					even when not provided and may decide not to use the small buffer optimization
 | 
				
			||||||
 | 
					in order to meet them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Compressed pair
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Primarily designed for internal use and far from being feature complete, the
 | 
				
			||||||
 | 
					`compressed_pair` class does exactly what it promises: it tries to reduce the
 | 
				
			||||||
 | 
					size of a pair by exploiting _Empty Base Class Optimization_ (or _EBCO_).<br/>
 | 
				
			||||||
 | 
					This class **is not** a drop-in replacement for `std::pair`. However, it offers
 | 
				
			||||||
 | 
					enough functionalities to be a good alternative for when reducing memory usage
 | 
				
			||||||
 | 
					is more important than having some cool and probably useless feature.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Although the API is very close to that of `std::pair` (apart from the fact that
 | 
				
			||||||
 | 
					the template parameters are inferred from the constructor and therefore there is
 | 
				
			||||||
 | 
					no `entt::make_compressed_pair`), the major difference is that `first` and
 | 
				
			||||||
 | 
					`second` are functions for implementation requirements:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::compressed_pair pair{0, 3.};
 | 
				
			||||||
 | 
					pair.first() = 42;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There isn't much to describe then. It's recommended to rely on documentation and
 | 
				
			||||||
 | 
					intuition. At the end of the day, it's just a pair and nothing more.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Enum as bitmask
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sometimes it's useful to be able to use enums as bitmasks. However, enum classes
 | 
				
			||||||
 | 
					aren't really suitable for the purpose. Main problem is that they don't convert
 | 
				
			||||||
 | 
					implicitly to their underlying type.<br/>
 | 
				
			||||||
 | 
					The choice is then between using old-fashioned enums (with all their problems
 | 
				
			||||||
 | 
					that I don't want to discuss here) or writing _ugly_ code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Fortunately, there is also a third way: adding enough operators in the global
 | 
				
			||||||
 | 
					scope to treat enum classes as bitmasks transparently.<br/>
 | 
				
			||||||
 | 
					The ultimate goal is to write code like the following (or maybe something more
 | 
				
			||||||
 | 
					meaningful, but this should give a grasp and remain simple at the same time):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					enum class my_flag {
 | 
				
			||||||
 | 
					    unknown = 0x01,
 | 
				
			||||||
 | 
					    enabled = 0x02,
 | 
				
			||||||
 | 
					    disabled = 0x04
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const my_flag flags = my_flag::enabled;
 | 
				
			||||||
 | 
					const bool is_enabled = !!(flags & my_flag::enabled);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The problem with adding all operators to the global scope is that these come
 | 
				
			||||||
 | 
					into play even when not required, with the risk of introducing errors that are
 | 
				
			||||||
 | 
					difficult to deal with.<br/>
 | 
				
			||||||
 | 
					However, C++ offers enough tools to get around this problem. In particular, the
 | 
				
			||||||
 | 
					library requires users to register the enum classes for which bitmask support
 | 
				
			||||||
 | 
					should be enabled:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct entt::enum_as_bitmask<my_flag>
 | 
				
			||||||
 | 
					    : std::true_type
 | 
				
			||||||
 | 
					{};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is handy when dealing with enum classes defined by third party libraries
 | 
				
			||||||
 | 
					and over which the user has no control. However, it's also verbose and can be
 | 
				
			||||||
 | 
					avoided by adding a specific value to the enum class itself:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					enum class my_flag {
 | 
				
			||||||
 | 
					    unknown = 0x01,
 | 
				
			||||||
 | 
					    enabled = 0x02,
 | 
				
			||||||
 | 
					    disabled = 0x04,
 | 
				
			||||||
 | 
					    _entt_enum_as_bitmask
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this case, there is no need to specialize the `enum_as_bitmask` traits, since
 | 
				
			||||||
 | 
					`EnTT` automatically detects the flag and enables the bitmask support.<br/>
 | 
				
			||||||
 | 
					Once the enum class is registered (in one way or the other), the most common
 | 
				
			||||||
 | 
					operators such as `&`, `|` but also `&=` and `|=` are available for use.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Refer to the official documentation for the full list of operators.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Hashed strings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hashed strings are human-readable identifiers in the codebase that turn into
 | 
				
			||||||
 | 
					numeric values at runtime, thus without affecting performance.<br/>
 | 
				
			||||||
 | 
					The class has an implicit `constexpr` constructor that chews a bunch of
 | 
				
			||||||
 | 
					characters. Once created, one can get the original string by means of the `data`
 | 
				
			||||||
 | 
					member function or convert the instance into a number.<br/>
 | 
				
			||||||
 | 
					A hashed string is well suited wherever a constant expression is required. No
 | 
				
			||||||
 | 
					_string-to-number_ conversion will take place at runtime if used carefully.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example of use:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					auto load(entt::hashed_string::hash_type resource) {
 | 
				
			||||||
 | 
					    // uses the numeric representation of the resource to load and return it
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					auto resource = load(entt::hashed_string{"gui/background"});
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There is also a _user defined literal_ dedicated to hashed strings to make them
 | 
				
			||||||
 | 
					more _user-friendly_:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					using namespace entt::literals;
 | 
				
			||||||
 | 
					constexpr auto str = "text"_hs;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					User defined literals in `EnTT` are enclosed in the `entt::literals` namespace.
 | 
				
			||||||
 | 
					Therefore, the entire namespace or selectively the literal of interest must be
 | 
				
			||||||
 | 
					explicitly included before each use, a bit like `std::literals`.<br/>
 | 
				
			||||||
 | 
					The class also offers the necessary functionalities to create hashed strings at
 | 
				
			||||||
 | 
					runtime:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					std::string orig{"text"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// create a full-featured hashed string...
 | 
				
			||||||
 | 
					entt::hashed_string str{orig.c_str()};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ... or compute only the unique identifier
 | 
				
			||||||
 | 
					const auto hash = entt::hashed_string::value(orig.c_str());
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This possibility shouldn't be exploited in tight loops, since the computation
 | 
				
			||||||
 | 
					takes place at runtime and no longer at compile-time. It could therefore affect
 | 
				
			||||||
 | 
					performance to some degrees.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Wide characters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `hashed_string` class is an alias  for `basic_hashed_string<char>`. To use
 | 
				
			||||||
 | 
					the C++ type for wide character representations, there exists also the alias
 | 
				
			||||||
 | 
					`hashed_wstring` for `basic_hashed_string<wchar_t>`.<br/>
 | 
				
			||||||
 | 
					In this case, the user defined literal to use to create hashed strings on the
 | 
				
			||||||
 | 
					fly is `_hws`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					constexpr auto str = L"text"_hws;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The hash type of `hashed_wstring` is the same as its counterpart.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Conflicts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The hashed string class uses FNV-1a internally to hash strings. Because of the
 | 
				
			||||||
 | 
					_pigeonhole principle_, conflicts are possible. This is a fact.<br/>
 | 
				
			||||||
 | 
					There is no silver bullet to solve the problem of conflicts when dealing with
 | 
				
			||||||
 | 
					hashing functions. In this case, the best solution is likely to give up. That's
 | 
				
			||||||
 | 
					all.<br/>
 | 
				
			||||||
 | 
					After all, human-readable unique identifiers aren't something strictly defined
 | 
				
			||||||
 | 
					and over which users have not the control. Choosing a slightly different
 | 
				
			||||||
 | 
					identifier is probably the best solution to make the conflict disappear in this
 | 
				
			||||||
 | 
					case.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Iterators
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Writing and working with iterators isn't always easy. More often than not it
 | 
				
			||||||
 | 
					also leads to duplicated code.<br/>
 | 
				
			||||||
 | 
					`EnTT` tries to overcome this problem by offering some utilities designed to
 | 
				
			||||||
 | 
					make this hard work easier.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Input iterator pointer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When writing an input iterator that returns in-place constructed values if
 | 
				
			||||||
 | 
					dereferenced, it's not always straightforward to figure out what `value_type` is
 | 
				
			||||||
 | 
					and how to make it behave like a full-fledged pointer.<br/>
 | 
				
			||||||
 | 
					Conversely, it would be very useful to have an `operator->` available on the
 | 
				
			||||||
 | 
					iterator itself that always works without too much complexity.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The input iterator pointer is meant for this. It's a small class that wraps the
 | 
				
			||||||
 | 
					in-place constructed value and adds some functions on top of it to make it
 | 
				
			||||||
 | 
					suitable for use with input iterators: 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct iterator_type {
 | 
				
			||||||
 | 
					    using value_type = std::pair<first_type, second_type>;
 | 
				
			||||||
 | 
					    using pointer = input_iterator_pointer<value_type>;
 | 
				
			||||||
 | 
					    using reference = value_type;
 | 
				
			||||||
 | 
					    using difference_type = std::ptrdiff_t;
 | 
				
			||||||
 | 
					    using iterator_category = std::input_iterator_tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The library makes extensive use of this class internally. In many cases, the
 | 
				
			||||||
 | 
					`value_type` of the returned iterators is just an input iterator pointer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Iota iterator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Waiting for C++20, this iterator accepts an integral value and returns all
 | 
				
			||||||
 | 
					elements in a certain range:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::iota_iterator first{0};
 | 
				
			||||||
 | 
					entt::iota_iterator last{100};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for(; first != last; ++first) {
 | 
				
			||||||
 | 
					    int value = *first;
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In the future, views will replace this class. Meanwhile, the library makes some
 | 
				
			||||||
 | 
					interesting uses of it when a range of integral values is to be returned to the
 | 
				
			||||||
 | 
					user.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Iterable adaptor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Typically, a container class provides `begin` and `end` member functions (with
 | 
				
			||||||
 | 
					their const counterparts) for iteration.<br/>
 | 
				
			||||||
 | 
					However, it can happen that a class offers multiple iteration methods or allows
 | 
				
			||||||
 | 
					users to iterate different sets of _elements_.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The iterable adaptor is a utility class that makes it easier to use and access
 | 
				
			||||||
 | 
					data in this case.<br/>
 | 
				
			||||||
 | 
					It accepts a couple of iterators (or an iterator and a sentinel) and offers an
 | 
				
			||||||
 | 
					_iterable_ object with all the expected methods like `begin`, `end` and whatnot.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The library uses this class extensively.<br/>
 | 
				
			||||||
 | 
					Think for example of views, which can be iterated to access entities but also
 | 
				
			||||||
 | 
					offer a method of obtaining an iterable object that returns tuples of entities
 | 
				
			||||||
 | 
					and components at once.<br/>
 | 
				
			||||||
 | 
					Another example is the registry class which allows users to iterate its storage
 | 
				
			||||||
 | 
					by returning an iterable object for the purpose.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Memory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There are a handful of tools within `EnTT` to interact with memory in one way or
 | 
				
			||||||
 | 
					another.<br/>
 | 
				
			||||||
 | 
					Some are geared towards simplifying the implementation of (internal or external)
 | 
				
			||||||
 | 
					allocator aware containers. Others are designed to help the developer with
 | 
				
			||||||
 | 
					everyday problems.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The former are very specific and for niche problems. These are tools designed to
 | 
				
			||||||
 | 
					unwrap fancy or plain pointers (`to_address`) or to help forget the meaning of
 | 
				
			||||||
 | 
					acronyms like _POCCA_, _POCMA_ or _POCS_.<br/>
 | 
				
			||||||
 | 
					I won't describe them here in detail. Instead, I recommend reading the inline
 | 
				
			||||||
 | 
					documentation to those interested in the subject.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Power of two and fast modulus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Finding out if a number is a power of two (`is_power_of_two`) or what the next
 | 
				
			||||||
 | 
					power of two is given a random value (`next_power_of_two`) is very useful at
 | 
				
			||||||
 | 
					times.<br/>
 | 
				
			||||||
 | 
					For example, it helps to allocate memory in pages having a size suitable for the
 | 
				
			||||||
 | 
					fast modulus:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					const std::size_t result = entt::fast_mod(value, modulus);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Where `modulus` is necessarily a power of two. Perhaps not everyone knows that
 | 
				
			||||||
 | 
					this type of operation is far superior in terms of performance to the basic
 | 
				
			||||||
 | 
					modulus and for this reason preferred in many areas.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Allocator aware unique pointers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A nasty thing in C++ (at least up to C++20) is the fact that shared pointers
 | 
				
			||||||
 | 
					support allocators while unique pointers don't.<br/>
 | 
				
			||||||
 | 
					There is a proposal at the moment that also shows (among the other things) how
 | 
				
			||||||
 | 
					this can be implemented without any compiler support.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `allocate_unique` function follows this proposal, making a virtue out of
 | 
				
			||||||
 | 
					necessity:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					std::unique_ptr<my_type, entt::allocation_deleter<my_type>> ptr = entt::allocate_unique<my_type>(allocator, arguments);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Although the internal implementation is slightly different from what is proposed
 | 
				
			||||||
 | 
					for the standard, this function offers an API that is a drop-in replacement for
 | 
				
			||||||
 | 
					the same feature.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Monostate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The monostate pattern is often presented as an alternative to a singleton based
 | 
				
			||||||
 | 
					configuration system.<br/>
 | 
				
			||||||
 | 
					This is exactly its purpose in `EnTT`. Moreover, this implementation is thread
 | 
				
			||||||
 | 
					safe by design (hopefully).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Keys are integral values (easily obtained by hashed strings), values are basic
 | 
				
			||||||
 | 
					types like `int`s or `bool`s. Values of different types can be associated with
 | 
				
			||||||
 | 
					each key, even more than one at a time.<br/>
 | 
				
			||||||
 | 
					Because of this, one should pay attention to use the same type both during an
 | 
				
			||||||
 | 
					assignment and when trying to read back the data. Otherwise, there is the risk
 | 
				
			||||||
 | 
					to incur in unexpected results.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example of use:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::monostate<entt::hashed_string{"mykey"}>{} = true;
 | 
				
			||||||
 | 
					entt::monostate<"mykey"_hs>{} = 42;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const bool b = entt::monostate<"mykey"_hs>{};
 | 
				
			||||||
 | 
					const int i = entt::monostate<entt::hashed_string{"mykey"}>{};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Type support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` provides some basic information about types of all kinds.<br/>
 | 
				
			||||||
 | 
					It also offers additional features that are not yet available in the standard
 | 
				
			||||||
 | 
					library or that will never be.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Built-in RTTI support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Runtime type identification support (or RTTI) is one of the most frequently
 | 
				
			||||||
 | 
					disabled features in the C++ world, especially in the gaming sector. Regardless
 | 
				
			||||||
 | 
					of the reasons for this, it's often a shame not to be able to rely on opaque
 | 
				
			||||||
 | 
					type information at runtime.<br/>
 | 
				
			||||||
 | 
					The library tries to fill this gap by offering a built-in system that doesn't
 | 
				
			||||||
 | 
					serve as a replacement but comes very close to being one and offers similar
 | 
				
			||||||
 | 
					information to that provided by its counterpart.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Basically, the whole system relies on a handful of classes. In particular:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The unique sequential identifier associated with a given type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto index = entt::type_index<a_type>::value();
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The returned value isn't guaranteed to be stable across different runs.<br/>
 | 
				
			||||||
 | 
					  However, it can be very useful as index in associative and unordered
 | 
				
			||||||
 | 
					  associative containers or for positional accesses in a vector or an array.
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  An external generator can also be used if needed. In fact, `type_index` can be
 | 
				
			||||||
 | 
					  specialized by type and is also _sfinae-friendly_ in order to allow more
 | 
				
			||||||
 | 
					  refined specializations such as:
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  template<typename Type>
 | 
				
			||||||
 | 
					  struct entt::type_index<Type, std::void_d<decltype(Type::index())>> {
 | 
				
			||||||
 | 
					      static entt::id_type value() noexcept {
 | 
				
			||||||
 | 
					          return Type::index();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  Indexes **must** be sequentially generated in this case.<br/>
 | 
				
			||||||
 | 
					  The tool is widely used within `EnTT`. Generating indices not sequentially
 | 
				
			||||||
 | 
					  would break an assumption and would likely lead to undesired behaviors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The hash value associated with a given type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto hash = entt::type_hash<a_type>::value();
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  In general, the `value` function exposed by `type_hash` is also `constexpr`
 | 
				
			||||||
 | 
					  but this isn't guaranteed for all compilers and platforms (although it's valid
 | 
				
			||||||
 | 
					  with the most well-known and popular ones).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This function **can** use non-standard features of the language for its own
 | 
				
			||||||
 | 
					  purposes. This makes it possible to provide compile-time identifiers that
 | 
				
			||||||
 | 
					  remain stable across different runs.<br/>
 | 
				
			||||||
 | 
					  Users can prevent the library from using these features by means of the
 | 
				
			||||||
 | 
					  `ENTT_STANDARD_CPP` definition. In this case, there is no guarantee that
 | 
				
			||||||
 | 
					  identifiers remain stable across executions. Moreover, they are generated
 | 
				
			||||||
 | 
					  at runtime and are no longer a compile-time thing.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  As it happens with `type_index`, also `type_hash` is a _sfinae-friendly_ class
 | 
				
			||||||
 | 
					  that can be specialized in order to customize its behavior globally or on a
 | 
				
			||||||
 | 
					  per-type or per-traits basis.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The name associated with a given type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto name = entt::type_name<a_type>::value();
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This value is extracted from some information generally made available by the
 | 
				
			||||||
 | 
					  compiler in use. Therefore, it may differ depending on the compiler and may be
 | 
				
			||||||
 | 
					  empty in the event that this information isn't available.<br/>
 | 
				
			||||||
 | 
					  For example, given the following class:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  struct my_type { /* ... */ };
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The name is `my_type` when compiled with GCC or CLang and `struct my_type`
 | 
				
			||||||
 | 
					  when MSVC is in use.<br/>
 | 
				
			||||||
 | 
					  Most of the time the name is also retrieved at compile-time and is therefore
 | 
				
			||||||
 | 
					  always returned through an `std::string_view`. Users can easily access it and
 | 
				
			||||||
 | 
					  modify it as needed, for example by removing the word `struct` to normalize
 | 
				
			||||||
 | 
					  the result. `EnTT` doesn't do this for obvious reasons, since it would be
 | 
				
			||||||
 | 
					  creating a new string at runtime otherwise.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This function **can** use non-standard features of the language for its own
 | 
				
			||||||
 | 
					  purposes. Users can prevent the library from using these features by means of
 | 
				
			||||||
 | 
					  the `ENTT_STANDARD_CPP` definition. In this case, the name is just empty.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  As it happens with `type_index`, also `type_name` is a _sfinae-friendly_ class
 | 
				
			||||||
 | 
					  that can be specialized in order to customize its behavior globally or on a
 | 
				
			||||||
 | 
					  per-type or per-traits basis.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These are then combined into utilities that aim to offer an API that is somewhat
 | 
				
			||||||
 | 
					similar to that made available by the standard library.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Type info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `type_info` class isn't a drop-in replacement for `std::type_info` but can
 | 
				
			||||||
 | 
					provide similar information which are not implementation defined and don't
 | 
				
			||||||
 | 
					require to enable RTTI.<br/>
 | 
				
			||||||
 | 
					Therefore, they can sometimes be even more reliable than those obtained
 | 
				
			||||||
 | 
					otherwise.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Its type defines an opaque class that is also copyable and movable.<br/>
 | 
				
			||||||
 | 
					Objects of this type are generally returned by the `type_id` functions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// by type
 | 
				
			||||||
 | 
					auto info = entt::type_id<a_type>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// by value
 | 
				
			||||||
 | 
					auto other = entt::type_id(42);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All elements thus received are nothing more than const references to instances
 | 
				
			||||||
 | 
					of `type_info` with static storage duration.<br/>
 | 
				
			||||||
 | 
					This is convenient for saving the entire object aside for the cost of a pointer.
 | 
				
			||||||
 | 
					However, nothing prevents from constructing `type_info` objects directly:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::type_info info{std::in_place_type<int>};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These are the information made available by `type_info`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The index associated with a given type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto idx = entt::type_id<a_type>().index();
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This is also an alias for the following:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto idx = entt::type_index<std::remove_cv_t<std::remove_reference_t<a_type>>>::value();
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The hash value associated with a given type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto hash = entt::type_id<a_type>().hash();
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This is also an alias for the following:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto hash = entt::type_hash<std::remove_cv_t<std::remove_reference_t<a_type>>>::value();
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The name associated with a given type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto name = entt::type_id<my_type>().name();
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This is also an alias for the following:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto name = entt::type_name<std::remove_cv_t<std::remove_reference_t<a_type>>>::value();
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Where all accessed features are available at compile-time, the `type_info` class
 | 
				
			||||||
 | 
					is also fully `constexpr`. However, this cannot be guaranteed in advance and
 | 
				
			||||||
 | 
					depends mainly on the compiler in use and any specializations of the classes
 | 
				
			||||||
 | 
					described above.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Almost unique identifiers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Since the default non-standard, compile-time implementation of `type_hash` makes
 | 
				
			||||||
 | 
					use of hashed strings, it may happen that two types are assigned the same hash
 | 
				
			||||||
 | 
					value.<br/>
 | 
				
			||||||
 | 
					In fact, although this is quite rare, it's not entirely excluded.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Another case where two types are assigned the same identifier is when classes
 | 
				
			||||||
 | 
					from different contexts (for example two or more libraries loaded at runtime)
 | 
				
			||||||
 | 
					have the same fully qualified name. In this case, `type_name` returns the same
 | 
				
			||||||
 | 
					value for the two types.<br/>
 | 
				
			||||||
 | 
					Fortunately, there are several easy ways to deal with this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The most trivial one is to define the `ENTT_STANDARD_CPP` macro. Runtime
 | 
				
			||||||
 | 
					  identifiers don't suffer from the same problem in fact. However, this solution
 | 
				
			||||||
 | 
					  doesn't work well with a plugin system, where the libraries aren't linked.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Another possibility is to specialize the `type_name` class for one of the
 | 
				
			||||||
 | 
					  conflicting types, in order to assign it a custom identifier. This is probably
 | 
				
			||||||
 | 
					  the easiest solution that also preserves the feature of the tool.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* A fully customized identifier generation policy (based for example on enum
 | 
				
			||||||
 | 
					  classes or preprocessing steps) may represent yet another option.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These are just some examples of possible approaches to the problem but there are
 | 
				
			||||||
 | 
					many others. As already mentioned above, since users have full control over
 | 
				
			||||||
 | 
					their types, this problem is in any case easy to solve and should not worry too
 | 
				
			||||||
 | 
					much.<br/>
 | 
				
			||||||
 | 
					In all likelihood, it will never happen to run into a conflict anyway.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Type traits
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A handful of utilities and traits not present in the standard template library
 | 
				
			||||||
 | 
					but which can be useful in everyday life.<br/>
 | 
				
			||||||
 | 
					This list **is not** exhaustive and contains only some of the most useful
 | 
				
			||||||
 | 
					classes. Refer to the inline documentation for more information on the features
 | 
				
			||||||
 | 
					offered by this module.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Size of
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The standard operator `sizeof` complains if users provide it with functions or
 | 
				
			||||||
 | 
					incomplete types. On the other hand, it's guaranteed that its result is always
 | 
				
			||||||
 | 
					non-zero, even if applied to an empty class type.<br/>
 | 
				
			||||||
 | 
					This small class combines the two and offers an alternative to `sizeof` that
 | 
				
			||||||
 | 
					works under all circumstances, returning zero if the type isn't supported:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					const auto size = entt::size_of_v<void>;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Is applicable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The standard library offers the great `std::is_invocable` trait in several
 | 
				
			||||||
 | 
					forms. This takes a function type and a series of arguments and returns true if
 | 
				
			||||||
 | 
					the condition is satisfied.<br/>
 | 
				
			||||||
 | 
					Moreover, users are also provided with `std::apply`, a tool for combining
 | 
				
			||||||
 | 
					invocable elements and tuples of arguments.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It would therefore be a good idea to have a variant of `std::is_invocable` that
 | 
				
			||||||
 | 
					also accepts its arguments in the form of a tuple-like type, so as to complete
 | 
				
			||||||
 | 
					the offer:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					constexpr bool result = entt::is_applicable<Func, std::tuple<a_type, another_type>>;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This trait is built on top of `std::is_invocable` and does nothing but unpack a
 | 
				
			||||||
 | 
					tuple-like type and simplify the code at the call site.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Constness as
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A utility to easily transfer the constness of a type to another type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// type is const dst_type because of the constness of src_type
 | 
				
			||||||
 | 
					using type = entt::constness_as_t<dst_type, const src_type>;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The trait is subject to the rules of the language. For example, _transferring_
 | 
				
			||||||
 | 
					constness between references won't give the desired effect.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Member class type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `auto` template parameter introduced with C++17 made it possible to simplify
 | 
				
			||||||
 | 
					many class templates and template functions but also made the class type opaque
 | 
				
			||||||
 | 
					when members are passed as template arguments.<br/>
 | 
				
			||||||
 | 
					The purpose of this utility is to extract the class type in a few lines of code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					template<typename Member>
 | 
				
			||||||
 | 
					using clazz = entt::member_class_t<Member>;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### N-th argument
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A utility to quickly find the n-th argument of a function, member function or
 | 
				
			||||||
 | 
					data member (for blind operations on opaque types):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					using type = entt::nth_argument_t<1u, &clazz::member>;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Disambiguation of overloaded functions is the responsibility of the user, should
 | 
				
			||||||
 | 
					it be needed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Integral constant
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Since `std::integral_constant` may be annoying because of its form that requires
 | 
				
			||||||
 | 
					to specify both a type and a value of that type, there is a more user-friendly
 | 
				
			||||||
 | 
					shortcut for the creation of integral constants.<br/>
 | 
				
			||||||
 | 
					This shortcut is the alias template `entt::integral_constant`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					constexpr auto constant = entt::integral_constant<42>;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Among the other uses, when combined with a hashed string it helps to define tags
 | 
				
			||||||
 | 
					as human-readable _names_ where actual types would be required otherwise:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					constexpr auto enemy_tag = entt::integral_constant<"enemy"_hs>;
 | 
				
			||||||
 | 
					registry.emplace<enemy_tag>(entity);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Tag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Type `id_type` is very important and widely used in `EnTT`. Therefore, there is
 | 
				
			||||||
 | 
					a more user-friendly shortcut for the creation of constants based on it.<br/>
 | 
				
			||||||
 | 
					This shortcut is the alias template `entt::tag`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If used in combination with hashed strings, it helps to use human-readable names
 | 
				
			||||||
 | 
					where types would be required otherwise. As an example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					registry.emplace<entt::tag<"enemy"_hs>>(entity);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					However, this isn't the only permitted use. Literally any value convertible to
 | 
				
			||||||
 | 
					`id_type` is a good candidate, such as the named constants of an unscoped enum.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Type list and value list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There is no respectable library where the much desired _type list_ can be
 | 
				
			||||||
 | 
					missing.<br/>
 | 
				
			||||||
 | 
					`EnTT` is no exception and provides (making extensive use of it internally) the
 | 
				
			||||||
 | 
					`type_list` type, in addition to its `value_list` counterpart dedicated to
 | 
				
			||||||
 | 
					non-type template parameters.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Here is a (possibly incomplete) list of the functionalities that come with a
 | 
				
			||||||
 | 
					type list:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `type_list_element[_t]` to get the N-th element of a type list.
 | 
				
			||||||
 | 
					* `type_list_index[_v]` to get the index of a given element of a type list.
 | 
				
			||||||
 | 
					* `type_list_cat[_t]` and a handy `operator+` to concatenate type lists.
 | 
				
			||||||
 | 
					* `type_list_unique[_t]` to remove duplicate types from a type list.
 | 
				
			||||||
 | 
					* `type_list_contains[_v]` to know if a type list contains a given type.
 | 
				
			||||||
 | 
					* `type_list_diff[_t]` to remove types from type lists.
 | 
				
			||||||
 | 
					* `type_list_transform[_t]` to _transform_ a range and create another type list.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I'm also pretty sure that more and more utilities will be added over time as
 | 
				
			||||||
 | 
					needs become apparent.<br/>
 | 
				
			||||||
 | 
					Many of these functionalities also exist in their version dedicated to value
 | 
				
			||||||
 | 
					lists. We therefore have `value_list_element[_v]` as well as
 | 
				
			||||||
 | 
					`value_list_cat[_t]`and so on.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Unique sequential identifiers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sometimes it's useful to be able to give unique, sequential numeric identifiers
 | 
				
			||||||
 | 
					to types either at compile-time or runtime.<br/>
 | 
				
			||||||
 | 
					There are plenty of different solutions for this out there and I could have used
 | 
				
			||||||
 | 
					one of them. However, I decided to spend my time to define a couple of tools
 | 
				
			||||||
 | 
					that fully embraces what the modern C++ has to offer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Compile-time generator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To generate sequential numeric identifiers at compile-time, `EnTT` offers the
 | 
				
			||||||
 | 
					`ident` class template:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// defines the identifiers for the given types
 | 
				
			||||||
 | 
					using id = entt::ident<a_type, another_type>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					switch(a_type_identifier) {
 | 
				
			||||||
 | 
					case id::value<a_type>:
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					case id::value<another_type>:
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					default:
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is what this class template has to offer: a `value` inline variable that
 | 
				
			||||||
 | 
					contains a numeric identifier for the given type. It can be used in any context
 | 
				
			||||||
 | 
					where constant expressions are required.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As long as the list remains unchanged, identifiers are also guaranteed to be
 | 
				
			||||||
 | 
					stable across different runs. In case they have been used in a production
 | 
				
			||||||
 | 
					environment and a type has to be removed, one can just use a placeholder to
 | 
				
			||||||
 | 
					leave the other identifiers unchanged:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					template<typename> struct ignore_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using id = entt::ident<
 | 
				
			||||||
 | 
					    a_type_still_valid,
 | 
				
			||||||
 | 
					    ignore_type<no_longer_valid_type>,
 | 
				
			||||||
 | 
					    another_type_still_valid
 | 
				
			||||||
 | 
					>;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Perhaps a bit ugly to see in a codebase but it gets the job done at least.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Runtime generator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `family` class template helps to generate sequential numeric identifiers for
 | 
				
			||||||
 | 
					types at runtime:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// defines a custom generator
 | 
				
			||||||
 | 
					using id = entt::family<struct my_tag>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const auto a_type_id = id::value<a_type>;
 | 
				
			||||||
 | 
					const auto another_type_id = id::value<another_type>;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is what a _family_ has to offer: a `value` inline variable that contains a
 | 
				
			||||||
 | 
					numeric identifier for the given type.<br/>
 | 
				
			||||||
 | 
					The generator is customizable, so as to get different _sequences_ for different
 | 
				
			||||||
 | 
					purposes if needed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Identifiers aren't guaranteed to be stable across different runs. Indeed it
 | 
				
			||||||
 | 
					mostly depends on the flow of execution.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Utilities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's not possible to escape the temptation to add utilities of some kind to a
 | 
				
			||||||
 | 
					library. In fact, `EnTT` also provides a handful of tools to simplify the
 | 
				
			||||||
 | 
					life of developers:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `entt::identity`: the identity function object that will be available with
 | 
				
			||||||
 | 
					  C++20. It returns its argument unchanged and nothing more. It's useful as a
 | 
				
			||||||
 | 
					  sort of _do nothing_ function in template programming.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `entt::overload`: a tool to disambiguate different overloads from their
 | 
				
			||||||
 | 
					  function type. It works with both free and member functions.<br/>
 | 
				
			||||||
 | 
					  Consider the following definition:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  struct clazz {
 | 
				
			||||||
 | 
					      void bar(int) {}
 | 
				
			||||||
 | 
					      void bar() {}
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This utility can be used to get the _right_ overload as:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto *member = entt::overload<void(int)>(&clazz::bar);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The line above is literally equivalent to:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto *member = static_cast<void(clazz:: *)(int)>(&clazz::bar);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Just easier to read and shorter to type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `entt::overloaded`: a small class template used to create a new type with an
 | 
				
			||||||
 | 
					  overloaded `operator()` from a bunch of lambdas or functors.<br/>
 | 
				
			||||||
 | 
					  As an example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  entt::overloaded func{
 | 
				
			||||||
 | 
					      [](int value) { /* ... */ },
 | 
				
			||||||
 | 
					      [](char value) { /* ... */ }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  func(42);
 | 
				
			||||||
 | 
					  func('c');
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Rather useful when doing metaprogramming and having to pass to a function a
 | 
				
			||||||
 | 
					  callable object that supports multiple types at once.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `entt::y_combinator`: this is a C++ implementation of **the** _y-combinator_.
 | 
				
			||||||
 | 
					  If it's not clear what it is, there is probably no need for this utility.<br/>
 | 
				
			||||||
 | 
					  Below is a small example to show its use:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  entt::y_combinator gauss([](const auto &self, auto value) -> unsigned int {
 | 
				
			||||||
 | 
					      return value ? (value + self(value-1u)) : 0;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const auto result = gauss(3u);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Maybe convoluted at a first glance but certainly effective. Unfortunately,
 | 
				
			||||||
 | 
					  the language doesn't make it possible to do much better.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is a rundown of the (actually few) utilities made available by `EnTT`. The
 | 
				
			||||||
 | 
					list will probably grow over time but the size of each will remain rather small,
 | 
				
			||||||
 | 
					as has been the case so far.
 | 
				
			||||||
							
								
								
									
										2344
									
								
								external/entt/entt/docs/md/entity.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2344
									
								
								external/entt/entt/docs/md/entity.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										215
									
								
								external/entt/entt/docs/md/faq.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								external/entt/entt/docs/md/faq.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,215 @@
 | 
				
			|||||||
 | 
					# Frequently Asked Questions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Introduction](#introduction)
 | 
				
			||||||
 | 
					* [FAQ](#faq)
 | 
				
			||||||
 | 
					  * [Why is my debug build on Windows so slow?](#why-is-my-debug-build-on-windows-so-slow)
 | 
				
			||||||
 | 
					  * [How can I represent hierarchies with my components?](#how-can-i-represent-hierarchies-with-my-components)
 | 
				
			||||||
 | 
					  * [Custom entity identifiers: yay or nay?](#custom-entity-identifiers-yay-or-nay)
 | 
				
			||||||
 | 
					  * [Warning C4307: integral constant overflow](#warning-C4307-integral-constant-overflow)
 | 
				
			||||||
 | 
					  * [Warning C4003: the min, the max and the macro](#warning-C4003-the-min-the-max-and-the-macro)
 | 
				
			||||||
 | 
					  * [The standard and the non-copyable types](#the-standard-and-the-non-copyable-types)
 | 
				
			||||||
 | 
					  * [Which functions trigger which signals](#which-functions-trigger-which-signals)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is a constantly updated section where I'm trying to put the answers to the
 | 
				
			||||||
 | 
					most frequently asked questions.<br/>
 | 
				
			||||||
 | 
					If you don't find your answer here, there are two cases: nobody has done it yet
 | 
				
			||||||
 | 
					or this section needs updating. In both cases, you can
 | 
				
			||||||
 | 
					[open a new issue](https://github.com/skypjack/entt/issues/new) or enter either
 | 
				
			||||||
 | 
					the [gitter channel](https://gitter.im/skypjack/entt) or the
 | 
				
			||||||
 | 
					[discord server](https://discord.gg/5BjPWBd) to ask for help.<br/>
 | 
				
			||||||
 | 
					Probably someone already has an answer for you and we can then integrate this
 | 
				
			||||||
 | 
					part of the documentation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# FAQ
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Why is my debug build on Windows so slow?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` is an experimental project that I also use to keep me up-to-date with the
 | 
				
			||||||
 | 
					latest revision of the language and the standard library. For this reason, it's
 | 
				
			||||||
 | 
					likely that some classes you're working with are using standard containers under
 | 
				
			||||||
 | 
					the hood.<br/>
 | 
				
			||||||
 | 
					Unfortunately, it's known that the standard containers aren't particularly
 | 
				
			||||||
 | 
					performing in debugging (the reasons for this go beyond this document) and are
 | 
				
			||||||
 | 
					even less so on Windows apparently. Fortunately this can also be mitigated a
 | 
				
			||||||
 | 
					lot, achieving good results in many cases.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					First of all, there are two things to do in a Windows project:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Disable the [`/JMC`](https://docs.microsoft.com/cpp/build/reference/jmc)
 | 
				
			||||||
 | 
					  option (_Just My Code_ debugging), available starting with Visual Studio 2017
 | 
				
			||||||
 | 
					  version 15.8.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Set the [`_ITERATOR_DEBUG_LEVEL`](https://docs.microsoft.com/cpp/standard-library/iterator-debug-level)
 | 
				
			||||||
 | 
					  macro to 0. This will disable checked iterators and iterator debugging.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Moreover, set the `ENTT_DISABLE_ASSERT` variable or redefine the `ENTT_ASSERT`
 | 
				
			||||||
 | 
					macro to disable internal debug checks in `EnTT`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					#define ENTT_ASSERT(...) ((void)0)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These asserts are introduced to help the users but they require to access to the
 | 
				
			||||||
 | 
					underlying containers and therefore risk ruining the performance in some cases.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					With these changes, debug performance should increase enough in most cases. If
 | 
				
			||||||
 | 
					you want something more, you can also switch to an optimization level `O0` or
 | 
				
			||||||
 | 
					preferably `O1`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## How can I represent hierarchies with my components?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is one of the first questions that anyone makes when starting to work with
 | 
				
			||||||
 | 
					the entity-component-system architectural pattern.<br/>
 | 
				
			||||||
 | 
					There are several approaches to the problem and the best one depends mainly on
 | 
				
			||||||
 | 
					the real problem one is facing. In all cases, how to do it doesn't strictly
 | 
				
			||||||
 | 
					depend on the library in use, but the latter certainly allows or not different
 | 
				
			||||||
 | 
					techniques depending on how the data are laid out.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I tried to describe some of the approaches that fit well with the model of
 | 
				
			||||||
 | 
					`EnTT`. [This](https://skypjack.github.io/2019-06-25-ecs-baf-part-4/) is the
 | 
				
			||||||
 | 
					first post of a series that tries to _explore_ the problem. More will probably
 | 
				
			||||||
 | 
					come in future.<br/>
 | 
				
			||||||
 | 
					In addition, `EnTT` also offers the possibility to create stable storage types
 | 
				
			||||||
 | 
					and therefore have pointer stability for one, all or some components. This is by
 | 
				
			||||||
 | 
					far the most convenient solution when it comes to creating hierarchies and
 | 
				
			||||||
 | 
					whatnot. See the documentation for the ECS part of the library and in particular
 | 
				
			||||||
 | 
					what concerns the `component_traits` class for further details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Custom entity identifiers: yay or nay?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Custom entity identifiers are definitely a good idea in two cases at least:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* If `std::uint32_t` isn't large enough for your purposes, since this is the
 | 
				
			||||||
 | 
					  underlying type of `entt::entity`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* If you want to avoid conflicts when using multiple registries.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Identifiers can be defined through enum classes and class types that define an
 | 
				
			||||||
 | 
					`entity_type` member of type `std::uint32_t` or `std::uint64_t`.<br/>
 | 
				
			||||||
 | 
					In fact, this is a definition equivalent to that of `entt::entity`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					enum class entity: std::uint32_t {};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There is no limit to the number of identifiers that can be defined.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Warning C4307: integral constant overflow
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					According to [this](https://github.com/skypjack/entt/issues/121) issue, using a
 | 
				
			||||||
 | 
					hashed string under VS (toolset v141) could generate a warning.<br/>
 | 
				
			||||||
 | 
					First of all, I want to reassure you: it's expected and harmless. However, it
 | 
				
			||||||
 | 
					can be annoying.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To suppress it and if you don't want to suppress all the other warnings as well,
 | 
				
			||||||
 | 
					here is a workaround in the form of a macro:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					#if defined(_MSC_VER)
 | 
				
			||||||
 | 
					#define HS(str) __pragma(warning(suppress:4307)) entt::hashed_string{str}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define HS(str) entt::hashed_string{str}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					With an example of use included:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					constexpr auto identifier = HS("my/resource/identifier");
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Thanks to [huwpascoe](https://github.com/huwpascoe) for the courtesy.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Warning C4003: the min, the max and the macro
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					On Windows, a header file defines two macros `min` and `max` which may result in
 | 
				
			||||||
 | 
					conflicts with their counterparts in the standard library and therefore in
 | 
				
			||||||
 | 
					errors during compilation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's a pretty big problem but fortunately it's not a problem of `EnTT` and there
 | 
				
			||||||
 | 
					is a fairly simple solution to it.<br/>
 | 
				
			||||||
 | 
					It consists in defining the `NOMINMAX` macro before including any other header
 | 
				
			||||||
 | 
					so as to get rid of the extra definitions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					#define NOMINMAX
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please refer to [this](https://github.com/skypjack/entt/issues/96) issue for
 | 
				
			||||||
 | 
					more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## The standard and the non-copyable types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` uses internally the trait `std::is_copy_constructible_v` to check if a
 | 
				
			||||||
 | 
					component is actually copyable. However, this trait doesn't really check whether
 | 
				
			||||||
 | 
					a type is actually copyable. Instead, it just checks that a suitable copy
 | 
				
			||||||
 | 
					constructor and copy operator exist.<br/>
 | 
				
			||||||
 | 
					This can lead to surprising results due to some idiosyncrasies of the standard.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For example, `std::vector` defines a copy constructor that is conditionally
 | 
				
			||||||
 | 
					enabled depending on whether the value type is copyable or not. As a result,
 | 
				
			||||||
 | 
					`std::is_copy_constructible_v` returns true for the following specialization:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct type {
 | 
				
			||||||
 | 
					    std::vector<std::unique_ptr<action>> vec;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					However, the copy constructor is effectively disabled upon specialization.
 | 
				
			||||||
 | 
					Therefore, trying to assign an instance of this type to an entity may trigger a
 | 
				
			||||||
 | 
					compilation error.<br/>
 | 
				
			||||||
 | 
					As a workaround, users can mark the type explicitly as non-copyable. This also
 | 
				
			||||||
 | 
					suppresses the implicit generation of the move constructor and operator, which
 | 
				
			||||||
 | 
					will therefore have to be defaulted accordingly:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct type {
 | 
				
			||||||
 | 
					    type(const type &) = delete;
 | 
				
			||||||
 | 
					    type(type &&) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    type & operator=(const type &) = delete;
 | 
				
			||||||
 | 
					    type & operator=(type &&) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<std::unique_ptr<action>> vec;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note that aggregate initialization is also disabled as a consequence.<br/>
 | 
				
			||||||
 | 
					Fortunately, this type of trick is quite rare. The bad news is that there is no
 | 
				
			||||||
 | 
					way to deal with it at the library level, this being due to the design of the
 | 
				
			||||||
 | 
					language. On the other hand, the fact that the language itself also offers a way
 | 
				
			||||||
 | 
					to mitigate the problem makes it manageable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Which functions trigger which signals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Storage classes offer three _signals_ that are emitted following specific
 | 
				
			||||||
 | 
					operations. Maybe not everyone knows what these operations are, though.<br/>
 | 
				
			||||||
 | 
					If this isn't clear, below you can find a _vademecum_ for this purpose:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `on_created` is invoked when a component is first added (neither modified nor 
 | 
				
			||||||
 | 
					  replaced) to an entity.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `on_update` is called whenever an existing component is modified or replaced.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `on_destroyed` is called when a component is explicitly or implicitly removed 
 | 
				
			||||||
 | 
					  from an entity.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Among the most controversial functions can be found `emplace_or_replace` and
 | 
				
			||||||
 | 
					`destroy`. However, following the above rules, it's quite simple to know what 
 | 
				
			||||||
 | 
					will happen.<br/>
 | 
				
			||||||
 | 
					In the first case, `on_created` is invoked if the entity has not the component,
 | 
				
			||||||
 | 
					otherwise the latter is replaced and therefore `on_update` is triggered. As for
 | 
				
			||||||
 | 
					the second case, components are removed from their entities and thus freed when
 | 
				
			||||||
 | 
					they are recycled. It means that `on_destroyed` is triggered for every component 
 | 
				
			||||||
 | 
					owned by the entity that is destroyed.
 | 
				
			||||||
							
								
								
									
										372
									
								
								external/entt/entt/docs/md/graph.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										372
									
								
								external/entt/entt/docs/md/graph.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,372 @@
 | 
				
			|||||||
 | 
					# Crash Course: graph
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Introduction](#introduction)
 | 
				
			||||||
 | 
					* [Data structures](#data-structures)
 | 
				
			||||||
 | 
					  * [Adjacency matrix](#adjacency-matrix)
 | 
				
			||||||
 | 
					  * [Graphviz dot language](#graphviz-dot-language)
 | 
				
			||||||
 | 
					* [Flow builder](#flow-builder)
 | 
				
			||||||
 | 
					  * [Tasks and resources](#tasks-and-resources)
 | 
				
			||||||
 | 
					  * [Fake resources and order of execution](#fake-resources-and-order-of-execution)
 | 
				
			||||||
 | 
					  * [Sync points](#sync-points)
 | 
				
			||||||
 | 
					  * [Execution graph](#execution-graph)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` doesn't aim to offer everything one needs to work with graphs. Therefore,
 | 
				
			||||||
 | 
					anyone looking for this in the _graph_ submodule will be disappointed.<br/>
 | 
				
			||||||
 | 
					Quite the opposite is true though. This submodule is minimal and contains only
 | 
				
			||||||
 | 
					the data structures and algorithms strictly necessary for the development of
 | 
				
			||||||
 | 
					some tools such as the _flow builder_.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Data structures
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As anticipated in the introduction, the aim isn't to offer all possible data
 | 
				
			||||||
 | 
					structures suitable for representing and working with graphs. Many will likely
 | 
				
			||||||
 | 
					be added or refined over time. However I want to discourage anyone expecting
 | 
				
			||||||
 | 
					tight scheduling on the subject.<br/>
 | 
				
			||||||
 | 
					The data structures presented in this section are mainly useful for the
 | 
				
			||||||
 | 
					development and support of some tools which are also part of the same submodule.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Adjacency matrix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The adjacency matrix is designed to represent either a directed or an undirected
 | 
				
			||||||
 | 
					graph:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::adjacency_matrix<entt::directed_tag> adjacency_matrix{};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `directed_tag` type _creates_ the graph as directed. There is also an
 | 
				
			||||||
 | 
					`undirected_tag` counterpart which creates it as undirected.<br/>
 | 
				
			||||||
 | 
					The interface deviates slightly from the typical double indexing of C and offers
 | 
				
			||||||
 | 
					an API that is perhaps more familiar to a C++ programmer. Therefore, the access
 | 
				
			||||||
 | 
					and modification of an element takes place via the `contains`, `insert` and
 | 
				
			||||||
 | 
					`erase` functions rather than a double call to an `operator[]`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					if(adjacency_matrix.contains(0u, 1u)) {
 | 
				
			||||||
 | 
					    adjacency_matrix.erase(0u, 1u);
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
					    adjacency_matrix.insert(0u, 1u);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Both `insert` and` erase` are _idempotent_ functions which have no effect if the
 | 
				
			||||||
 | 
					element already exists or has already been deleted.<br/>
 | 
				
			||||||
 | 
					The first one returns an `std::pair` containing the iterator to the element and
 | 
				
			||||||
 | 
					a boolean value indicating whether the element was newly inserted or not. The
 | 
				
			||||||
 | 
					second one returns the number of deleted elements (0 or 1).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					An adjacency matrix is initialized with the number of elements (vertices) when
 | 
				
			||||||
 | 
					constructing it but can also be resized later using the `resize` function:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::adjacency_matrix<entt::directed_tag> adjacency_matrix{3u};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To visit all vertices, the class offers a function named `vertices` that returns
 | 
				
			||||||
 | 
					an iterable object suitable for the purpose:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					for(auto &&vertex: adjacency_matrix.vertices()) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The same result is obtained with the following snippet, since the vertices are
 | 
				
			||||||
 | 
					plain unsigned integral values:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					for(auto last = adjacency_matrix.size(), pos = {}; pos < last; ++pos) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As for visiting the edges, a few functions are available.<br/>
 | 
				
			||||||
 | 
					When the purpose is to visit all the edges of a given adjacency matrix, the
 | 
				
			||||||
 | 
					`edges` function returns an iterable object that is used to get them as pairs of
 | 
				
			||||||
 | 
					vertices:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					for(auto [lhs, rhs]: adjacency_matrix.edges()) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If the goal is to visit all the in- or out-edges of a given vertex instead, the
 | 
				
			||||||
 | 
					`in_edges` and `out_edges` functions are meant for that:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					for(auto [lhs, rhs]: adjacency_matrix.out_edges(3u)) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Both the functions expect the vertex to visit (that is, to return the in- or
 | 
				
			||||||
 | 
					out-edges for) as an argument.<br/>
 | 
				
			||||||
 | 
					Finally, the adjacency matrix is an allocator-aware container and offers most of
 | 
				
			||||||
 | 
					the functionalities one would expect from this type of containers, such as
 | 
				
			||||||
 | 
					`clear` or 'get_allocator` and so on.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Graphviz dot language
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As it's one of the most popular formats, the library offers minimal support for
 | 
				
			||||||
 | 
					converting a graph to a Graphviz dot snippet.<br/>
 | 
				
			||||||
 | 
					The simplest way is to pass both an output stream and a graph to the `dot`
 | 
				
			||||||
 | 
					function:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					std::ostringstream output{};
 | 
				
			||||||
 | 
					entt::dot(output, adjacency_matrix);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's also possible to provide a callback to which the vertices are passed and
 | 
				
			||||||
 | 
					which can be used to add (`dot`) properties to the output as needed:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					std::ostringstream output{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					entt::dot(output, adjacency_matrix, [](auto &output, auto vertex) {
 | 
				
			||||||
 | 
					    out << "label=\"v\"" << vertex << ",shape=\"box\"";
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This second mode is particularly convenient when the user wants to associate
 | 
				
			||||||
 | 
					externally managed data to the graph being converted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Flow builder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A flow builder is used to create execution graphs from tasks and resources.<br/>
 | 
				
			||||||
 | 
					The implementation is as generic as possible and doesn't bind to any other part
 | 
				
			||||||
 | 
					of the library.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This class is designed as a sort of _state machine_ to which a specific task is
 | 
				
			||||||
 | 
					attached for which the resources accessed in read-only or read-write mode are
 | 
				
			||||||
 | 
					specified.<br/>
 | 
				
			||||||
 | 
					Most of the functions in the API also return the flow builder itself, according
 | 
				
			||||||
 | 
					to what is the common sense API when it comes to builder classes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once all tasks are registered and resources assigned to them, an execution graph
 | 
				
			||||||
 | 
					in the form of an adjacency matrix is returned to the user.<br/>
 | 
				
			||||||
 | 
					This graph contains all the tasks assigned to the flow builder in the form of
 | 
				
			||||||
 | 
					_vertices_. The _vertex_ itself is used as an index to get the identifier passed
 | 
				
			||||||
 | 
					during registration.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Tasks and resources
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Although these terms are used extensively in the documentation, the flow builder
 | 
				
			||||||
 | 
					has no real concept of tasks and resources.<br/>
 | 
				
			||||||
 | 
					This class works mainly with _identifiers_, that is, values of type `id_type`.
 | 
				
			||||||
 | 
					In other terms, both tasks and resources are identified by integral values.<br/>
 | 
				
			||||||
 | 
					This allows not to couple the class itself to the rest of the library or to any
 | 
				
			||||||
 | 
					particular data structure. On the other hand, it requires the user to keep track
 | 
				
			||||||
 | 
					of the association between identifiers and operations or actual data.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once a flow builder is created (which requires no constructor arguments), the
 | 
				
			||||||
 | 
					first thing to do is to bind a task. This tells to the builder _who_ intends to
 | 
				
			||||||
 | 
					consume the resources that are specified immediately after:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::flow builder{};
 | 
				
			||||||
 | 
					builder.bind("task_1"_hs);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The example uses the `EnTT` hashed string to generate an identifier for the
 | 
				
			||||||
 | 
					task.<br/>
 | 
				
			||||||
 | 
					Indeed, the use of `id_type` as an identifier type isn't by accident. In fact,
 | 
				
			||||||
 | 
					it matches well with the internal hashed string class. Moreover, it's also the
 | 
				
			||||||
 | 
					same type returned by the hash function of the internal RTTI system, in case the
 | 
				
			||||||
 | 
					user wants to rely on that.<br/>
 | 
				
			||||||
 | 
					However, being an integral value, it leaves the user full freedom to rely on his
 | 
				
			||||||
 | 
					own tools if necessary.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once a task is associated with the flow builder, it's also assigned read-only or
 | 
				
			||||||
 | 
					read-write resources as appropriate:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					builder
 | 
				
			||||||
 | 
					    .bind("task_1"_hs)
 | 
				
			||||||
 | 
					        .ro("resource_1"_hs)
 | 
				
			||||||
 | 
					        .ro("resource_2"_hs)
 | 
				
			||||||
 | 
					    .bind("task_2"_hs)
 | 
				
			||||||
 | 
					        .rw("resource_2"_hs)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As mentioned, many functions return the builder itself and it's therefore easy
 | 
				
			||||||
 | 
					to concatenate the different calls.<br/>
 | 
				
			||||||
 | 
					Also in the case of resources, they are identified by numeric values of type
 | 
				
			||||||
 | 
					`id_type`. As above, the choice is not entirely random. This goes well with the
 | 
				
			||||||
 | 
					tools offered by the library while leaving room for maximum flexibility.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Finally, both the `ro` and` rw` functions also offer an overload that accepts a
 | 
				
			||||||
 | 
					pair of iterators, so that one can pass a range of resources in one go.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Rebinding
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `flow` class is resource based rather than task based. This means that graph
 | 
				
			||||||
 | 
					generation is driven by resources and not by the order of _appearance_ of tasks
 | 
				
			||||||
 | 
					during flow definition.<br/>
 | 
				
			||||||
 | 
					Although this concept is particularly important, it's almost irrelevant for the
 | 
				
			||||||
 | 
					vast majority of cases. However, it becomes relevant when _rebinding_ resources
 | 
				
			||||||
 | 
					or tasks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In fact, nothing prevents rebinding elements to a flow.<br/>
 | 
				
			||||||
 | 
					However, the behavior changes slightly from case to case and has some nuances
 | 
				
			||||||
 | 
					that it's worth knowing about.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Directly rebinding a resource without the task being replaced trivially results
 | 
				
			||||||
 | 
					in the task's access mode for that resource being updated:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					builder.bind("task"_hs).rw("resource"_hs).ro("resource"_hs)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this case, the resource is accessed in read-only mode, regardless of the
 | 
				
			||||||
 | 
					first call to `rw`.<br/>
 | 
				
			||||||
 | 
					Behind the scenes, the call doesn't actually _replace_ the previous one but is
 | 
				
			||||||
 | 
					queued after it instead, overwriting it when generating the graph. Thus, a large
 | 
				
			||||||
 | 
					number of resource rebindings may even impact processing times (very difficult
 | 
				
			||||||
 | 
					to observe but theoretically possible).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Rebinding resources and also combining it with changes to tasks has far more
 | 
				
			||||||
 | 
					implications instead.<br/>
 | 
				
			||||||
 | 
					As mentioned, graph generation takes place starting from resources and not from
 | 
				
			||||||
 | 
					tasks. Therefore, the result may not be as expected:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					builder
 | 
				
			||||||
 | 
					    .bind("task_1"_hs)
 | 
				
			||||||
 | 
					        .ro("resource"_hs)
 | 
				
			||||||
 | 
					    .bind("task_2"_hs)
 | 
				
			||||||
 | 
					        .ro("resource"_hs)
 | 
				
			||||||
 | 
					    .bind("task_1"_hs)
 | 
				
			||||||
 | 
					        .rw("resource"_hs);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					What happens here is that the resource first _sees_ a read-only access request
 | 
				
			||||||
 | 
					from the first task, then a read-write request from the second task and finally
 | 
				
			||||||
 | 
					a new read-only request from the first task.<br/>
 | 
				
			||||||
 | 
					Although this definition would probably be counted as an error, the resulting
 | 
				
			||||||
 | 
					graph may be unexpected. This in fact consists of a single edge outgoing from
 | 
				
			||||||
 | 
					the second task and directed to the first task.<br/>
 | 
				
			||||||
 | 
					To intuitively understand what happens, it's enough to think of the fact that a
 | 
				
			||||||
 | 
					task never has an edge pointing to itself.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					While not obvious, this approach has its pros and cons like any other solution.
 | 
				
			||||||
 | 
					For example, creating loops is actually simple in the context of resource-based
 | 
				
			||||||
 | 
					graph generations:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					builder
 | 
				
			||||||
 | 
					    .bind("task_1"_hs)
 | 
				
			||||||
 | 
					        .rw("resource"_hs)
 | 
				
			||||||
 | 
					    .bind("task_2"_hs)
 | 
				
			||||||
 | 
					        .rw("resource"_hs)
 | 
				
			||||||
 | 
					    .bind("task_1"_hs)
 | 
				
			||||||
 | 
					        .rw("resource"_hs);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As expected, this definition leads to the creation of two edges that define a
 | 
				
			||||||
 | 
					loop between the two tasks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As a general rule, rebinding resources and tasks is highly discouraged because
 | 
				
			||||||
 | 
					it could lead to subtle bugs if users don't know what they're doing.<br/>
 | 
				
			||||||
 | 
					However, once the mechanisms of resource-based graph generation are understood,
 | 
				
			||||||
 | 
					it can offer to the expert user a flexibility and a range of possibilities
 | 
				
			||||||
 | 
					otherwise inaccessible.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Fake resources and order of execution
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The flow builder doesn't offer the ability to specify when a task should execute
 | 
				
			||||||
 | 
					before or after another task.<br/>
 | 
				
			||||||
 | 
					In fact, the order of _registration_ on the resources also determines the order
 | 
				
			||||||
 | 
					in which the tasks are processed during the generation of the execution graph.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					However, there is a way to _force_ the execution order of two processes.<br/>
 | 
				
			||||||
 | 
					Briefly, since accessing a resource in opposite modes requires sequential rather
 | 
				
			||||||
 | 
					than parallel scheduling, it's possible to make use of fake resources to rule on
 | 
				
			||||||
 | 
					the execution order:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					builder
 | 
				
			||||||
 | 
					    .bind("task_1"_hs)
 | 
				
			||||||
 | 
					        .ro("resource_1"_hs)
 | 
				
			||||||
 | 
					        .rw("fake"_hs)
 | 
				
			||||||
 | 
					    .bind("task_2"_hs)
 | 
				
			||||||
 | 
					        .ro("resource_2"_hs)
 | 
				
			||||||
 | 
					        .ro("fake"_hs)
 | 
				
			||||||
 | 
					    .bind("task_3"_hs)
 | 
				
			||||||
 | 
					        .ro("resource_2"_hs)
 | 
				
			||||||
 | 
					        .ro("fake"_hs)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This snippet forces the execution of `task_1` **before** `task_2` and `task_3`.
 | 
				
			||||||
 | 
					This is due to the fact that the former sets a read-write requirement on a fake
 | 
				
			||||||
 | 
					resource that the other tasks also want to access in read-only mode.<br/>
 | 
				
			||||||
 | 
					Similarly, it's possible to force a task to run **after** a certain group:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					builder
 | 
				
			||||||
 | 
					    .bind("task_1"_hs)
 | 
				
			||||||
 | 
					        .ro("resource_1"_hs)
 | 
				
			||||||
 | 
					        .ro("fake"_hs)
 | 
				
			||||||
 | 
					    .bind("task_2"_hs)
 | 
				
			||||||
 | 
					        .ro("resource_1"_hs)
 | 
				
			||||||
 | 
					        .ro("fake"_hs)
 | 
				
			||||||
 | 
					    .bind("task_3"_hs)
 | 
				
			||||||
 | 
					        .ro("resource_2"_hs)
 | 
				
			||||||
 | 
					        .rw("fake"_hs)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this case, since there are a number of processes that want to read a specific
 | 
				
			||||||
 | 
					resource, they will do so in parallel by forcing `task_3` to run after all the
 | 
				
			||||||
 | 
					others tasks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Sync points
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sometimes it's useful to assign the role of _sync point_ to a node.<br/>
 | 
				
			||||||
 | 
					Whether it accesses new resources or is simply a watershed, the procedure for
 | 
				
			||||||
 | 
					assigning this role to a vertex is always the same. First it's tied to the flow
 | 
				
			||||||
 | 
					builder, then the `sync` function is invoked:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					builder.bind("sync_point"_hs).sync();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The choice to assign an _identity_ to this type of nodes lies in the fact that,
 | 
				
			||||||
 | 
					more often than not, they also perform operations on resources.<br/>
 | 
				
			||||||
 | 
					If this isn't the case, it will still be possible to create no-op vertices to
 | 
				
			||||||
 | 
					which empty tasks are assigned.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Execution graph
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once both the resources and their consumers have been properly registered, the
 | 
				
			||||||
 | 
					purpose of this tool is to generate an execution graph that takes into account
 | 
				
			||||||
 | 
					all specified constraints to return the best scheduling for the vertices:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::adjacency_matrix<entt::directed_tag> graph = builder.graph();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Searching for the main vertices (that is, those without in-edges) is usually the
 | 
				
			||||||
 | 
					first thing required:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					for(auto &&vertex: graph) {
 | 
				
			||||||
 | 
					    if(auto in_edges = graph.in_edges(vertex); in_edges.begin() == in_edges.end()) {
 | 
				
			||||||
 | 
					        // ...
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Then it's possible to instantiate an execution graph by means of other functions
 | 
				
			||||||
 | 
					such as `out_edges` to retrieve the children of a given task or `edges` to get
 | 
				
			||||||
 | 
					the identifiers.
 | 
				
			||||||
							
								
								
									
										97
									
								
								external/entt/entt/docs/md/lib.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								external/entt/entt/docs/md/lib.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
				
			|||||||
 | 
					# Push EnTT across boundaries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Working across boundaries](#working-across-boundaries)
 | 
				
			||||||
 | 
					  * [Smooth until proven otherwise](#smooth-until-proven-otherwise)
 | 
				
			||||||
 | 
					  * [Meta context](#meta-context)
 | 
				
			||||||
 | 
					  * [Memory management](#memory-management)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Working across boundaries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` has historically had a limit when used across boundaries on Windows in
 | 
				
			||||||
 | 
					general and on GNU/Linux when default visibility was set to hidden. The
 | 
				
			||||||
 | 
					limitation was mainly due to a custom utility used to assign unique, sequential
 | 
				
			||||||
 | 
					identifiers with different types.<br/>
 | 
				
			||||||
 | 
					Fortunately, nowadays `EnTT` works smoothly across boundaries.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Smooth until proven otherwise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Many classes in `EnTT` make extensive use of type erasure for their purposes.
 | 
				
			||||||
 | 
					This raises the need to identify objects whose type has been erased.<br/>
 | 
				
			||||||
 | 
					The `type_hash` class template is how identifiers are generated and thus made
 | 
				
			||||||
 | 
					available to the rest of the library. In general, this class doesn't arouse much
 | 
				
			||||||
 | 
					interest. The only exception is when a conflict between identifiers occurs
 | 
				
			||||||
 | 
					(definitely uncommon though) or when the default solution proposed by `EnTT`
 | 
				
			||||||
 | 
					isn't suitable for the user's purposes.<br/>
 | 
				
			||||||
 | 
					The section dedicated to `type_info` contains all the details to get around the
 | 
				
			||||||
 | 
					issue in a concise and elegant way. Please refer to the specific documentation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When working with linked libraries, compile definitions `ENTT_API_EXPORT` and
 | 
				
			||||||
 | 
					`ENTT_API_IMPORT` are to import or export symbols, so as to make everything work
 | 
				
			||||||
 | 
					nicely across boundaries.<br/>
 | 
				
			||||||
 | 
					On the other hand, everything should run smoothly when working with plugins or
 | 
				
			||||||
 | 
					shared libraries that don't export any symbols.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For those who need more details, the test suite contains many examples covering
 | 
				
			||||||
 | 
					the most common cases (see the `lib` directory for all details).<br/>
 | 
				
			||||||
 | 
					It goes without saying that it's impossible to cover **all** possible cases.
 | 
				
			||||||
 | 
					However, what is offered should hopefully serve as a basis for all of them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Meta context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The runtime reflection system deserves a special mention when it comes to using
 | 
				
			||||||
 | 
					it across boundaries.<br/>
 | 
				
			||||||
 | 
					Since it's linked already to a static context to which the elements are attached
 | 
				
			||||||
 | 
					and different contexts don't relate to each other, they must be _shared_ to
 | 
				
			||||||
 | 
					allow the use of meta types across boundaries.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Fortunately, sharing a context is also trivial to do. First of all, the local
 | 
				
			||||||
 | 
					one is acquired in the main space:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					auto handle = entt::locator<entt::meta_ctx>::handle();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Then, it's passed to the receiving space that sets it as its default context,
 | 
				
			||||||
 | 
					thus discarding or storing aside the local one:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::locator<entt::meta_ctx>::reset(handle);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					From now on, both spaces refer to the same context and on it are attached all
 | 
				
			||||||
 | 
					new meta types, no matter where they are created.<br/>
 | 
				
			||||||
 | 
					Note that _replacing_ the main context doesn't also propagate changes across
 | 
				
			||||||
 | 
					boundaries. In other words, replacing a context results in the decoupling of the
 | 
				
			||||||
 | 
					two sides and therefore a divergence in the contents.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Memory Management
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There is another subtle problem due to memory management that can lead to
 | 
				
			||||||
 | 
					headaches.<br/>
 | 
				
			||||||
 | 
					It can occur where there are pools of objects (such as components or events)
 | 
				
			||||||
 | 
					dynamically created on demand. This is usually not a problem when working with
 | 
				
			||||||
 | 
					linked libraries that rely on the same dynamic runtime. However, it can occur in
 | 
				
			||||||
 | 
					the case of plugins or statically linked runtimes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As an example, imagine creating an instance of `registry` in the main executable
 | 
				
			||||||
 | 
					and sharing it with a plugin. If the latter starts working with a component that
 | 
				
			||||||
 | 
					is unknown to the former, a dedicated pool is created within the registry on
 | 
				
			||||||
 | 
					first use.<br/>
 | 
				
			||||||
 | 
					As one can guess, this pool is instantiated on a different side of the boundary
 | 
				
			||||||
 | 
					from the `registry`. Therefore, the instance is now managing memory from
 | 
				
			||||||
 | 
					different spaces and this can quickly lead to crashes if not properly addressed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To overcome the risk, it's recommended to use well-defined interfaces that make
 | 
				
			||||||
 | 
					fundamental types pass through the boundaries, isolating the instances of the
 | 
				
			||||||
 | 
					`EnTT` classes from time to time and as appropriate.<br/>
 | 
				
			||||||
 | 
					Refer to the test suite for some examples, read the documentation available
 | 
				
			||||||
 | 
					online about this type of issues or consult someone who has already had such
 | 
				
			||||||
 | 
					experiences to avoid problems.
 | 
				
			||||||
							
								
								
									
										304
									
								
								external/entt/entt/docs/md/links.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										304
									
								
								external/entt/entt/docs/md/links.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,304 @@
 | 
				
			|||||||
 | 
					# EnTT in Action
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Introduction](#introduction)
 | 
				
			||||||
 | 
					* [EnTT in Action](#entt-in-action)
 | 
				
			||||||
 | 
					  * [Games](#games)
 | 
				
			||||||
 | 
					  * [Engines and the like](#engines-and-the-like)
 | 
				
			||||||
 | 
					  * [Articles, videos and blog posts](#articles-videos-and-blog-posts)
 | 
				
			||||||
 | 
					  * [Any Other Business](#any-other-business)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` is widely used in private and commercial applications. I cannot even
 | 
				
			||||||
 | 
					mention most of them because of some signatures I put on some documents time
 | 
				
			||||||
 | 
					ago. Fortunately, there are also people who took the time to implement open
 | 
				
			||||||
 | 
					source projects based on `EnTT` and didn't hold back when it came to documenting
 | 
				
			||||||
 | 
					them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Below an incomplete list of games, applications and articles that can be used as
 | 
				
			||||||
 | 
					a reference.<br/>
 | 
				
			||||||
 | 
					Where I put the word _apparently_ means that the use of `EnTT` is documented but
 | 
				
			||||||
 | 
					the authors didn't make explicit announcements or contacted me directly.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you know of other resources out there that are about `EnTT`, feel free to
 | 
				
			||||||
 | 
					open an issue or a PR and I'll be glad to add them to this page.<br/>
 | 
				
			||||||
 | 
					I hope the following lists can grow much more in the future.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# EnTT in Action
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Games
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * [Minecraft](https://minecraft.net/en-us/attribution/) by
 | 
				
			||||||
 | 
					    [Mojang](https://mojang.com/): of course, **that** Minecraft, see the
 | 
				
			||||||
 | 
					    open source attributions page for more details.
 | 
				
			||||||
 | 
					  * [Minecraft Earth](https://www.minecraft.net/en-us/about-earth) by
 | 
				
			||||||
 | 
					    [Mojang](https://mojang.com/): an augmented reality game for mobile, that
 | 
				
			||||||
 | 
					    lets users bring Minecraft into the real world.
 | 
				
			||||||
 | 
					  * [Ember Sword](https://embersword.com/): a modern Free-to-Play MMORPG with a
 | 
				
			||||||
 | 
					    player-driven economy, a classless combat system, and scarce, tradable
 | 
				
			||||||
 | 
					    cosmetic collectibles.
 | 
				
			||||||
 | 
					  * Apparently [Diablo II: Resurrected](https://diablo2.blizzard.com/) by
 | 
				
			||||||
 | 
					    [Blizzard](https://www.blizzard.com/): monsters, heroes, items, spells, all
 | 
				
			||||||
 | 
					    resurrected. Thanks unknown insider.
 | 
				
			||||||
 | 
					  * [Apparently](https://www.youtube.com/watch?v=P8xvOA3ikrQ&t=1105s)
 | 
				
			||||||
 | 
					    [Call of Duty: Vanguard](https://www.callofduty.com/vanguard) by
 | 
				
			||||||
 | 
					    [Sledgehammer Games](https://www.sledgehammergames.com/): I can neither
 | 
				
			||||||
 | 
					    confirm nor deny but there is a license I know in the credits.
 | 
				
			||||||
 | 
					  * Apparently [D&D Dark Alliance](https://darkalliance.wizards.com) by
 | 
				
			||||||
 | 
					    [Wizards of the Coast](https://company.wizards.com): your party, their
 | 
				
			||||||
 | 
					    funeral.
 | 
				
			||||||
 | 
					  * [TiltedOnline](https://github.com/tiltedphoques/TiltedOnline) by
 | 
				
			||||||
 | 
					    [Tilted Phoques](https://github.com/tiltedphoques): Skyrim and Fallout 4 mod
 | 
				
			||||||
 | 
					    to play online.
 | 
				
			||||||
 | 
					  * [Antkeeper](https://github.com/antkeeper/antkeeper-source): an ant colony
 | 
				
			||||||
 | 
					    simulation [game](https://antkeeper.com/).
 | 
				
			||||||
 | 
					  * [Openblack](https://github.com/openblack/openblack): open source
 | 
				
			||||||
 | 
					    reimplementation of the game _Black & White_ (2001).
 | 
				
			||||||
 | 
					  * [Land of the Rair](https://github.com/LandOfTheRair/core2): the new backend
 | 
				
			||||||
 | 
					    of [a retro-style MUD](https://rair.land/) for the new age.
 | 
				
			||||||
 | 
					  * [Face Smash](https://play.google.com/store/apps/details?id=com.gamee.facesmash):
 | 
				
			||||||
 | 
					    a game to play with your face.
 | 
				
			||||||
 | 
					  * [EnTT Pacman](https://github.com/Kerndog73/EnTT-Pacman): an example of how
 | 
				
			||||||
 | 
					    to make Pacman with `EnTT`.
 | 
				
			||||||
 | 
					  * [Wacman](https://github.com/carlfindahl/wacman): a pacman clone with OpenGL.
 | 
				
			||||||
 | 
					  * [Classic Tower Defence](https://github.com/kerndog73/Classic-Tower-Defence):
 | 
				
			||||||
 | 
					    a tiny little tower defence game featuring a homemade font.
 | 
				
			||||||
 | 
					    [Check it out](https://indi-kernick.itch.io/classic-tower-defence).
 | 
				
			||||||
 | 
					  * [The Machine](https://github.com/Kerndog73/The-Machine): a box pushing
 | 
				
			||||||
 | 
					    puzzler with logic gates and other cool stuff.
 | 
				
			||||||
 | 
					    [Check it out](https://indi-kernick.itch.io/the-machine-web-version).
 | 
				
			||||||
 | 
					  * [EnTTPong](https://github.com/DomRe/EnttPong): a basic game made to showcase
 | 
				
			||||||
 | 
					    different parts of `EnTT` and C++17.
 | 
				
			||||||
 | 
					  * [Randballs](https://github.com/gale93/randballs): simple `SFML` and `EnTT`
 | 
				
			||||||
 | 
					    playground.
 | 
				
			||||||
 | 
					  * [EnTT Tower Defense](https://github.com/Daivuk/tddod): a data oriented tower
 | 
				
			||||||
 | 
					    defense example.
 | 
				
			||||||
 | 
					  * [EnTT Breakout](https://github.com/vblanco20-1/entt-breakout): simple
 | 
				
			||||||
 | 
					    example of a breakout game, using `SDL` and `EnTT`.
 | 
				
			||||||
 | 
					  * [Arcade puzzle game with EnTT](https://github.com/MasonRG/ArcadePuzzleGame):
 | 
				
			||||||
 | 
					    arcade puzzle game made in C++ using the `SDL2` and `EnTT` libraries.
 | 
				
			||||||
 | 
					  * [Snake with EnTT](https://github.com/MasonRG/SnakeGame): simple snake game
 | 
				
			||||||
 | 
					    made in C++ with the `SDL2` and `EnTT` libraries.
 | 
				
			||||||
 | 
					  * [Mirrors lasers and robots](https://github.com/guillaume-haerinck/imac-tower-defense):
 | 
				
			||||||
 | 
					    a small tower defense game based on mirror orientation.
 | 
				
			||||||
 | 
					  * [PopHead](https://github.com/SPC-Some-Polish-Coders/PopHead/): 2D, Zombie,
 | 
				
			||||||
 | 
					    RPG game made from scratch in C++.
 | 
				
			||||||
 | 
					  * [Robotligan](https://github.com/Trisslotten/robotligan): multiplayer
 | 
				
			||||||
 | 
					    football game.
 | 
				
			||||||
 | 
					  * [DungeonSlayer](https://github.com/alohaeee/DungeonSlayer): 2D game made
 | 
				
			||||||
 | 
					    from scratch in C++.
 | 
				
			||||||
 | 
					  * [3DGame](https://github.com/kwarkGorny/3DGame): 2.5D top-down space shooter.
 | 
				
			||||||
 | 
					  * [Pulcher](https://github.com/AODQ/pulcher): 2D cross-platform game inspired
 | 
				
			||||||
 | 
					    by Quake.
 | 
				
			||||||
 | 
					  * [Destroid](https://github.com/tyrannicaltoucan/destroid): _one-bazillionth_
 | 
				
			||||||
 | 
					    arcade game about shooting dirty rocks in space, inspired by Asteroids.
 | 
				
			||||||
 | 
					  * [Wanderer](https://github.com/albin-johansson/wanderer): a 2D exploration
 | 
				
			||||||
 | 
					    based indie game.
 | 
				
			||||||
 | 
					  * [Spelunky<EFBFBD> Classic remake](https://github.com/dbeef/spelunky-psp): a truly
 | 
				
			||||||
 | 
					    multiplatform experience with a rewrite from scratch.
 | 
				
			||||||
 | 
					  * [CubbyTower](https://github.com/utilForever/CubbyTower): a simple tower
 | 
				
			||||||
 | 
					    defense game using C++ with Entity Component System (ECS).
 | 
				
			||||||
 | 
					  * [Runeterra](https://github.com/utilForever/Runeterra): Legends of Runeterra
 | 
				
			||||||
 | 
					    simulator using C++ with some reinforcement learning.
 | 
				
			||||||
 | 
					  * [Black Sun](https://store.steampowered.com/app/1670930/Black_Sun/): fly your
 | 
				
			||||||
 | 
					    space ship through a large 2D open world.
 | 
				
			||||||
 | 
					  * [PokeMaster](https://github.com/utilForever/PokeMaster): Pokemon Battle
 | 
				
			||||||
 | 
					    simulator using C++ with some reinforcement learning.
 | 
				
			||||||
 | 
					  * [HomeHearth](https://youtu.be/GrEWl8npL9Y): choose your hero, protect the
 | 
				
			||||||
 | 
					    town, before it's too late.
 | 
				
			||||||
 | 
					  * [City Builder Game](https://github.com/PhiGei2000/CityBuilderGame): a simple
 | 
				
			||||||
 | 
					    city-building game using C++ and OpenGL.
 | 
				
			||||||
 | 
					  * [BattleSub](https://github.com/bfeldpw/battlesub): two player 2D submarine
 | 
				
			||||||
 | 
					    game with some fluid dynamics.
 | 
				
			||||||
 | 
					  * [Crimson Rush](https://github.com/WilKam01/LuaCGame): a dungeon-crawler and
 | 
				
			||||||
 | 
					    rougelike inspired game about exploring and surviving as long as possible.
 | 
				
			||||||
 | 
					  * [Space Fight](https://github.com/cholushkin/SpaceFight): one screen
 | 
				
			||||||
 | 
					    multi-player arcade shooter game prototype.
 | 
				
			||||||
 | 
					  * [Confetti Party](https://github.com/hexerei/entt-confetti): C++ sample
 | 
				
			||||||
 | 
					    application as a starting point using `EnTT` and `SDL2`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Engines and the like:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * [Aether Engine](https://hadean.com/spatial-simulation/)
 | 
				
			||||||
 | 
					    [v1.1+](https://docs.hadean.com/v1.1/Licenses/) by
 | 
				
			||||||
 | 
					    [Hadean](https://hadean.com/): a library designed for spatially partitioning
 | 
				
			||||||
 | 
					    agent-based simulations.
 | 
				
			||||||
 | 
					  * [Fling Engine](https://github.com/flingengine/FlingEngine): a Vulkan game
 | 
				
			||||||
 | 
					    engine with a focus on data oriented design.
 | 
				
			||||||
 | 
					  * [NovusCore](https://github.com/novuscore/NovusCore): a modern take on World
 | 
				
			||||||
 | 
					    of Warcraft emulation.
 | 
				
			||||||
 | 
					  * [Chrysalis](https://github.com/ivanhawkes/Chrysalis): action RPG SDK for
 | 
				
			||||||
 | 
					    CRYENGINE games.
 | 
				
			||||||
 | 
					  * [LM-Engine](https://github.com/Lawrencemm/LM-Engine): the Vim of game
 | 
				
			||||||
 | 
					    engines.
 | 
				
			||||||
 | 
					  * [Edyn](https://github.com/xissburg/edyn): a real-time physics engine
 | 
				
			||||||
 | 
					    organized as an ECS.
 | 
				
			||||||
 | 
					  * [MushMachine](https://github.com/MadeOfJelly/MushMachine): engine...
 | 
				
			||||||
 | 
					    vrooooommm.
 | 
				
			||||||
 | 
					  * [Antara Gaming SDK](https://github.com/KomodoPlatform/antara-gaming-sdk):
 | 
				
			||||||
 | 
					    the Komodo Gaming Software Development Kit.
 | 
				
			||||||
 | 
					  * [XVP](https://ravingbots.com/xvp-expansive-vehicle-physics-for-unreal-engine/):
 | 
				
			||||||
 | 
					    [_eXpansive Vehicle Physics_](https://github.com/raving-bots/xvp/wiki/Plugin-integration-guide)
 | 
				
			||||||
 | 
					    plugin for Unreal Engine.
 | 
				
			||||||
 | 
					  * [Apparently](https://teamwisp.github.io/credits/)
 | 
				
			||||||
 | 
					    [Wisp](https://teamwisp.github.io/product/) by
 | 
				
			||||||
 | 
					    [Team Wisp](https://teamwisp.github.io/): an advanced real-time ray tracing
 | 
				
			||||||
 | 
					    renderer built for the demands of video game artists.
 | 
				
			||||||
 | 
					  * [shiva](https://github.com/Milerius/shiva): modern C++ engine with
 | 
				
			||||||
 | 
					    modularity.
 | 
				
			||||||
 | 
					  * [ImGui/EnTT editor](https://github.com/Green-Sky/imgui_entt_entity_editor):
 | 
				
			||||||
 | 
					    a drop-in, single-file entity editor for `EnTT` that uses `ImGui` as
 | 
				
			||||||
 | 
					    graphical backend (with
 | 
				
			||||||
 | 
					    [demo code](https://github.com/Green-Sky/imgui_entt_entity_editor_demo)).
 | 
				
			||||||
 | 
					  * [SgOgl](https://github.com/stwe/SgOgl): a game engine library for OpenGL
 | 
				
			||||||
 | 
					    developed for educational purposes.
 | 
				
			||||||
 | 
					  * [Lumos](https://github.com/jmorton06/Lumos): game engine written in C++
 | 
				
			||||||
 | 
					    using OpenGL and Vulkan.
 | 
				
			||||||
 | 
					  * [Silvanus](https://github.com/hobbyistmaker/silvanus): Silvanus Fusion 360
 | 
				
			||||||
 | 
					    Box Generator.
 | 
				
			||||||
 | 
					  * [Lina Engine](https://github.com/inanevin/LinaEngine): an open-source,
 | 
				
			||||||
 | 
					    modular, tiny and fast C++ game engine, aimed to develop 3D desktop games.
 | 
				
			||||||
 | 
					  * [Spike](https://github.com/FahimFuad/Spike): a powerful game engine which
 | 
				
			||||||
 | 
					    can run on a toaster.
 | 
				
			||||||
 | 
					  * [Helena Framework](https://github.com/NIKEA-SOFT/HelenaFramework): a modern
 | 
				
			||||||
 | 
					    framework in C++17 for backend development.
 | 
				
			||||||
 | 
					  * [Unity/EnTT](https://github.com/TongTungGiang/unity-entt): tech demo of a
 | 
				
			||||||
 | 
					    native simulation layer using `EnTT` and `Unity` as a rendering engine.
 | 
				
			||||||
 | 
					  * [OverEngine](https://github.com/OverShifted/OverEngine): an over-engineered
 | 
				
			||||||
 | 
					    game engine.
 | 
				
			||||||
 | 
					  * [Electro](https://github.com/Electro-Technologies/Electro): high performance
 | 
				
			||||||
 | 
					    3D game engine with a high emphasis on rendering.
 | 
				
			||||||
 | 
					  * [Kawaii](https://github.com/Mathieu-Lala/Kawaii_Engine): a modern data
 | 
				
			||||||
 | 
					    oriented game engine.
 | 
				
			||||||
 | 
					  * [Becketron](https://github.com/Doctor-Foxling/Becketron): a game engine
 | 
				
			||||||
 | 
					    written mostly in C++.
 | 
				
			||||||
 | 
					  * [Spatial Engine](https://github.com/luizgabriel/Spatial.Engine): a
 | 
				
			||||||
 | 
					    cross-platform engine created on top of google's filament rendering engine.
 | 
				
			||||||
 | 
					  * [Kaguya](https://github.com/KaiH0717/Kaguya): D3D12 Rendering Engine.
 | 
				
			||||||
 | 
					  * [OpenAWE](https://github.com/OpenAWE-Project/OpenAWE): open implementation
 | 
				
			||||||
 | 
					    of the Alan Wake Engine.
 | 
				
			||||||
 | 
					  * [Nazara Engine](https://github.com/DigitalPulseSoftware/NazaraEngine): fast,
 | 
				
			||||||
 | 
					    cross-platform, object-oriented API to help in daily developer life.
 | 
				
			||||||
 | 
					  * [Billy Engine](https://github.com/billy4479/BillyEngine): some kind of a 2D
 | 
				
			||||||
 | 
					    engine based on `SDL2` and `EnTT`.
 | 
				
			||||||
 | 
					  * [Ducktape](https://github.com/DucktapeEngine/Ducktape): an open source C++
 | 
				
			||||||
 | 
					    2D & 3D game engine that focuses on being fast and powerful.
 | 
				
			||||||
 | 
					  * [The Worst Engine](https://github.com/Parasik72/TWE): a game engine based on
 | 
				
			||||||
 | 
					    OpenGL.
 | 
				
			||||||
 | 
					  * [Ecsact](https://ecsact.dev/): a language aimed at describing ECS, with a
 | 
				
			||||||
 | 
					    [runtime implementation](https://github.com/ecsact-dev/ecsact_rt_entt) based
 | 
				
			||||||
 | 
					    on `EnTT`.
 | 
				
			||||||
 | 
					  * [AGE (Arc Game Engine)](https://github.com/MohitSethi99/ArcGameEngine): an
 | 
				
			||||||
 | 
					    open-source engine for building 2D & 3D real-time rendering and interactive
 | 
				
			||||||
 | 
					    contents.
 | 
				
			||||||
 | 
					  * [Kengine](https://github.com/phisko/kengine): the _Koala engine_ is a game
 | 
				
			||||||
 | 
					    engine entirely implemented as an entity-component-ystem.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Articles, videos and blog posts:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * [Some posts](https://skypjack.github.io/tags/#entt) on my personal
 | 
				
			||||||
 | 
					    [blog](https://skypjack.github.io/) are about `EnTT`, for those who want to
 | 
				
			||||||
 | 
					    know **more** on this project.
 | 
				
			||||||
 | 
					  * [Game Engine series](https://www.youtube.com/c/TheChernoProject/videos) by
 | 
				
			||||||
 | 
					    [The Cherno](https://github.com/TheCherno) (not only about `EnTT` but also
 | 
				
			||||||
 | 
					    on the use of an ECS in general):
 | 
				
			||||||
 | 
					    - [Intro to EnTT](https://www.youtube.com/watch?v=D4hz0wEB978).
 | 
				
			||||||
 | 
					    - [Entities and Components](https://www.youtube.com/watch?v=-B1iu4QJTUc).
 | 
				
			||||||
 | 
					    - [The ENTITY Class](https://www.youtube.com/watch?v=GfSzeAcsBb0).
 | 
				
			||||||
 | 
					    - [Camera Systems](https://www.youtube.com/watch?v=ubZn7BlrnTU).
 | 
				
			||||||
 | 
					    - [Scene Camera](https://www.youtube.com/watch?v=UKVFRRufKzo).
 | 
				
			||||||
 | 
					    - [Native Scripting](https://www.youtube.com/watch?v=iIUhg88MK5M).
 | 
				
			||||||
 | 
					    - [Native Scripting (now with virtual functions!)](https://www.youtube.com/watch?v=1cHEcrIn8IQ).
 | 
				
			||||||
 | 
					    - [Scene Hierarchy Panel](https://www.youtube.com/watch?v=wziDnE8guvI).
 | 
				
			||||||
 | 
					    - [Properties Panel](https://www.youtube.com/watch?v=NBpB0qscF3E).
 | 
				
			||||||
 | 
					    - [Camera Component UI](https://www.youtube.com/watch?v=RIMt_6agUiU).
 | 
				
			||||||
 | 
					    - [Drawing Component UI](https://www.youtube.com/watch?v=u3yq8s3KuSE).
 | 
				
			||||||
 | 
					    - [Transform Component UI](https://www.youtube.com/watch?v=8JqcXYbzPJc).
 | 
				
			||||||
 | 
					    - [Adding/Removing Entities and Components UI](https://www.youtube.com/watch?v=PsyGmsIgp9M).
 | 
				
			||||||
 | 
					    - [Saving and Loading Scenes](https://www.youtube.com/watch?v=IEiOP7Y-Mbc).
 | 
				
			||||||
 | 
					    - ... And so on.
 | 
				
			||||||
 | 
					      [Check out](https://www.youtube.com/channel/UCQ-W1KE9EYfdxhL6S4twUNw) the
 | 
				
			||||||
 | 
					      _Game Engine Series_ by The Cherno for more videos.
 | 
				
			||||||
 | 
					  * [Warmonger Dynasty devlog series](https://david-delassus.medium.com/list/warmonger-dynasty-devlogs-f64b71f556de)
 | 
				
			||||||
 | 
					    by [linkdd](https://github.com/linkdd): an interesting walkthrough of
 | 
				
			||||||
 | 
					    developing a game (also) with EnTT.
 | 
				
			||||||
 | 
					  * [Use EnTT When You Need An ECS](https://www.codingwiththomas.com/blog/use-entt-when-you-need-an-ecs)
 | 
				
			||||||
 | 
					    by [Thomas](https://www.codingwiththomas.com/): I couldn't have said it
 | 
				
			||||||
 | 
					    better.
 | 
				
			||||||
 | 
					  * [Space Battle: Huge edition](http://victor.madtriangles.com/code%20experiment/2018/06/11/post-ecs-battle-huge.html):
 | 
				
			||||||
 | 
					    huge space battle built entirely from scratch.
 | 
				
			||||||
 | 
					  * [Space Battle](https://github.com/vblanco20-1/ECS_SpaceBattle): huge space
 | 
				
			||||||
 | 
					    battle built on `UE4`.
 | 
				
			||||||
 | 
					  * [Experimenting with ECS in UE4](http://victor.madtriangles.com/code%20experiment/2018/03/25/post-ue4-ecs-battle.html):
 | 
				
			||||||
 | 
					    interesting article about `UE4` and `EnTT`.
 | 
				
			||||||
 | 
					  * [Implementing ECS architecture in UE4](https://forums.unrealengine.com/development-discussion/c-gameplay-programming/1449913-implementing-ecs-architecture-in-ue4-giant-space-battle):
 | 
				
			||||||
 | 
					    giant space battle.
 | 
				
			||||||
 | 
					  * [Conan Adventures (SFML and EnTT in C++)](https://leinnan.github.io/blog/conan-adventuressfml-and-entt-in-c.html):
 | 
				
			||||||
 | 
					    create projects in modern C++ using `SFML`, `EnTT`, `Conan` and `CMake`.
 | 
				
			||||||
 | 
					  * [Adding EnTT ECS to Chrysalis](https://www.tauradius.com/post/adding-an-ecs-to-chrysalis/):
 | 
				
			||||||
 | 
					    a blog entry (and its 
 | 
				
			||||||
 | 
					    [follow-up](https://www.tauradius.com/post/chrysalis-update-2020-08-02/)) 
 | 
				
			||||||
 | 
					    about the integration of `EnTT` into `Chrysalis`, an action RPG SDK for
 | 
				
			||||||
 | 
					    CRYENGINE games.
 | 
				
			||||||
 | 
					  * [Creating Minecraft in One Week with C++ and Vulkan](https://vazgriz.com/189/creating-minecraft-in-one-week-with-c-and-vulkan/):
 | 
				
			||||||
 | 
					    a crack at recreating Minecraft in one week using a custom C++ engine and
 | 
				
			||||||
 | 
					    Vulkan ([code included](https://github.com/vazgriz/VoxelGame)).
 | 
				
			||||||
 | 
					  * [Ability Creator](https://www.erichildebrand.net/blog/ability-creator-project-retrospect):
 | 
				
			||||||
 | 
					    project retrospect by [Eric Hildebrand](https://www.erichildebrand.net/).
 | 
				
			||||||
 | 
					  * [EnTT Entity Component System Gaming Library](https://gamefromscratch.com/entt-entity-component-system-gaming-library/):
 | 
				
			||||||
 | 
					    `EnTT` on GameFromScratch.com.
 | 
				
			||||||
 | 
					  * [Custom C++ server for UE5](https://youtu.be/fbXZVNCOvjM) optimized for
 | 
				
			||||||
 | 
					    MMO(RPG)s and its [follow-up](https://youtu.be/yGlZeopx2hU) episode about
 | 
				
			||||||
 | 
					    player bots and full external ECS: a series definitely worth looking at.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Any Other Business:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * [ArcGIS Runtime SDKs](https://developers.arcgis.com/arcgis-runtime/) by
 | 
				
			||||||
 | 
					    [Esri](https://www.esri.com/): they use `EnTT` for the internal ECS and the
 | 
				
			||||||
 | 
					    cross platform C++ rendering engine. The SDKs are utilized by a lot of
 | 
				
			||||||
 | 
					    enterprise custom apps, as well as by Esri for its own public applications
 | 
				
			||||||
 | 
					    such as
 | 
				
			||||||
 | 
					    [Explorer](https://play.google.com/store/apps/details?id=com.esri.explorer),
 | 
				
			||||||
 | 
					    [Collector](https://play.google.com/store/apps/details?id=com.esri.arcgis.collector)
 | 
				
			||||||
 | 
					    and
 | 
				
			||||||
 | 
					    [Navigator](https://play.google.com/store/apps/details?id=com.esri.navigator).
 | 
				
			||||||
 | 
					  * [FASTSUITE Edition 2](https://www.fastsuite.com/en_EN/fastsuite/fastsuite-edition-2.html)
 | 
				
			||||||
 | 
					    by [Cenit](http://www.cenit.com/en_EN/about-us/overview.html): they use
 | 
				
			||||||
 | 
					    `EnTT` to drive their simulation, that is, the communication between robot
 | 
				
			||||||
 | 
					    controller emulator and renderer.
 | 
				
			||||||
 | 
					  * [Ragdoll](https://ragdolldynamics.com/): real-time physics for Autodesk Maya
 | 
				
			||||||
 | 
					    2020.
 | 
				
			||||||
 | 
					  * [Project Lagrange](https://github.com/adobe/lagrange): a robust geometry
 | 
				
			||||||
 | 
					    processing library by [Adobe](https://github.com/adobe).
 | 
				
			||||||
 | 
					  * [AtomicDEX](https://github.com/KomodoPlatform/atomicDEX-Desktop): a secure
 | 
				
			||||||
 | 
					    wallet and non-custodial decentralized exchange rolled into one application.
 | 
				
			||||||
 | 
					  * [Apparently](https://www.linkedin.com/in/skypjack/)
 | 
				
			||||||
 | 
					    [NIO](https://www.nio.io/): there was a collaboration to make some changes
 | 
				
			||||||
 | 
					    to `EnTT`, at the time used for internal projects.
 | 
				
			||||||
 | 
					  * [Apparently](https://www.linkedin.com/jobs/view/architekt-c%2B%2B-at-tieto-1219512333/)
 | 
				
			||||||
 | 
					    [Tieto](https://www.tieto.com/): they published a job post where `EnTT` was
 | 
				
			||||||
 | 
					    listed on their software stack.
 | 
				
			||||||
 | 
					  * [Sequentity](https://github.com/alanjfs/sequentity): A MIDI-like
 | 
				
			||||||
 | 
					    sequencer/tracker for C++ and `ImGui` (with `Magnum` and `EnTT`).
 | 
				
			||||||
 | 
					  * [EnTT meets Sol2](https://github.com/skaarj1989/entt-meets-sol2): freely
 | 
				
			||||||
 | 
					    available examples of how to combine `EnTT` and `Sol2`.
 | 
				
			||||||
 | 
					  * [Godot meets EnTT](https://github.com/portaloffreedom/godot_entt_example/):
 | 
				
			||||||
 | 
					    a simple example on how to use `EnTT` within
 | 
				
			||||||
 | 
					    [`Godot`](https://godotengine.org/).
 | 
				
			||||||
 | 
					  * [Godot and GameNetworkingSockets meet EnTT](https://github.com/portaloffreedom/godot_entt_net_example):
 | 
				
			||||||
 | 
					    a simple example on how to use `EnTT` and
 | 
				
			||||||
 | 
					    [`GameNetworkingSockets`](https://github.com/ValveSoftware/GameNetworkingSockets)
 | 
				
			||||||
 | 
					    within [`Godot`](https://godotengine.org/).
 | 
				
			||||||
 | 
					  * [MatchOneEntt](https://github.com/mhaemmerle/MatchOneEntt): port of
 | 
				
			||||||
 | 
					    [Match One](https://github.com/sschmid/Match-One) for `Entitas-CSharp`.
 | 
				
			||||||
 | 
					  * GitHub contains also
 | 
				
			||||||
 | 
					    [many other examples](https://github.com/search?o=desc&q=%22skypjack%2Fentt%22&s=indexed&type=Code)
 | 
				
			||||||
 | 
					    of use of `EnTT` from which to take inspiration if interested.
 | 
				
			||||||
							
								
								
									
										88
									
								
								external/entt/entt/docs/md/locator.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								external/entt/entt/docs/md/locator.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					# Crash Course: service locator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Introduction](#introduction)
 | 
				
			||||||
 | 
					* [Service locator](#service-locator)
 | 
				
			||||||
 | 
					  * [Opaque handles](#opaque-handles)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usually, service locators are tightly bound to the services they expose and it's
 | 
				
			||||||
 | 
					hard to define a general purpose solution.<br/>
 | 
				
			||||||
 | 
					This tiny class tries to fill the gap and gets rid of the burden of defining a
 | 
				
			||||||
 | 
					different specific locator for each application.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Service locator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The service locator API tries to mimic that of `std::optional` and adds some
 | 
				
			||||||
 | 
					extra functionalities on top of it such as allocator support.<br/>
 | 
				
			||||||
 | 
					There are a couple of functions to set up a service, namely `emplace` and
 | 
				
			||||||
 | 
					`allocate_emplace`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::locator<interface>::emplace<service>(argument);
 | 
				
			||||||
 | 
					entt::locator<interface>::allocate_emplace<service>(allocator, argument);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The difference is that the latter expects an allocator as the first argument and
 | 
				
			||||||
 | 
					uses it to allocate the service itself.<br/>
 | 
				
			||||||
 | 
					Once a service is set up, it's retrieved using the `value` function:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					interface &service = entt::locator<interface>::value();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Since the service may not be set (and therefore this function may result in an
 | 
				
			||||||
 | 
					undefined behavior), the `has_value` and `value_or` functions are also available
 | 
				
			||||||
 | 
					to test a service locator and to get a fallback service in case there is none:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					if(entt::locator<interface>::has_value()) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface &service = entt::locator<interface>::value_or<fallback_impl>(argument);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All arguments are used only if necessary, that is, if a service doesn't already
 | 
				
			||||||
 | 
					exist and therefore the fallback service is constructed and returned. In all
 | 
				
			||||||
 | 
					other cases, they are discarded.<br/>
 | 
				
			||||||
 | 
					Finally, to reset a service, use the `reset` function.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Opaque handles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sometimes it's useful to _transfer_ a copy of a service to another locator. For
 | 
				
			||||||
 | 
					example, when working across boundaries it's common to _share_ a service with a
 | 
				
			||||||
 | 
					dynamically loaded module.<br/>
 | 
				
			||||||
 | 
					Options aren't much in this case. Among these is the possibility of _exporting_
 | 
				
			||||||
 | 
					services and assigning them to a different locator.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is what the `handle` and `reset` functions are meant for.<br/>
 | 
				
			||||||
 | 
					The former returns an opaque object useful for _exporting_ (or rather, obtaining
 | 
				
			||||||
 | 
					a reference to) a service. The latter also accepts an optional argument to a
 | 
				
			||||||
 | 
					handle which then allows users to reset a service by initializing it with an
 | 
				
			||||||
 | 
					opaque handle:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					auto handle = entt::locator<interface>::handle();
 | 
				
			||||||
 | 
					entt::locator<interface>::reset(handle);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's worth noting that it's possible to get handles for uninitialized services
 | 
				
			||||||
 | 
					and use them with other locators. Of course, all a user will get is to have an
 | 
				
			||||||
 | 
					uninitialized service elsewhere as well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note that exporting a service allows users to _share_ the object currently set
 | 
				
			||||||
 | 
					in a locator. Replacing it won't replace the element even where a service has
 | 
				
			||||||
 | 
					been configured with a handle to the previous item.<br/>
 | 
				
			||||||
 | 
					In other words, if an audio service is replaced with a null object to silence an
 | 
				
			||||||
 | 
					application and the original service was shared, this operation won't propagate
 | 
				
			||||||
 | 
					to the other locators. Therefore, a module that share the ownership of the
 | 
				
			||||||
 | 
					original audio service is still able to emit sounds.
 | 
				
			||||||
							
								
								
									
										961
									
								
								external/entt/entt/docs/md/meta.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										961
									
								
								external/entt/entt/docs/md/meta.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,961 @@
 | 
				
			|||||||
 | 
					# Crash Course: runtime reflection system
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Introduction](#introduction)
 | 
				
			||||||
 | 
					* [Names and identifiers](#names-and-identifiers)
 | 
				
			||||||
 | 
					* [Reflection in a nutshell](#reflection-in-a-nutshell)
 | 
				
			||||||
 | 
					  * [Any to the rescue](#any-to-the-rescue)
 | 
				
			||||||
 | 
					  * [Enjoy the runtime](#enjoy-the-runtime)
 | 
				
			||||||
 | 
					  * [Container support](#container-support)
 | 
				
			||||||
 | 
					  * [Pointer-like types](#pointer-like-types)
 | 
				
			||||||
 | 
					  * [Template information](#template-information)
 | 
				
			||||||
 | 
					  * [Automatic conversions](#automatic-conversions)
 | 
				
			||||||
 | 
					  * [Implicitly generated default constructor](#implicitly-generated-default-constructor)
 | 
				
			||||||
 | 
					  * [From void to any](#from-void-to-any)
 | 
				
			||||||
 | 
					  * [Policies: the more, the less](#policies-the-more-the-less)
 | 
				
			||||||
 | 
					  * [Named constants and enums](#named-constants-and-enums)
 | 
				
			||||||
 | 
					  * [Properties and meta objects](#properties-and-meta-objects)
 | 
				
			||||||
 | 
					  * [Unregister types](#unregister-types)
 | 
				
			||||||
 | 
					  * [Meta context](#meta-context)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Reflection (or rather, its lack) is a trending topic in the C++ world and a tool
 | 
				
			||||||
 | 
					that can unlock a lot of interesting features in the specific case of `EnTT`. I
 | 
				
			||||||
 | 
					looked for a third-party library that met my needs on the subject, but I always
 | 
				
			||||||
 | 
					came across some details that I didn't like: macros, being intrusive, too many
 | 
				
			||||||
 | 
					allocations, and so on.<br/>
 | 
				
			||||||
 | 
					I finally decided to write a built-in, non-intrusive and macro-free runtime
 | 
				
			||||||
 | 
					reflection system for `EnTT`. Maybe I didn't do better than others or maybe yes,
 | 
				
			||||||
 | 
					time will tell me, but at least I can model this tool around the library to
 | 
				
			||||||
 | 
					which it belongs and not the opposite.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Names and identifiers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The meta system doesn't force users to rely on the tools provided by the library
 | 
				
			||||||
 | 
					when it comes to working with names and identifiers. It does this by offering an
 | 
				
			||||||
 | 
					API that works with opaque identifiers that may or may not be generated by means
 | 
				
			||||||
 | 
					of a hashed string.<br/>
 | 
				
			||||||
 | 
					This means that users can assign any type of identifier to the meta objects, as
 | 
				
			||||||
 | 
					long as they're numeric. It doesn't matter if they're generated at runtime, at
 | 
				
			||||||
 | 
					compile-time or with custom functions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					That being said, the examples in the following sections are all based on the
 | 
				
			||||||
 | 
					`hashed_string` class as provided by this library. Therefore, where an
 | 
				
			||||||
 | 
					identifier is required, it's likely that a user defined literal is used as
 | 
				
			||||||
 | 
					follows:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					auto factory = entt::meta<my_type>().type("reflected_type"_hs);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For what it's worth, this is completely equivalent to:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					auto factory = entt::meta<my_type>().type(42u);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Obviously, human-readable identifiers are more convenient to use and highly
 | 
				
			||||||
 | 
					recommended.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Reflection in a nutshell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Reflection always starts from actual C++ types. Users cannot reflect _imaginary_
 | 
				
			||||||
 | 
					types.<br/>
 | 
				
			||||||
 | 
					The `meta` function is where it all starts:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					auto factory = entt::meta<my_type>();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The returned value is a _factory object_ to use to continue building the meta
 | 
				
			||||||
 | 
					type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					By default, a meta type is associated with the identifier returned by the
 | 
				
			||||||
 | 
					runtime type identification system built-in in `EnTT`.<br/>
 | 
				
			||||||
 | 
					However, it's also possible to assign custom identifiers to meta types:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					auto factory = entt::meta<my_type>().type("reflected_type"_hs);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Identifiers are used to _retrieve_ meta types at runtime by _name_ other than by
 | 
				
			||||||
 | 
					type.<br/>
 | 
				
			||||||
 | 
					However, users can be interested in adding features to a reflected type so that
 | 
				
			||||||
 | 
					the reflection system can use it correctly under the hood, while they don't want
 | 
				
			||||||
 | 
					to also make the type _searchable_. In this case, it's sufficient not to invoke
 | 
				
			||||||
 | 
					`type`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A factory is such that all its member functions return the factory itself. It's
 | 
				
			||||||
 | 
					generally used to create the following:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* _Constructors_. A constructors is assigned to a reflected type by specifying
 | 
				
			||||||
 | 
					  its _list of arguments_. Free functions are also accepted if the return type
 | 
				
			||||||
 | 
					  is the expected one. From a client perspective, nothing changes between a free
 | 
				
			||||||
 | 
					  function or an actual constructor:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  entt::meta<my_type>().ctor<int, char>().ctor<&factory>();
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Meta default constructors are implicitly generated, if possible.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* _Destructors_. Both free functions and member functions are valid destructors:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  entt::meta<my_type>().dtor<&destroy>();
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The purpose is to offer the possibility to free up resources that require
 | 
				
			||||||
 | 
					  _special treatment_ before an object is actually destroyed.<br/>
 | 
				
			||||||
 | 
					  A function should neither delete nor explicitly invoke the destructor of a
 | 
				
			||||||
 | 
					  given instance.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* _Data members_. Meta data members are actual data members of the underlying
 | 
				
			||||||
 | 
					  type but also static and global variables or constants of any kind. From the
 | 
				
			||||||
 | 
					  point of view of the client, all the variables associated with the reflected
 | 
				
			||||||
 | 
					  type appear as if they were part of the type itself:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  entt::meta<my_type>()
 | 
				
			||||||
 | 
					      .data<&my_type::static_variable>("static"_hs)
 | 
				
			||||||
 | 
					      .data<&my_type::data_member>("member"_hs)
 | 
				
			||||||
 | 
					      .data<&global_variable>("global"_hs);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The `data` function requires the identifier to use for the meta data member.
 | 
				
			||||||
 | 
					  Users can then access it by _name_ at runtime.<br/>
 | 
				
			||||||
 | 
					  Data members are also defined by means of a setter and getter pair. These are
 | 
				
			||||||
 | 
					  either free functions, class members or a mix of them. This approach is also
 | 
				
			||||||
 | 
					  convenient to create read-only properties from a non-const data member:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  entt::meta<my_type>().data<nullptr, &my_type::data_member>("member"_hs);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Multiple setters are also supported by means of a `value_list` object:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  entt::meta<my_type>().data<entt::value_list<&from_int, &from_string>, &my_type::data_member>("member"_hs);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* _Member functions_. Meta member functions are actual member functions of the
 | 
				
			||||||
 | 
					  underlying type but also plain free functions. From the point of view of the
 | 
				
			||||||
 | 
					  client, all the functions associated with the reflected type appear as if they
 | 
				
			||||||
 | 
					  were part of the type itself:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  entt::meta<my_type>()
 | 
				
			||||||
 | 
					      .func<&my_type::static_function>("static"_hs)
 | 
				
			||||||
 | 
					      .func<&my_type::member_function>("member"_hs)
 | 
				
			||||||
 | 
					      .func<&free_function>("free"_hs);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The `func` function requires the identifier to use for the meta data function.
 | 
				
			||||||
 | 
					  Users can then access it by _name_ at runtime.<br/>
 | 
				
			||||||
 | 
					  Overloading of meta functions is supported. Overloaded functions are resolved
 | 
				
			||||||
 | 
					  at runtime by the reflection system according to the types of the arguments.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* _Base classes_. A base class is such that the underlying type is actually
 | 
				
			||||||
 | 
					  derived from it:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  entt::meta<derived_type>().base<base_type>();
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The reflection system tracks the relationship and allows for implicit casts at
 | 
				
			||||||
 | 
					  runtime when required. In other terms, wherever a `base_type` is required, an
 | 
				
			||||||
 | 
					  instance of `derived_type` is also accepted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* _Conversion functions_. Conversion functions allow users to define conversions
 | 
				
			||||||
 | 
					  that are implicitly performed by the reflection system when required:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  entt::meta<double>().conv<int>();
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is everything users need to create meta types. Refer to the inline
 | 
				
			||||||
 | 
					documentation for further details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Any to the rescue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The reflection system offers a kind of _extended version_ of the `entt::any`
 | 
				
			||||||
 | 
					class (see the core module for more details).<br/>
 | 
				
			||||||
 | 
					The purpose is to add some feature on top of those already present, so as to
 | 
				
			||||||
 | 
					integrate it with the meta type system without having to duplicate the code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The API is very similar to that of the `any` type. The class `meta_any` _wraps_
 | 
				
			||||||
 | 
					many of the feature to infer a meta node, before forwarding some or all of the
 | 
				
			||||||
 | 
					arguments to the underlying storage.<br/>
 | 
				
			||||||
 | 
					Among the few relevant differences, `meta_any` adds support for containers and
 | 
				
			||||||
 | 
					pointer-like types, while `any` doesn't.<br/>
 | 
				
			||||||
 | 
					Similar to `any`, this class is also used to create _aliases_ for unmanaged
 | 
				
			||||||
 | 
					objects either with `forward_as_meta` or using the `std::in_place_type<T &>`
 | 
				
			||||||
 | 
					disambiguation tag, as well as from an existing object by means of the `as_ref`
 | 
				
			||||||
 | 
					member function.<br/>
 | 
				
			||||||
 | 
					Unlike `any` instead, `meta_any` treats an empty instance and one initialized
 | 
				
			||||||
 | 
					with `void` differently:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta_any empty{};
 | 
				
			||||||
 | 
					entt::meta_any other{std::in_place_type<void>};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					While `any` considers both as empty, `meta_any` treats objects initialized with
 | 
				
			||||||
 | 
					`void` as if they were _valid_ ones. This allows to differentiate between failed
 | 
				
			||||||
 | 
					function calls and function calls that are successful but return nothing.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Finally, the member functions `try_cast`, `cast` and `allow_cast` are used to
 | 
				
			||||||
 | 
					cast the underlying object to a given type (either a reference or a value type)
 | 
				
			||||||
 | 
					or to _convert_ a `meta_any` in such a way that a cast becomes viable for the
 | 
				
			||||||
 | 
					resulting object.<br/>
 | 
				
			||||||
 | 
					There is in fact no `any_cast` equivalent for `meta_any`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Enjoy the runtime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once the web of reflected types is constructed, it's a matter of using it at
 | 
				
			||||||
 | 
					runtime where required.<br/>
 | 
				
			||||||
 | 
					There are a few options to search for a reflected type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// direct access to a reflected type
 | 
				
			||||||
 | 
					auto by_type = entt::resolve<my_type>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// look up a reflected type by identifier
 | 
				
			||||||
 | 
					auto by_id = entt::resolve("reflected_type"_hs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// look up a reflected type by type info
 | 
				
			||||||
 | 
					auto by_type_id = entt::resolve(entt::type_id<my_type>());
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There exists also an overload of the `resolve` function to use to iterate all
 | 
				
			||||||
 | 
					reflected types at once. It returns an iterable object to be used in a range-for
 | 
				
			||||||
 | 
					loop:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					for(auto &&[id, type]: entt::resolve()) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In all cases, the returned value is an instance of `meta_type` (possibly with
 | 
				
			||||||
 | 
					its id). This kind of objects offer an API to know their _runtime identifiers_,
 | 
				
			||||||
 | 
					to iterate all the meta objects associated with them and even to build instances
 | 
				
			||||||
 | 
					of the underlying type.<br/>
 | 
				
			||||||
 | 
					Meta data members and functions are accessed by name:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Meta data members:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto data = entt::resolve<my_type>().data("member"_hs);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The returned type is `meta_data` and may be invalid if there is no meta data
 | 
				
			||||||
 | 
					  object associated with the given identifier.<br/>
 | 
				
			||||||
 | 
					  A meta data object offers an API to query the underlying type (for example, to
 | 
				
			||||||
 | 
					  know if it's a const or a static one), to get the meta type of the variable
 | 
				
			||||||
 | 
					  and to set or get the contained value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Meta function members:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto func = entt::resolve<my_type>().func("member"_hs);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The returned type is `meta_func` and may be invalid if there is no meta
 | 
				
			||||||
 | 
					  function object associated with the given identifier.<br/>
 | 
				
			||||||
 | 
					  A meta function object offers an API to query the underlying type (for
 | 
				
			||||||
 | 
					  example, to know if it's a const or a static function), to know the number of
 | 
				
			||||||
 | 
					  arguments, the meta return type and the meta types of the parameters. In
 | 
				
			||||||
 | 
					  addition, a meta function object is used to invoke the underlying function and
 | 
				
			||||||
 | 
					  then get the return value in the form of a `meta_any` object.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All the meta objects thus obtained as well as the meta types explicitly convert
 | 
				
			||||||
 | 
					to a boolean value to check for validity:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					if(auto func = entt::resolve<my_type>().func("member"_hs); func) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Furthermore, all them (and a few more, like meta basis) are returned by a bunch
 | 
				
			||||||
 | 
					of overloads that provide the caller with iterable ranges of top-level elements.
 | 
				
			||||||
 | 
					As an example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					for(auto &&[id, type]: entt::resolve<my_type>().base()) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Meta type are also used to `construct` actual instances of the underlying
 | 
				
			||||||
 | 
					type.<br/>
 | 
				
			||||||
 | 
					In particular, the `construct` member function accepts a variable number of
 | 
				
			||||||
 | 
					arguments and searches for a match. It then returns a `meta_any` object that may
 | 
				
			||||||
 | 
					or may not be initialized, depending on whether a suitable constructor was found
 | 
				
			||||||
 | 
					or not.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There is no object that wraps the destructor of a meta type nor a `destroy`
 | 
				
			||||||
 | 
					member function in its API. Destructors are invoked implicitly by `meta_any`
 | 
				
			||||||
 | 
					behind the scenes and users have not to deal with them explicitly. Furthermore,
 | 
				
			||||||
 | 
					they've no name, cannot be searched and wouldn't have member functions to expose
 | 
				
			||||||
 | 
					anyway.<br/>
 | 
				
			||||||
 | 
					Similarly, conversion functions aren't directly accessible. They're used
 | 
				
			||||||
 | 
					internally by `meta_any` and the meta objects when needed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Meta types and meta objects in general contain much more than what was said.
 | 
				
			||||||
 | 
					Refer to the inline documentation for further details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Container support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The runtime reflection system also supports containers of all types.<br/>
 | 
				
			||||||
 | 
					Moreover, _containers_ doesn't necessarily mean those offered by the C++
 | 
				
			||||||
 | 
					standard library. In fact, user defined data structures can also work with the
 | 
				
			||||||
 | 
					meta system in many cases.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To make a container be recognized as such by the meta system, users are required
 | 
				
			||||||
 | 
					to provide specializations for either the `meta_sequence_container_traits` class
 | 
				
			||||||
 | 
					or the `meta_associative_container_traits` class, according to the actual _type_
 | 
				
			||||||
 | 
					of the container.<br/>
 | 
				
			||||||
 | 
					`EnTT` already exports the specializations for some common classes. In
 | 
				
			||||||
 | 
					particular:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `std::vector`, `std::array`, `std::deque` and `std::list` (but not
 | 
				
			||||||
 | 
					  `std::forward_list`) are supported as _sequence containers_.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `std::map`, `std::set` and their unordered counterparts are supported as
 | 
				
			||||||
 | 
					  _associative containers_.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's important to include the header file `container.hpp` to make these
 | 
				
			||||||
 | 
					specializations available to the compiler when needed.<br/>
 | 
				
			||||||
 | 
					The same file also contains many examples for the users that are interested in
 | 
				
			||||||
 | 
					making their own containers available to the meta system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When a specialization of the `meta_sequence_container_traits` class exists, the
 | 
				
			||||||
 | 
					meta system treats the wrapped type as a sequence container. In a similar way,
 | 
				
			||||||
 | 
					a type is treated as an associative container if a specialization of the
 | 
				
			||||||
 | 
					`meta_associative_container_traits` class is found for it.<br/>
 | 
				
			||||||
 | 
					Proxy objects are returned by dedicated members of the `meta_any` class. The
 | 
				
			||||||
 | 
					following is a deliberately verbose example of how users can access a proxy
 | 
				
			||||||
 | 
					object for a sequence container:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					std::vector<int> vec{1, 2, 3};
 | 
				
			||||||
 | 
					entt::meta_any any = entt::forward_as_meta(vec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(any.type().is_sequence_container()) {
 | 
				
			||||||
 | 
					    if(auto view = any.as_sequence_container(); view) {
 | 
				
			||||||
 | 
					        // ...
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The method to use to get a proxy object for associative containers is
 | 
				
			||||||
 | 
					`as_associative_container` instead.<br/>
 | 
				
			||||||
 | 
					It's not necessary to perform a double check actually. Instead, it's enough to
 | 
				
			||||||
 | 
					query the meta type or verify that the proxy object is valid. In fact, proxies
 | 
				
			||||||
 | 
					are contextually convertible to bool to check for validity. For example, invalid
 | 
				
			||||||
 | 
					proxies are returned when the wrapped object isn't a container.<br/>
 | 
				
			||||||
 | 
					In all cases, users aren't expected to _reflect_ containers explicitly. It's
 | 
				
			||||||
 | 
					sufficient to assign a container for which a specialization of the traits
 | 
				
			||||||
 | 
					classes exists to a `meta_any` object to be able to get its proxy object.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The interface of the `meta_sequence_container` proxy object is the same for all
 | 
				
			||||||
 | 
					types of sequence containers, although the available features differ from case
 | 
				
			||||||
 | 
					to case. In particular:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `value_type` member function returns the meta type of the elements.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `size` member function returns the number of elements in the container as
 | 
				
			||||||
 | 
					  an unsigned integer value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `resize` member function allows to resize the wrapped container and
 | 
				
			||||||
 | 
					  returns true in case of success.<br/>
 | 
				
			||||||
 | 
					  For example, it's not possible to resize fixed size containers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `clear` member function allows to clear the wrapped container and returns
 | 
				
			||||||
 | 
					  true in case of success.<br/>
 | 
				
			||||||
 | 
					  For example, it's not possible to clear fixed size containers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `begin` and `end` member functions return opaque iterators that is used to
 | 
				
			||||||
 | 
					  iterate the container directly:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  for(entt::meta_any element: view) {
 | 
				
			||||||
 | 
					      // ...
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  In all cases, given an underlying container of type `C`, the returned element
 | 
				
			||||||
 | 
					  contains an object of type `C::value_type` which therefore depends on the
 | 
				
			||||||
 | 
					  actual container.<br/>
 | 
				
			||||||
 | 
					  All meta iterators are input iterators and don't offer an indirection operator
 | 
				
			||||||
 | 
					  on purpose.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `insert` member function is used to add elements to the container. It
 | 
				
			||||||
 | 
					  accepts a meta iterator and the element to insert:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto last = view.end();
 | 
				
			||||||
 | 
					  // appends an integer to the container
 | 
				
			||||||
 | 
					  view.insert(last, 42);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This function returns a meta iterator pointing to the inserted element and a
 | 
				
			||||||
 | 
					  boolean value to indicate whether the operation was successful or not. A call
 | 
				
			||||||
 | 
					  to `insert` may silently fail in case of fixed size containers or whether the
 | 
				
			||||||
 | 
					  arguments aren't at least convertible to the required types.<br/>
 | 
				
			||||||
 | 
					  Since meta iterators are contextually convertible to bool, users can rely on
 | 
				
			||||||
 | 
					  them to know if the operation failed on the actual container or upstream, for
 | 
				
			||||||
 | 
					  example due to an argument conversion problem.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `erase` member function is used to remove elements from the container. It
 | 
				
			||||||
 | 
					  accepts a meta iterator to the element to remove:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto first = view.begin();
 | 
				
			||||||
 | 
					  // removes the first element from the container
 | 
				
			||||||
 | 
					  view.erase(first);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This function returns a meta iterator following the last removed element and a
 | 
				
			||||||
 | 
					  boolean value to indicate whether the operation was successful or not. A call
 | 
				
			||||||
 | 
					  to `erase` may silently fail in case of fixed size containers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `operator[]` is used to access container elements. It accepts a single
 | 
				
			||||||
 | 
					  argument, the position of the element to return:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  for(std::size_t pos{}, last = view.size(); pos < last; ++pos) {
 | 
				
			||||||
 | 
					      entt::meta_any value = view[pos];
 | 
				
			||||||
 | 
					      // ...
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The function returns instances of `meta_any` that directly refer to the actual
 | 
				
			||||||
 | 
					  elements. Modifying the returned object directly modifies the element inside
 | 
				
			||||||
 | 
					  the container.<br/>
 | 
				
			||||||
 | 
					  Depending on the underlying sequence container, this operation may not be as
 | 
				
			||||||
 | 
					  efficient. For example, in the case of an `std::list`, a positional access
 | 
				
			||||||
 | 
					  translates to a linear visit of the list itself (probably not what the user
 | 
				
			||||||
 | 
					  expects).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Similarly, also the interface of the `meta_associative_container` proxy object
 | 
				
			||||||
 | 
					is the same for all types of associative containers. However, there are some
 | 
				
			||||||
 | 
					differences in behavior in the case of key-only containers. In particular:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `key_only` member function returns true if the wrapped container is a
 | 
				
			||||||
 | 
					  key-only one.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `key_type` member function returns the meta type of the keys.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `mapped_type` member function returns an invalid meta type for key-only
 | 
				
			||||||
 | 
					  containers and the meta type of the mapped values for all other types of
 | 
				
			||||||
 | 
					  containers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `value_type` member function returns the meta type of the elements.<br/>
 | 
				
			||||||
 | 
					  For example, it returns the meta type of `int` for `std::set<int>` while it
 | 
				
			||||||
 | 
					  returns the meta type of `std::pair<const int, char>` for
 | 
				
			||||||
 | 
					  `std::map<int, char>`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `size` member function returns the number of elements in the container as
 | 
				
			||||||
 | 
					  an unsigned integer value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `clear` member function allows to clear the wrapped container and returns
 | 
				
			||||||
 | 
					  true in case of success.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `begin` and `end` member functions return opaque iterators that are used
 | 
				
			||||||
 | 
					  to iterate the container directly:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  for(std::pair<entt::meta_any, entt::meta_any> element: view) {
 | 
				
			||||||
 | 
					      // ...
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  In all cases, given an underlying container of type `C`, the returned element
 | 
				
			||||||
 | 
					  is a key-value pair where the key has type `C::key_type` and the value has
 | 
				
			||||||
 | 
					  type `C::mapped_type`. Since key-only containers don't have a mapped type,
 | 
				
			||||||
 | 
					  their _value_ is nothing more than an invalid `meta_any` object.<br/>
 | 
				
			||||||
 | 
					  All meta iterators are input iterators and don't offer an indirection operator
 | 
				
			||||||
 | 
					  on purpose.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  While the accessed key is usually constant in the associative containers and
 | 
				
			||||||
 | 
					  is therefore returned by copy, the value (if any) is wrapped by an instance of
 | 
				
			||||||
 | 
					  `meta_any` that directly refers to the actual element. Modifying it directly
 | 
				
			||||||
 | 
					  modifies the element inside the container.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `insert` member function is used to add elements to a container. It gets
 | 
				
			||||||
 | 
					  two arguments, respectively the key and the value to insert:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  auto last = view.end();
 | 
				
			||||||
 | 
					  // appends an integer to the container
 | 
				
			||||||
 | 
					  view.insert(last.handle(), 42, 'c');
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This function returns a boolean value to indicate whether the operation was
 | 
				
			||||||
 | 
					  successful or not. A call to `insert` may fail when the arguments aren't at
 | 
				
			||||||
 | 
					  least convertible to the required types.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `erase` member function is used to remove elements from a container. It
 | 
				
			||||||
 | 
					  gets a single argument, the key to remove:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  view.erase(42);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This function returns a boolean value to indicate whether the operation was
 | 
				
			||||||
 | 
					  successful or not. A call to `erase` may fail when the argument isn't at least
 | 
				
			||||||
 | 
					  convertible to the required type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The `operator[]` is used to access elements in a container. It gets a single
 | 
				
			||||||
 | 
					  argument, the key of the element to return:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  entt::meta_any value = view[42];
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The function returns instances of `meta_any` that directly refer to the actual
 | 
				
			||||||
 | 
					  elements. Modifying the returned object directly modifies the element inside
 | 
				
			||||||
 | 
					  the container.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Container support is minimal but likely sufficient to satisfy all needs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Pointer-like types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As with containers, it's also possible to _tell_ to the meta system which types
 | 
				
			||||||
 | 
					are _pointers_. This makes it possible to dereference instances of `meta_any`,
 | 
				
			||||||
 | 
					thus obtaining light _references_ to pointed objects that are also correctly
 | 
				
			||||||
 | 
					associated with their meta types.<br/>
 | 
				
			||||||
 | 
					To make the meta system recognize a type as _pointer-like_, users can specialize
 | 
				
			||||||
 | 
					the `is_meta_pointer_like` class. `EnTT` already exports the specializations for
 | 
				
			||||||
 | 
					some common classes. In particular:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* All types of raw pointers.
 | 
				
			||||||
 | 
					* `std::unique_ptr` and `std::shared_ptr`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's important to include the header file `pointer.hpp` to make these
 | 
				
			||||||
 | 
					specializations available to the compiler when needed.<br/>
 | 
				
			||||||
 | 
					The same file also contains many examples for the users that are interested in
 | 
				
			||||||
 | 
					making their own pointer-like types available to the meta system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When a type is recognized as a pointer-like one by the meta system, it's
 | 
				
			||||||
 | 
					possible to dereference the instances of `meta_any` that contain these objects.
 | 
				
			||||||
 | 
					The following is a deliberately verbose example to show how to use this feature:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					int value = 42;
 | 
				
			||||||
 | 
					// meta type equivalent to that of int *
 | 
				
			||||||
 | 
					entt::meta_any any{&value};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(any.type().is_pointer_like()) {
 | 
				
			||||||
 | 
					    // meta type equivalent to that of int
 | 
				
			||||||
 | 
					    if(entt::meta_any ref = *any; ref) {
 | 
				
			||||||
 | 
					        // ...
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's not necessary to perform a double check. Instead, it's enough to query the
 | 
				
			||||||
 | 
					meta type or verify that the returned object is valid. For example, invalid
 | 
				
			||||||
 | 
					instances are returned when the wrapped object isn't a pointer-like type.<br/>
 | 
				
			||||||
 | 
					Dereferencing a pointer-like object returns an instance of `meta_any` which
 | 
				
			||||||
 | 
					_refers_ to the pointed object. Modifying it means modifying the pointed object
 | 
				
			||||||
 | 
					directly (unless the returned element is const).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In general, _dereferencing_ a pointer-like type boils down to a `*ptr`. However,
 | 
				
			||||||
 | 
					`EnTT` also supports classes that don't offer an `operator*`. In particular:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* It's possible to exploit a solution based on ADL lookup by offering a function
 | 
				
			||||||
 | 
					  (also a template one) named `dereference_meta_pointer_like`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  template<typename Type>
 | 
				
			||||||
 | 
					  Type & dereference_meta_pointer_like(const custom_pointer_type<Type> &ptr) {
 | 
				
			||||||
 | 
					      return ptr.deref();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* When not in control of the type's namespace, it's possible to inject into the
 | 
				
			||||||
 | 
					  `entt` namespace a specialization of the `adl_meta_pointer_like` class
 | 
				
			||||||
 | 
					  template to bypass the adl lookup as a whole:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  template<typename Type>
 | 
				
			||||||
 | 
					  struct entt::adl_meta_pointer_like<custom_pointer_type<Type>> {
 | 
				
			||||||
 | 
					      static decltype(auto) dereference(const custom_pointer_type<Type> &ptr) {
 | 
				
			||||||
 | 
					          return ptr.deref();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In all other cases and when dereferencing a pointer works as expected regardless
 | 
				
			||||||
 | 
					of the pointed type, no user intervention is required.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Template information
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Meta types also provide a minimal set of information about the _nature_ of the
 | 
				
			||||||
 | 
					original type in case it's a class template.<br/>
 | 
				
			||||||
 | 
					By default, this works out of the box and requires no user action. However, it's
 | 
				
			||||||
 | 
					important to include the header file `template.hpp` to make this information
 | 
				
			||||||
 | 
					available to the compiler when needed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Meta template information are easily found:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// this method returns true if the type is recognized as a class template specialization
 | 
				
			||||||
 | 
					if(auto type = entt::resolve<std::shared_ptr<my_type>>(); type.is_template_specialization()) {
 | 
				
			||||||
 | 
					    // meta type of the class template conveniently wrapped by entt::meta_class_template_tag
 | 
				
			||||||
 | 
					    auto class_type = type.template_type();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // number of template arguments
 | 
				
			||||||
 | 
					    std::size_t arity = type.template_arity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // meta type of the i-th argument
 | 
				
			||||||
 | 
					    auto arg_type = type.template_arg(0u);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Typically, when template information for a type are required, what the library
 | 
				
			||||||
 | 
					provides is sufficient. However, there are some cases where a user may want more
 | 
				
			||||||
 | 
					details or a different set of information.<br/>
 | 
				
			||||||
 | 
					Consider the case of a class template that is meant to wrap function types:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					template<typename>
 | 
				
			||||||
 | 
					struct function_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Ret, typename... Args>
 | 
				
			||||||
 | 
					struct function_type<Ret(Args...)> {};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this case, rather than the function type, it might be useful to provide the
 | 
				
			||||||
 | 
					return type and unpacked arguments as if they were different template parameters
 | 
				
			||||||
 | 
					for the original class template.<br/>
 | 
				
			||||||
 | 
					To achieve this, users must enter the library internals and provide their own
 | 
				
			||||||
 | 
					specialization for the class template `entt::meta_template_traits`, such as:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					template<typename Ret, typename... Args>
 | 
				
			||||||
 | 
					struct entt::meta_template_traits<function_type<Ret(Args...)>> {
 | 
				
			||||||
 | 
					    using class_type = meta_class_template_tag<function_type>;
 | 
				
			||||||
 | 
					    using args_type = type_list<Ret, Args...>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The reflection system doesn't verify the accuracy of the information nor infer a
 | 
				
			||||||
 | 
					correspondence between real types and meta types.<br/>
 | 
				
			||||||
 | 
					Therefore, the specialization is used as is and the information it contains is
 | 
				
			||||||
 | 
					associated with the appropriate type when required.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Automatic conversions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In C++, there are a number of conversions allowed between arithmetic types that
 | 
				
			||||||
 | 
					make it convenient to work with this kind of data.<br/>
 | 
				
			||||||
 | 
					If this were to be translated into explicit registrations with the reflection
 | 
				
			||||||
 | 
					system, it would result in a long series of instructions such as the following:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta<int>()
 | 
				
			||||||
 | 
					    .conv<bool>()
 | 
				
			||||||
 | 
					    .conv<char>()
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					    .conv<double>();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Repeated for each type eligible to undergo this type of conversions. This is
 | 
				
			||||||
 | 
					both error-prone and repetitive.<br/>
 | 
				
			||||||
 | 
					Similarly, the language allows users to silently convert unscoped enums to their
 | 
				
			||||||
 | 
					underlying types and offers what it takes to do the same for scoped enums. It
 | 
				
			||||||
 | 
					would result in the following if it were to be done explicitly:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta<my_enum>()
 | 
				
			||||||
 | 
					    .conv<std::underlying_type_t<my_enum>>();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Fortunately, all of this can also be avoided. `EnTT` offers implicit support for
 | 
				
			||||||
 | 
					these types of conversions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta_any any{42};
 | 
				
			||||||
 | 
					any.allow_cast<double>();
 | 
				
			||||||
 | 
					double value = any.cast<double>();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					With no need for registration, the conversion takes place automatically under
 | 
				
			||||||
 | 
					the hood. The same goes for a call to `allow_cast` involving a meta type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta_type type = entt::resolve<int>();
 | 
				
			||||||
 | 
					entt::meta_any any{my_enum::a_value};
 | 
				
			||||||
 | 
					any.allow_cast(type);
 | 
				
			||||||
 | 
					int value = any.cast<int>();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This makes working with arithmetic types and scoped or unscoped enums as easy as
 | 
				
			||||||
 | 
					it is in C++.<br/>
 | 
				
			||||||
 | 
					It's still possible to set up conversion functions manually and these are always
 | 
				
			||||||
 | 
					preferred over the automatic ones.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Implicitly generated default constructor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Creating objects of default constructible types through the reflection system
 | 
				
			||||||
 | 
					while not having to explicitly register the meta type or its default constructor
 | 
				
			||||||
 | 
					is also possible.<br/>
 | 
				
			||||||
 | 
					For example, in the case of primitive types like `int` or `char`, but not just
 | 
				
			||||||
 | 
					them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For default constructible types only, default constructors are automatically
 | 
				
			||||||
 | 
					defined and associated with their meta types, whether they are explicitly or
 | 
				
			||||||
 | 
					implicitly generated.<br/>
 | 
				
			||||||
 | 
					Therefore, this is all is needed to construct an integer from its meta type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::resolve<int>().construct();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Where the meta type is for example the one returned from a meta container,
 | 
				
			||||||
 | 
					useful for building keys without knowing or having to register the actual types.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In all cases, when users register default constructors, they are preferred both
 | 
				
			||||||
 | 
					during searches and when the `construct` member function is invoked.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## From void to any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sometimes all a user has is an opaque pointer to an object of a known meta type.
 | 
				
			||||||
 | 
					It would be handy in this case to be able to construct a `meta_any` element from
 | 
				
			||||||
 | 
					it.<br/>
 | 
				
			||||||
 | 
					For this purpose, the `meta_type` class offers a `from_void` member function
 | 
				
			||||||
 | 
					designed to convert an opaque pointer into a `meta_any`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta_any any = entt::resolve(id).from_void(element);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unfortunately, it's not possible to do a check on the actual type. Therefore,
 | 
				
			||||||
 | 
					this call can be considered as a _static cast_ with all its _problems_.<br/>
 | 
				
			||||||
 | 
					On the other hand, the ability to construct a `meta_any` from an opaque pointer
 | 
				
			||||||
 | 
					opens the door to some pretty interesting uses that are worth exploring.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Policies: the more, the less
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Policies are a kind of compile-time directives that can be used when registering
 | 
				
			||||||
 | 
					reflection information.<br/>
 | 
				
			||||||
 | 
					Their purpose is to require slightly different behavior than the default in some
 | 
				
			||||||
 | 
					specific cases. For example, when reading a given data member, its value is
 | 
				
			||||||
 | 
					returned wrapped in a `meta_any` object which, by default, makes a copy of it.
 | 
				
			||||||
 | 
					For large objects or if the caller wants to access the original instance, this
 | 
				
			||||||
 | 
					behavior isn't desirable. Policies are there to offer a solution to this and
 | 
				
			||||||
 | 
					other problems.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There are a few alternatives available at the moment:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The _as-is_ policy, associated with the type `entt::as_is_t`.<br/>
 | 
				
			||||||
 | 
					  This is the default policy. In general, it should never be used explicitly,
 | 
				
			||||||
 | 
					  since it's implicitly selected if no other policy is specified.<br/>
 | 
				
			||||||
 | 
					  In this case, the return values of the functions as well as the properties
 | 
				
			||||||
 | 
					  exposed as data members are always returned by copy in a dedicated wrapper and
 | 
				
			||||||
 | 
					  therefore associated with their original meta types.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The _as-void_ policy, associated with the type `entt::as_void_t`.<br/>
 | 
				
			||||||
 | 
					  Its purpose is to discard the return value of a meta object, whatever it is,
 | 
				
			||||||
 | 
					  thus making it appear as if its type were `void`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  entt::meta<my_type>().func<&my_type::member_function, entt::as_void_t>("member"_hs);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If the use with functions is obvious, perhaps less so is use with constructors
 | 
				
			||||||
 | 
					  and data members. In the first case, the returned wrapper is always empty even
 | 
				
			||||||
 | 
					  though the constructor is still invoked. In the second case, the property
 | 
				
			||||||
 | 
					  isn't accessible for reading instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The _as-ref_ and _as-cref_ policies, associated with the types
 | 
				
			||||||
 | 
					  `entt::as_ref_t` and `entt::as_cref_t`.<br/>
 | 
				
			||||||
 | 
					  They allow to build wrappers that act as references to unmanaged objects.
 | 
				
			||||||
 | 
					  Accessing the object contained in the wrapper for which the _reference_ was
 | 
				
			||||||
 | 
					  requested makes it possible to directly access the instance used to initialize
 | 
				
			||||||
 | 
					  the wrapper itself:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  entt::meta<my_type>().data<&my_type::data_member, entt::as_ref_t>("member"_hs);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  These policies work with constructors (for example, when objects are taken
 | 
				
			||||||
 | 
					  from an external container rather than created on demand), data members and
 | 
				
			||||||
 | 
					  functions in general.<br/>
 | 
				
			||||||
 | 
					  If on the one hand `as_cref_t` always forces the return type to be const,
 | 
				
			||||||
 | 
					  `as_ref_t` _adapts_ to the constness of the passed object and to that of the
 | 
				
			||||||
 | 
					  return type if any.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Some uses are rather trivial, but it's useful to note that there are some less
 | 
				
			||||||
 | 
					obvious corner cases that can in turn be solved with the use of policies.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Named constants and enums
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As mentioned, the `data` member function is used to reflect constants of any
 | 
				
			||||||
 | 
					type.<br/>
 | 
				
			||||||
 | 
					This allows users to create meta types for enums that work exactly like any
 | 
				
			||||||
 | 
					other meta type built from a class. Similarly, arithmetic types are _enriched_
 | 
				
			||||||
 | 
					with constants of special meaning where required.<br/>
 | 
				
			||||||
 | 
					All values thus exported appear to users as if they were constant data members
 | 
				
			||||||
 | 
					of the reflected types. This avoids the need to _export_ what is the difference
 | 
				
			||||||
 | 
					between enums and classes in C++ directly in the space of the reflected types.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Exposing constant values or elements from an enum is quite simple:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta<my_enum>()
 | 
				
			||||||
 | 
					    .data<my_enum::a_value>("a_value"_hs)
 | 
				
			||||||
 | 
					    .data<my_enum::another_value>("another_value"_hs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					entt::meta<int>().data<2048>("max_int"_hs);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Accessing them is trivial as well. It's a matter of doing the following, as with
 | 
				
			||||||
 | 
					any other data member of a meta type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					auto value = entt::resolve<my_enum>().data("a_value"_hs).get({}).cast<my_enum>();
 | 
				
			||||||
 | 
					auto max = entt::resolve<int>().data("max_int"_hs).get({}).cast<int>();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All this happens behind the scenes without any allocation because of the small
 | 
				
			||||||
 | 
					object optimization performed by the `meta_any` class.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Properties and meta objects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sometimes (for example, when it comes to creating an editor) it might be useful
 | 
				
			||||||
 | 
					to attach properties to the meta objects created. Fortunately, this is possible
 | 
				
			||||||
 | 
					for most of them:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta<my_type>().type("reflected_type"_hs).prop("tooltip"_hs, "message");
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Properties are always in the key/value form. The key is a numeric identifier,
 | 
				
			||||||
 | 
					mostly similar to the identifier used to register meta objects. There are no
 | 
				
			||||||
 | 
					restrictions on the type of the value instead, as long as it's movable.<br/>
 | 
				
			||||||
 | 
					Key only properties are also supported out of the box:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta<my_type>().type("reflected_type"_hs).prop(my_enum::key_only);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To attach multiple properties to a meta object, just invoke `prop` more than
 | 
				
			||||||
 | 
					once.<br/>
 | 
				
			||||||
 | 
					It's also possible to call `prop` at different times, as long as the factory is
 | 
				
			||||||
 | 
					reset to the meta object of interest.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The meta objects for which properties are supported are currently meta types,
 | 
				
			||||||
 | 
					meta data and meta functions.<br/>
 | 
				
			||||||
 | 
					These types also offer a couple of member functions named `prop` to iterate all
 | 
				
			||||||
 | 
					properties at once or to search a specific property by key:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// iterate all properties of a meta type
 | 
				
			||||||
 | 
					for(auto &&[id, prop]: entt::resolve<my_type>().prop()) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// search for a given property by name
 | 
				
			||||||
 | 
					auto prop = entt::resolve<my_type>().prop("tooltip"_hs);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Meta properties are objects having a fairly poor interface, all in all. They
 | 
				
			||||||
 | 
					only provide the `value` member function to retrieve the contained value in the
 | 
				
			||||||
 | 
					form of a `meta_any` object.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Unregister types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A type registered with the reflection system can also be _unregistered_. This
 | 
				
			||||||
 | 
					means unregistering all its data members, member functions, conversion functions
 | 
				
			||||||
 | 
					and so on. However, base classes aren't unregistered as well, since they don't
 | 
				
			||||||
 | 
					necessarily depend on it.<br/>
 | 
				
			||||||
 | 
					Roughly speaking, unregistering a type means disconnecting all associated meta
 | 
				
			||||||
 | 
					objects from it and making its identifier no longer available:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta_reset<my_type>();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's also possible to reset types by their unique identifiers:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta_reset("my_type"_hs);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Finally, there exists a non-template overload of the `meta_reset` function that
 | 
				
			||||||
 | 
					doesn't accept arguments and resets all meta types at once:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta_reset();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A type can be re-registered later with a completely different name and form.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Meta context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All meta types and their parts are created at runtime and stored in a default
 | 
				
			||||||
 | 
					_context_. This is obtained via a service locator as:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					auto &&context = entt::locator<entt::meta_context>::value_or();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					By itself, a context is an opaque object that the user cannot do much with.
 | 
				
			||||||
 | 
					However, users can replace an existing context with another at any time:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta_context other{};
 | 
				
			||||||
 | 
					auto &&context = entt::locator<entt::meta_context>::value_or();
 | 
				
			||||||
 | 
					std::swap(context, other);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is useful for testing purposes or to define multiple context objects with
 | 
				
			||||||
 | 
					different meta type to use as appropriate.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If _replacing_ the default context isn't enough, `EnTT` also offers the ability
 | 
				
			||||||
 | 
					to use multiple and externally managed contexts with the runtime reflection
 | 
				
			||||||
 | 
					system.<br/>
 | 
				
			||||||
 | 
					For example, to create new meta types within a context other than the default
 | 
				
			||||||
 | 
					one, simply pass it as an argument to the `meta` call:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta_ctx context{};
 | 
				
			||||||
 | 
					auto factory = entt::meta<my_type>(context).type("reflected_type"_hs);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					By doing so, the new meta type isn't available in the default context but is
 | 
				
			||||||
 | 
					usable by passing around the new context when needed, such as when creating a
 | 
				
			||||||
 | 
					new `meta_any` object:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta_any any{context, std::in_place_type<my_type>};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Similarly, to search for meta types in a context other than the default one,
 | 
				
			||||||
 | 
					it's necessary to pass it to the `resolve` function:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::meta_type type = entt::resolve(context, "reflected_type"_hs)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					More generally, when using externally managed contexts, it's always required to
 | 
				
			||||||
 | 
					provide the system with the context to use, at least at the _entry point_.<br/>
 | 
				
			||||||
 | 
					For example, once the `meta_type` instant is obtained, it's no longer necessary
 | 
				
			||||||
 | 
					to pass the context around as the meta type takes the information with it and
 | 
				
			||||||
 | 
					eventually propagates it to all its parts.<br/>
 | 
				
			||||||
 | 
					On the other hand, it's necessary to instruct the library on where meta types
 | 
				
			||||||
 | 
					are to be fetched when `meta_any`s and `meta_handle`s are constructed, a factory
 | 
				
			||||||
 | 
					created or a meta type resolved.
 | 
				
			||||||
							
								
								
									
										357
									
								
								external/entt/entt/docs/md/poly.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										357
									
								
								external/entt/entt/docs/md/poly.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,357 @@
 | 
				
			|||||||
 | 
					# Crash Course: poly
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Introduction](#introduction)
 | 
				
			||||||
 | 
					  * [Other libraries](#other-libraries)
 | 
				
			||||||
 | 
					* [Concept and implementation](#concept-and-implementation)
 | 
				
			||||||
 | 
					  * [Deduced interface](#deduced-interface)
 | 
				
			||||||
 | 
					  * [Defined interface](#defined-interface)
 | 
				
			||||||
 | 
					  * [Fulfill a concept](#fulfill-a-concept)
 | 
				
			||||||
 | 
					* [Inheritance](#inheritance)
 | 
				
			||||||
 | 
					* [Static polymorphism in the wild](#static-polymorphism-in-the-wild)
 | 
				
			||||||
 | 
					* [Storage size and alignment requirement](#storage-size-and-alignment-requirement)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Static polymorphism is a very powerful tool in C++, albeit sometimes cumbersome
 | 
				
			||||||
 | 
					to obtain.<br/>
 | 
				
			||||||
 | 
					This module aims to make it simple and easy to use.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The library allows to define _concepts_ as interfaces to fulfill with concrete
 | 
				
			||||||
 | 
					classes without having to inherit from a common base.<br/>
 | 
				
			||||||
 | 
					Among others, this is one of the advantages of static polymorphism in general
 | 
				
			||||||
 | 
					and of a generic wrapper like that offered by the `poly` class template in
 | 
				
			||||||
 | 
					particular.<br/>
 | 
				
			||||||
 | 
					The result is an object to pass around as such and not through a reference or a
 | 
				
			||||||
 | 
					pointer, as it happens when it comes to working with dynamic polymorphism.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Since the `poly` class template makes use of `entt::any` internally, it also
 | 
				
			||||||
 | 
					supports most of its feature. For example, the possibility to create aliases to
 | 
				
			||||||
 | 
					existing and thus unmanaged objects. This allows users to exploit the static
 | 
				
			||||||
 | 
					polymorphism while maintaining ownership of objects.<br/>
 | 
				
			||||||
 | 
					Likewise, the `poly` class template also benefits from the small buffer
 | 
				
			||||||
 | 
					optimization offered by the `entt::any` class and therefore minimizes the number
 | 
				
			||||||
 | 
					of allocations, avoiding them altogether where possible.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Other libraries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There are some very interesting libraries regarding static polymorphism.<br/>
 | 
				
			||||||
 | 
					The ones that I like more are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [`dyno`](https://github.com/ldionne/dyno): runtime polymorphism done right.
 | 
				
			||||||
 | 
					* [`Poly`](https://github.com/facebook/folly/blob/master/folly/docs/Poly.md):
 | 
				
			||||||
 | 
					  a class template that makes it easy to define a type-erasing polymorphic
 | 
				
			||||||
 | 
					  object wrapper.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The former is admittedly an experimental library, with many interesting ideas.
 | 
				
			||||||
 | 
					I've some doubts about the usefulness of some feature in real world projects,
 | 
				
			||||||
 | 
					but perhaps my lack of experience comes into play here. In my opinion, its only
 | 
				
			||||||
 | 
					flaw is the API which I find slightly more cumbersome than other solutions.<br/>
 | 
				
			||||||
 | 
					The latter was undoubtedly a source of inspiration for this module, although I
 | 
				
			||||||
 | 
					opted for different choices in the implementation of both the final API and some
 | 
				
			||||||
 | 
					feature.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Either way, the authors are gurus of the C++ community, people I only have to
 | 
				
			||||||
 | 
					learn from.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Concept and implementation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The first thing to do to create a _type-erasing polymorphic object wrapper_ (to
 | 
				
			||||||
 | 
					use the terminology introduced by Eric Niebler) is to define a _concept_ that
 | 
				
			||||||
 | 
					types will have to adhere to.<br/>
 | 
				
			||||||
 | 
					For this purpose, the library offers a single class that supports both deduced
 | 
				
			||||||
 | 
					and fully defined interfaces. Although having interfaces deduced automatically
 | 
				
			||||||
 | 
					is convenient and allows users to write less code in most cases, it has some
 | 
				
			||||||
 | 
					limitations and it's therefore useful to be able to get around the deduction by
 | 
				
			||||||
 | 
					providing a custom definition for the static virtual table.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once the interface is defined, a generic implementation is needed to fulfill the
 | 
				
			||||||
 | 
					concept itself.<br/>
 | 
				
			||||||
 | 
					Also in this case, the library allows customizations based on types or families
 | 
				
			||||||
 | 
					of types, so as to be able to go beyond the generic case where necessary.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Deduced interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is how a concept with a deduced interface is defined:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct Drawable: entt::type_list<> {
 | 
				
			||||||
 | 
					    template<typename Base>
 | 
				
			||||||
 | 
					    struct type: Base {
 | 
				
			||||||
 | 
					        void draw() { this->template invoke<0>(*this); }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's recognizable by the fact that it inherits from an empty type list.<br/>
 | 
				
			||||||
 | 
					Functions can also be const, accept any number of parameters and return a type
 | 
				
			||||||
 | 
					other than `void`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct Drawable: entt::type_list<> {
 | 
				
			||||||
 | 
					    template<typename Base>
 | 
				
			||||||
 | 
					    struct type: Base {
 | 
				
			||||||
 | 
					        bool draw(int pt) const { return this->template invoke<0>(*this, pt); }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this case, all parameters are passed to `invoke` after the reference to
 | 
				
			||||||
 | 
					`this` and the return value is whatever the internal call returns.<br/>
 | 
				
			||||||
 | 
					As for `invoke`, this is a name that is injected into the _concept_ through
 | 
				
			||||||
 | 
					`Base`, from which one must necessarily inherit. Since it's also a dependent
 | 
				
			||||||
 | 
					name, the `this-> template` form is unfortunately necessary due to the rules of
 | 
				
			||||||
 | 
					the language. However, there also exists an alternative that goes through an
 | 
				
			||||||
 | 
					external call:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct Drawable: entt::type_list<> {
 | 
				
			||||||
 | 
					    template<typename Base>
 | 
				
			||||||
 | 
					    struct type: Base {
 | 
				
			||||||
 | 
					        void draw() const { entt::poly_call<0>(*this); }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once the _concept_ is defined, users must provide a generic implementation of it
 | 
				
			||||||
 | 
					in order to tell the system how any type can satisfy its requirements. This is
 | 
				
			||||||
 | 
					done via an alias template within the concept itself.<br/>
 | 
				
			||||||
 | 
					The index passed as a template parameter to either `invoke` or `poly_call`
 | 
				
			||||||
 | 
					refers to how this alias is defined.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Defined interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A fully defined concept is no different to one for which the interface is
 | 
				
			||||||
 | 
					deduced, with the only difference that the list of types is not empty this time:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct Drawable: entt::type_list<void()> {
 | 
				
			||||||
 | 
					    template<typename Base>
 | 
				
			||||||
 | 
					    struct type: Base {
 | 
				
			||||||
 | 
					        void draw() { entt::poly_call<0>(*this); }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Again, parameters and return values other than `void` are allowed. Also, the
 | 
				
			||||||
 | 
					function type must be const when the method to bind to it is const:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct Drawable: entt::type_list<bool(int) const> {
 | 
				
			||||||
 | 
					    template<typename Base>
 | 
				
			||||||
 | 
					    struct type: Base {
 | 
				
			||||||
 | 
					        bool draw(int pt) const { return entt::poly_call<0>(*this, pt); }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Why should a user fully define a concept if the function types are the same as
 | 
				
			||||||
 | 
					the deduced ones?<br>
 | 
				
			||||||
 | 
					In fact, this is the limitation that can be worked around by manually defining
 | 
				
			||||||
 | 
					the static virtual table.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When things are deduced, there is an implicit constraint.<br/>
 | 
				
			||||||
 | 
					If the concept exposes a member function called `draw` with function type
 | 
				
			||||||
 | 
					`void()`, a concept is satisfied:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Either by a class that exposes a member function with the same name and the
 | 
				
			||||||
 | 
					  same signature.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Or through a lambda that makes use of existing member functions from the
 | 
				
			||||||
 | 
					  interface itself.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In other words, it's not possible to make use of functions not belonging to the
 | 
				
			||||||
 | 
					interface, even if they're part of the types that fulfill the concept.<br/>
 | 
				
			||||||
 | 
					Similarly, it's not possible to deduce a function in the static virtual table
 | 
				
			||||||
 | 
					with a function type different from that of the associated member function in
 | 
				
			||||||
 | 
					the interface itself.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Explicitly defining a static virtual table suppresses the deduction step and
 | 
				
			||||||
 | 
					allows maximum flexibility when providing the implementation for a concept.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Fulfill a concept
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `impl` alias template of a concept is used to define how it's fulfilled:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct Drawable: entt::type_list<> {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Type>
 | 
				
			||||||
 | 
					    using impl = entt::value_list<&Type::draw>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this case, it's stated that the `draw` method of a generic type is enough to
 | 
				
			||||||
 | 
					satisfy the requirements of the `Drawable` concept.<br/>
 | 
				
			||||||
 | 
					Both member functions and free functions are supported to fulfill concepts:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					void print(Type &self) { self.print(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Drawable: entt::type_list<void()> {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Type>
 | 
				
			||||||
 | 
					    using impl = entt::value_list<&print<Type>>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Likewise, as long as the parameter types and return type support conversions to
 | 
				
			||||||
 | 
					and from those of the function type referenced in the static virtual table, the
 | 
				
			||||||
 | 
					actual implementation may differ in its function type since it's erased
 | 
				
			||||||
 | 
					internally.<br/>
 | 
				
			||||||
 | 
					Moreover, the `self` parameter isn't strictly required by the system and can be
 | 
				
			||||||
 | 
					left out for free functions if not required.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Refer to the inline documentation for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Inheritance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_Concept inheritance_ is straightforward due to how poly looks like in `EnTT`.
 | 
				
			||||||
 | 
					Therefore, it's quite easy to build hierarchies of concepts if necessary.<br/>
 | 
				
			||||||
 | 
					The only constraint is that all concepts in a hierarchy must belong to the same
 | 
				
			||||||
 | 
					_family_, that is, they must be either all deduced or all defined.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For a deduced concept, inheritance is achieved in a few steps:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct DrawableAndErasable: entt::type_list<> {
 | 
				
			||||||
 | 
					    template<typename Base>
 | 
				
			||||||
 | 
					    struct type: typename Drawable::template type<Base> {
 | 
				
			||||||
 | 
					        static constexpr auto base = std::tuple_size_v<typename entt::poly_vtable<Drawable>::type>;
 | 
				
			||||||
 | 
					        void erase() { entt::poly_call<base + 0>(*this); }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Type>
 | 
				
			||||||
 | 
					    using impl = entt::value_list_cat_t<
 | 
				
			||||||
 | 
					        typename Drawable::impl<Type>,
 | 
				
			||||||
 | 
					        entt::value_list<&Type::erase>
 | 
				
			||||||
 | 
					    >;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The static virtual table is empty and must remain so.<br/>
 | 
				
			||||||
 | 
					On the other hand, `type` no longer inherits from `Base`. Instead, it forwards
 | 
				
			||||||
 | 
					its template parameter to the type exposed by the _base class_. Internally, the
 | 
				
			||||||
 | 
					_size_ of the static virtual table of the base class is used as an offset for
 | 
				
			||||||
 | 
					the local indexes.<br/>
 | 
				
			||||||
 | 
					Finally, by means of the `value_list_cat_t` utility, the implementation consists
 | 
				
			||||||
 | 
					in appending the new functions to the previous list.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As for a defined concept instead, the list of types is _extended_ in a similar
 | 
				
			||||||
 | 
					way to what is shown for the implementation of the above concept.<br/>
 | 
				
			||||||
 | 
					To do this, it's useful to declare a function that allows to convert a _concept_
 | 
				
			||||||
 | 
					into its underlying `type_list` object:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					template<typename... Type>
 | 
				
			||||||
 | 
					entt::type_list<Type...> as_type_list(const entt::type_list<Type...> &);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The definition isn't strictly required, since the function is only used through
 | 
				
			||||||
 | 
					a `decltype` as it follows:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct DrawableAndErasable: entt::type_list_cat_t<
 | 
				
			||||||
 | 
					    decltype(as_type_list(std::declval<Drawable>())),
 | 
				
			||||||
 | 
					    entt::type_list<void()>
 | 
				
			||||||
 | 
					> {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Similar to above, `type_list_cat_t` is used to concatenate the underlying static
 | 
				
			||||||
 | 
					virtual table with the new function types.<br/>
 | 
				
			||||||
 | 
					Everything else is the same as already shown instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Static polymorphism in the wild
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once the _concept_ and implementation are defined, it's possible to use the
 | 
				
			||||||
 | 
					`poly` class template to _wrap_ instances that meet the requirements:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					using drawable = entt::poly<Drawable>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct circle {
 | 
				
			||||||
 | 
					    void draw() { /* ... */ }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct square {
 | 
				
			||||||
 | 
					    void draw() { /* ... */ }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					drawable instance{circle{}};
 | 
				
			||||||
 | 
					instance->draw();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					instance = square{};
 | 
				
			||||||
 | 
					instance->draw();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This class offers a wide range of constructors, from the default one (which
 | 
				
			||||||
 | 
					returns an uninitialized `poly` object) to the copy and move constructors, as
 | 
				
			||||||
 | 
					well as the ability to create objects in-place.<br/>
 | 
				
			||||||
 | 
					Among others, there is also a constructor that allows users to wrap unmanaged
 | 
				
			||||||
 | 
					objects in a `poly` instance (either const or non-const ones):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					circle shape;
 | 
				
			||||||
 | 
					drawable instance{std::in_place_type<circle &>, shape};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Similarly, it's possible to create non-owning copies of `poly` from an existing
 | 
				
			||||||
 | 
					object:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					drawable other = instance.as_ref();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In both cases, although the interface of the `poly` object doesn't change, it
 | 
				
			||||||
 | 
					doesn't construct any element or take care of destroying the referenced objects.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note also how the underlying concept is accessed via a call to `operator->` and
 | 
				
			||||||
 | 
					not directly as `instance.draw()`.<br/>
 | 
				
			||||||
 | 
					This allows users to decouple the API of the wrapper from that of the concept.
 | 
				
			||||||
 | 
					Therefore, where `instance.data()` invokes the `data` member function of the
 | 
				
			||||||
 | 
					poly object, `instance->data()` maps directly to the functionality exposed by
 | 
				
			||||||
 | 
					the underlying concept.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Storage size and alignment requirement
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Under the hood, the `poly` class template makes use of `entt::any`. Therefore,
 | 
				
			||||||
 | 
					it can take advantage of the possibility of defining at compile-time the size of
 | 
				
			||||||
 | 
					the storage suitable for the small buffer optimization as well as the alignment
 | 
				
			||||||
 | 
					requirements:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::basic_poly<Drawable, sizeof(double[4]), alignof(double[4])>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The default size is `sizeof(double[2])`, which seems like a good compromise
 | 
				
			||||||
 | 
					between a buffer that is too large and one unable to hold anything larger than
 | 
				
			||||||
 | 
					an integer. The alignment requirement is optional and by default such that it's
 | 
				
			||||||
 | 
					the most stringent (the largest) for any object whose size is at most equal to
 | 
				
			||||||
 | 
					the one provided.<br/>
 | 
				
			||||||
 | 
					It's worth noting that providing a size of 0 (which is an accepted value in all
 | 
				
			||||||
 | 
					respects) will force the system to dynamically allocate the contained objects in
 | 
				
			||||||
 | 
					all cases.
 | 
				
			||||||
							
								
								
									
										217
									
								
								external/entt/entt/docs/md/process.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								external/entt/entt/docs/md/process.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,217 @@
 | 
				
			|||||||
 | 
					# Crash Course: cooperative scheduler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Introduction](#introduction)
 | 
				
			||||||
 | 
					* [The process](#the-process)
 | 
				
			||||||
 | 
					  * [Adaptor](#adaptor)
 | 
				
			||||||
 | 
					* [The scheduler](#the-scheduler)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Processes are a useful tool to work around the strict definition of a system and
 | 
				
			||||||
 | 
					introduce logic in a different way, usually without resorting to other component
 | 
				
			||||||
 | 
					types.<br/>
 | 
				
			||||||
 | 
					`EnTT` offers minimal support to this paradigm by introducing a few classes used
 | 
				
			||||||
 | 
					to define and execute cooperative processes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The process
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A typical task inherits from the `process` class template that stays true to the
 | 
				
			||||||
 | 
					CRTP idiom. Moreover, derived classes specify what the intended type for elapsed
 | 
				
			||||||
 | 
					times is.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A process should expose publicly the following member functions whether needed
 | 
				
			||||||
 | 
					(note that it isn't required to define a function unless the derived class wants
 | 
				
			||||||
 | 
					to _override_ the default behavior):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `void update(Delta, void *);`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This is invoked once per tick until a process is explicitly aborted or ends
 | 
				
			||||||
 | 
					  either with or without errors. Even though it's not mandatory to declare this
 | 
				
			||||||
 | 
					  member function, as a rule of thumb each process should at least define it to
 | 
				
			||||||
 | 
					  work _properly_. The `void *` parameter is an opaque pointer to user data (if
 | 
				
			||||||
 | 
					  any) forwarded directly to the process during an update.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `void init();`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This is invoked when the process joins the running queue of a scheduler. It
 | 
				
			||||||
 | 
					  happens usually as soon as the process is attached to the scheduler if it's a
 | 
				
			||||||
 | 
					  top level one, otherwise when it replaces its parent if it's a _continuation_.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `void succeeded();`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This is invoked in case of success, immediately after an update and during the
 | 
				
			||||||
 | 
					  same tick.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `void failed();`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This is invoked in case of errors, immediately after an update and during the
 | 
				
			||||||
 | 
					  same tick.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `void aborted();`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This is invoked only if a process is explicitly aborted. There is no guarantee
 | 
				
			||||||
 | 
					  that it executes in the same tick, it depends solely on whether the process is
 | 
				
			||||||
 | 
					  aborted immediately or not.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Derived classes can also change the internal state of a process by invoking
 | 
				
			||||||
 | 
					`succeed` and `fail`, as well as `pause` and `unpause` the process itself.<br/>
 | 
				
			||||||
 | 
					All these are protected member functions made available to manage the life cycle
 | 
				
			||||||
 | 
					of a process from a derived class.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Here is a minimal example for the sake of curiosity:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct my_process: entt::process<my_process, std::uint32_t> {
 | 
				
			||||||
 | 
					    using delta_type = std::uint32_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my_process(delta_type delay)
 | 
				
			||||||
 | 
					        : remaining{delay}
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void update(delta_type delta, void *) {
 | 
				
			||||||
 | 
					        remaining -= std::min(remaining, delta);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!remaining) {
 | 
				
			||||||
 | 
					            succeed();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    delta_type remaining;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Adaptor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Lambdas and functors can't be used directly with a scheduler because they aren't
 | 
				
			||||||
 | 
					properly defined processes with managed life cycles.<br/>
 | 
				
			||||||
 | 
					This class helps in filling the gap and turning lambdas and functors into
 | 
				
			||||||
 | 
					full-featured processes usable by a scheduler.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The function call operator has a signature similar to the one of the `update`
 | 
				
			||||||
 | 
					function of a process but for the fact that it receives two extra callbacks to
 | 
				
			||||||
 | 
					invoke whenever a process terminates with success or with an error:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					void(Delta delta, void *data, auto succeed, auto fail);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Parameters have the following meaning:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `delta` is the elapsed time.
 | 
				
			||||||
 | 
					* `data` is an opaque pointer to user data if any, `nullptr` otherwise.
 | 
				
			||||||
 | 
					* `succeed` is a function to call when a process terminates with success.
 | 
				
			||||||
 | 
					* `fail` is a function to call when a process terminates with errors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Both `succeed` and `fail` accept no parameters at all.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note that usually users shouldn't worry about creating adaptors at all. A
 | 
				
			||||||
 | 
					scheduler creates them internally each and every time a lambda or a functor is
 | 
				
			||||||
 | 
					used as a process.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The scheduler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A cooperative scheduler runs different processes and helps managing their life
 | 
				
			||||||
 | 
					cycles.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Each process is invoked once per tick. If it terminates, it's removed
 | 
				
			||||||
 | 
					automatically from the scheduler and it's never invoked again. Otherwise, it's
 | 
				
			||||||
 | 
					a good candidate to run one more time the next tick.<br/>
 | 
				
			||||||
 | 
					A process can also have a _child_. In this case, the parent process is replaced
 | 
				
			||||||
 | 
					with its child when it terminates and only if it returns with success. In case
 | 
				
			||||||
 | 
					of errors, both the parent process and its child are discarded. This way, it's
 | 
				
			||||||
 | 
					easy to create chain of processes to run sequentially.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Using a scheduler is straightforward. To create it, users must provide only the
 | 
				
			||||||
 | 
					type for the elapsed times and no arguments at all:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::basic_scheduler<std::uint64_t> scheduler;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Otherwise, the `scheduler` alias is also available for the most common cases. It
 | 
				
			||||||
 | 
					uses `std::uint32_t` as a default type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::scheduler scheduler;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The class has member functions to query its internal data structures, like
 | 
				
			||||||
 | 
					`empty` or `size`, as well as a `clear` utility to reset it to a clean state:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// checks if there are processes still running
 | 
				
			||||||
 | 
					const auto empty = scheduler.empty();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// gets the number of processes still running
 | 
				
			||||||
 | 
					entt::scheduler::size_type size = scheduler.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// resets the scheduler to its initial state and discards all the processes
 | 
				
			||||||
 | 
					scheduler.clear();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To attach a process to a scheduler there are mainly two ways:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* If the process inherits from the `process` class template, it's enough to
 | 
				
			||||||
 | 
					  indicate its type and submit all the parameters required to construct it to
 | 
				
			||||||
 | 
					  the `attach` member function:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  scheduler.attach<my_process>(1000u);
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Otherwise, in case of a lambda or a functor, it's enough to provide an
 | 
				
			||||||
 | 
					  instance of the class to the `attach` member function:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```cpp
 | 
				
			||||||
 | 
					  scheduler.attach([](auto...){ /* ... */ });
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In both cases, the return value is an opaque object that offers a `then` member
 | 
				
			||||||
 | 
					function used to create chains of processes to run sequentially.<br/>
 | 
				
			||||||
 | 
					As a minimal example of use:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// schedules a task in the form of a lambda function
 | 
				
			||||||
 | 
					scheduler.attach([](auto delta, void *, auto succeed, auto fail) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					// appends a child in the form of another lambda function
 | 
				
			||||||
 | 
					.then([](auto delta, void *, auto succeed, auto fail) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					// appends a child in the form of a process class
 | 
				
			||||||
 | 
					.then<my_process>(1000u);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To update a scheduler and therefore all its processes, the `update` member
 | 
				
			||||||
 | 
					function is the way to go:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// updates all the processes, no user data are provided
 | 
				
			||||||
 | 
					scheduler.update(delta);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// updates all the processes and provides them with custom data
 | 
				
			||||||
 | 
					scheduler.update(delta, &data);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In addition to these functions, the scheduler offers an `abort` member function
 | 
				
			||||||
 | 
					that is used to discard all the running processes at once:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// aborts all the processes abruptly ...
 | 
				
			||||||
 | 
					scheduler.abort(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ... or gracefully during the next tick
 | 
				
			||||||
 | 
					scheduler.abort();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										91
									
								
								external/entt/entt/docs/md/reference.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								external/entt/entt/docs/md/reference.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					# Similar projects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Introduction](#introduction)
 | 
				
			||||||
 | 
					* [Similar projects](#similar-projects)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There are many projects similar to `EnTT`, both open source and not.<br/>
 | 
				
			||||||
 | 
					Some even borrowed some ideas from this library and expressed them in different
 | 
				
			||||||
 | 
					languages.<br/>
 | 
				
			||||||
 | 
					Others developed different architectures from scratch and therefore offer
 | 
				
			||||||
 | 
					alternative solutions with their pros and cons.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you know of other similar projects out there, feel free to open an issue or a
 | 
				
			||||||
 | 
					PR and I'll be glad to add them to this page.<br/>
 | 
				
			||||||
 | 
					I hope the following lists can grow much more in the future.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Similar projects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Below an incomplete list of similar projects that I've come across so far.<br/>
 | 
				
			||||||
 | 
					If some terms or designs aren't clear, I recommend referring to the
 | 
				
			||||||
 | 
					[_ECS Back and Forth_](https://skypjack.github.io/tags/#ecs) series for all the
 | 
				
			||||||
 | 
					details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* C:
 | 
				
			||||||
 | 
					  * [destral_ecs](https://github.com/roig/destral_ecs): a single-file ECS based
 | 
				
			||||||
 | 
					    on sparse sets.
 | 
				
			||||||
 | 
					  * [Diana](https://github.com/discoloda/Diana): an ECS that uses sparse sets to
 | 
				
			||||||
 | 
					    keep track of entities in systems.
 | 
				
			||||||
 | 
					  * [Flecs](https://github.com/SanderMertens/flecs): a multithreaded archetype
 | 
				
			||||||
 | 
					    ECS based on semi-contiguous arrays rather than chunks.
 | 
				
			||||||
 | 
					  * [lent](https://github.com/nem0/lent): the Donald Trump of the ECS libraries.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* C++:
 | 
				
			||||||
 | 
					  * [decs](https://github.com/vblanco20-1/decs): a chunk based archetype ECS.
 | 
				
			||||||
 | 
					  * [ecst](https://github.com/SuperV1234/ecst): a multithreaded compile-time
 | 
				
			||||||
 | 
					    ECS that uses sparse sets to keep track of entities in systems.
 | 
				
			||||||
 | 
					  * [EntityX](https://github.com/alecthomas/entityx): a bitset based ECS that
 | 
				
			||||||
 | 
					    uses a single large matrix of components indexed with entities.
 | 
				
			||||||
 | 
					  * [Gaia-ECS](https://github.com/richardbiely/gaia-ecs): a chunk based
 | 
				
			||||||
 | 
					    archetype ECS.
 | 
				
			||||||
 | 
					  * [Polypropylene](https://github.com/pmbittner/Polypropylene): a hybrid
 | 
				
			||||||
 | 
					    solution between an ECS and dynamic mixins.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* C#
 | 
				
			||||||
 | 
					  * [Arch](https://github.com/genaray/Arch): a simple, fast and _unity entities_
 | 
				
			||||||
 | 
					    inspired archetype ECS with optional multithreading. 
 | 
				
			||||||
 | 
					  * [Entitas](https://github.com/sschmid/Entitas-CSharp): the ECS framework for
 | 
				
			||||||
 | 
					    C# and Unity, where _reactive systems_ were invented.
 | 
				
			||||||
 | 
					  * [LeoECS](https://github.com/Leopotam/ecs): simple lightweight C# Entity
 | 
				
			||||||
 | 
					    Component System framework.
 | 
				
			||||||
 | 
					  * [Svelto.ECS](https://github.com/sebas77/Svelto.ECS): a very interesting
 | 
				
			||||||
 | 
					    platform agnostic and table based ECS framework.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Go:
 | 
				
			||||||
 | 
					  * [gecs](https://github.com/tutumagi/gecs): a sparse sets based ECS inspired 
 | 
				
			||||||
 | 
					    by `EnTT`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Javascript:
 | 
				
			||||||
 | 
					  * [\@javelin/ecs](https://github.com/3mcd/javelin/tree/master/packages/ecs):
 | 
				
			||||||
 | 
					    an archetype ECS in TypeScript.
 | 
				
			||||||
 | 
					  * [ecsy](https://github.com/MozillaReality/ecsy): I haven't had the time to
 | 
				
			||||||
 | 
					    investigate the underlying design of `ecsy` but it looks cool anyway.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Perl:
 | 
				
			||||||
 | 
					  * [Game::Entities](https://gitlab.com/jjatria/perl-game-entities): a simple
 | 
				
			||||||
 | 
					    entity registry for ECS designs inspired by `EnTT`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Raku:
 | 
				
			||||||
 | 
					  * [Game::Entities](https://gitlab.com/jjatria/raku-game-entities): a simple
 | 
				
			||||||
 | 
					    entity registry for ECS designs inspired by `EnTT`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Rust:
 | 
				
			||||||
 | 
					  * [Legion](https://github.com/TomGillen/legion): a chunk based archetype ECS.
 | 
				
			||||||
 | 
					  * [Shipyard](https://github.com/leudz/shipyard): it borrows some ideas from
 | 
				
			||||||
 | 
					    `EnTT` and offers a sparse sets based ECS with grouping functionalities.
 | 
				
			||||||
 | 
					  * [Sparsey](https://github.com/LechintanTudor/sparsey): sparse set based ECS
 | 
				
			||||||
 | 
					    written in Rust.
 | 
				
			||||||
 | 
					  * [Specs](https://github.com/amethyst/specs): a parallel ECS based mainly on
 | 
				
			||||||
 | 
					    hierarchical bitsets that allows different types of storage as needed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Zig
 | 
				
			||||||
 | 
					  * [zig-ecs](https://github.com/prime31/zig-ecs): a _zig-ification_ of `EnTT`.
 | 
				
			||||||
							
								
								
									
										191
									
								
								external/entt/entt/docs/md/resource.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								external/entt/entt/docs/md/resource.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
				
			|||||||
 | 
					# Crash Course: resource management
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Introduction](#introduction)
 | 
				
			||||||
 | 
					* [The resource, the loader and the cache](#the-resource-the-loader-and-the-cache)
 | 
				
			||||||
 | 
					  * [Resource handle](#resource-handle)
 | 
				
			||||||
 | 
					  * [Loaders](#loader)
 | 
				
			||||||
 | 
					  * [The cache class](#the-cache)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Resource management is usually one of the most critical parts of a game.
 | 
				
			||||||
 | 
					Solutions are often tuned to the particular application. There exist several
 | 
				
			||||||
 | 
					approaches and all of them are perfectly fine as long as they fit the
 | 
				
			||||||
 | 
					requirements of the piece of software in which they are used.<br/>
 | 
				
			||||||
 | 
					Examples are loading everything on start, loading on request, predictive
 | 
				
			||||||
 | 
					loading, and so on.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`EnTT` doesn't pretend to offer a _one-fits-all_ solution for the different
 | 
				
			||||||
 | 
					cases.<br/>
 | 
				
			||||||
 | 
					Instead, the library comes with a minimal, general purpose resource cache that
 | 
				
			||||||
 | 
					might be useful in many cases.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The resource, the loader and the cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Resource, loader and cache are the three main actors for the purpose.<br/>
 | 
				
			||||||
 | 
					The _resource_ is an image, an audio, a video or any other type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct my_resource { const int value; };
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The _loader_ is a callable type the aim of which is to load a specific resource:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct my_loader final {
 | 
				
			||||||
 | 
					    using result_type = std::shared_ptr<my_resource>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result_type operator()(int value) const {
 | 
				
			||||||
 | 
					        // ...
 | 
				
			||||||
 | 
					        return std::make_shared<my_resource>(value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Its function operator can accept any arguments and should return a value of the
 | 
				
			||||||
 | 
					declared result type (`std::shared_ptr<my_resource>` in the example).<br/>
 | 
				
			||||||
 | 
					A loader can also overload its function call operator to make it possible to
 | 
				
			||||||
 | 
					construct the same or another resource from different lists of arguments.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Finally, a cache is a specialization of a class template tailored to a specific
 | 
				
			||||||
 | 
					resource and (optionally) a loader:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					using my_cache = entt::resource_cache<my_resource, my_loader>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_cache cache{};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The class is designed to create different caches for different resource types
 | 
				
			||||||
 | 
					and to manage each one independently in the most appropriate way.<br/>
 | 
				
			||||||
 | 
					As a (very) trivial example, audio tracks can survive in most of the scenes of
 | 
				
			||||||
 | 
					an application while meshes can be associated with a single scene only, then
 | 
				
			||||||
 | 
					discarded when a player leaves it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Resource handle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Resources aren't returned directly to the caller. Instead, they are wrapped in a
 | 
				
			||||||
 | 
					_resource handle_, an instance of the `entt::resource` class template.<br/>
 | 
				
			||||||
 | 
					For those who know the _flyweight design pattern_ already, that's exactly what
 | 
				
			||||||
 | 
					it is. To all others, this is the time to brush up on some notions instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A shared pointer could have been used as a resource handle. In fact, the default
 | 
				
			||||||
 | 
					implementation mostly maps the interface of its standard counterpart and only
 | 
				
			||||||
 | 
					adds a few things on top of it.<br/>
 | 
				
			||||||
 | 
					However, the handle in `EnTT` is designed as a standalone class template. This
 | 
				
			||||||
 | 
					is due to the fact that specializing a class in the standard library is often
 | 
				
			||||||
 | 
					undefined behavior while having the ability to specialize the handle for one,
 | 
				
			||||||
 | 
					more or all resource types could help over time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Loaders
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A loader is responsible for _loading_ resources (quite obviously).<br/>
 | 
				
			||||||
 | 
					By default, it's just a callable object that forwards its arguments to the
 | 
				
			||||||
 | 
					resource itself. That is, a _passthrough type_. All the work is demanded to the
 | 
				
			||||||
 | 
					constructor(s) of the resource itself.<br/>
 | 
				
			||||||
 | 
					Loaders also are fully customizable as expected.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A custom loader is a class with at least one function call operator and a member
 | 
				
			||||||
 | 
					type named `result_type`.<br/>
 | 
				
			||||||
 | 
					The loader isn't required to return a resource handle. As long as `return_type`
 | 
				
			||||||
 | 
					is suitable for constructing a handle, that's fine.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When using the default handle, it expects a resource type which is convertible
 | 
				
			||||||
 | 
					to or suitable for constructing an `std::shared_ptr<Type>` (where `Type` is the
 | 
				
			||||||
 | 
					actual resource type).<br/>
 | 
				
			||||||
 | 
					In other terms, the loader should return shared pointers to the given resource
 | 
				
			||||||
 | 
					type. However, this isn't mandatory. Users can easily get around this constraint
 | 
				
			||||||
 | 
					by specializing both the handle and the loader.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A cache forwards all its arguments to the loader if required. This means that
 | 
				
			||||||
 | 
					loaders can also support tag dispatching to offer different loading policies:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct my_loader {
 | 
				
			||||||
 | 
					    using result_type = std::shared_ptr<my_resource>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct from_disk_tag{};
 | 
				
			||||||
 | 
					    struct from_network_tag{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Args>
 | 
				
			||||||
 | 
					    result_type operator()(from_disk_tag, Args&&... args) {
 | 
				
			||||||
 | 
					        // ...
 | 
				
			||||||
 | 
					        return std::make_shared<my_resource>(std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Args>
 | 
				
			||||||
 | 
					    result_type operator()(from_network_tag, Args&&... args) {
 | 
				
			||||||
 | 
					        // ...
 | 
				
			||||||
 | 
					        return std::make_shared<my_resource>(std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This makes the whole loading logic quite flexible and easy to extend over time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## The cache class
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The cache is the class that is asked to _connect the dots_.<br/>
 | 
				
			||||||
 | 
					It loads the resources, stores them aside and returns handles as needed:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::resource_cache<my_resource, my_loader> cache{};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Under the hood, a cache is nothing more than a map where the key value has type
 | 
				
			||||||
 | 
					`entt::id_type` while the mapped value is whatever type its loader returns.<br/>
 | 
				
			||||||
 | 
					For this reason, it offers most of the functionalities a user would expect from
 | 
				
			||||||
 | 
					a map, such as `empty` or `size` and so on. Similarly, it's an iterable type
 | 
				
			||||||
 | 
					that also supports indexing by resource id:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					for(auto [id, res]: cache) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(entt::resource<my_resource> res = cache["resource/id"_hs]; res) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please, refer to the inline documentation for all the details about the other
 | 
				
			||||||
 | 
					functions (such as `contains` or `erase`).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Set aside the part of the API that this class _shares_ with a map, it also adds
 | 
				
			||||||
 | 
					something on top of it in order to address the most common requirements of a
 | 
				
			||||||
 | 
					resource cache.<br/>
 | 
				
			||||||
 | 
					In particular, it doesn't have an `emplace` member function which is replaced by
 | 
				
			||||||
 | 
					`load` and `force_load` instead (where the former loads a new resource only if
 | 
				
			||||||
 | 
					not present while the second triggers a forced loading in any case):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					auto ret = cache.load("resource/id"_hs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// true only if the resource was not already present
 | 
				
			||||||
 | 
					const bool loaded = ret.second;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// takes the resource handle pointed to by the returned iterator
 | 
				
			||||||
 | 
					entt::resource<my_resource> res = ret.first->second;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note that the hashed string is used for convenience in the example above.<br/>
 | 
				
			||||||
 | 
					Resource identifiers are nothing more than integral values. Therefore, plain
 | 
				
			||||||
 | 
					numbers as well as non-class enum value are accepted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's worth mentioning that the iterators of a cache as well as its indexing
 | 
				
			||||||
 | 
					operators return resource handles rather than instances of the mapped type.<br/>
 | 
				
			||||||
 | 
					Since the cache has no control over the loader and a resource isn't required to
 | 
				
			||||||
 | 
					also be convertible to bool, these handles can be invalid. This usually means an
 | 
				
			||||||
 | 
					error in the user logic but it may also be an _expected_ event.<br/>
 | 
				
			||||||
 | 
					It's therefore recommended to verify handles validity with a check in debug (for
 | 
				
			||||||
 | 
					example, when loading) or an appropriate logic in retail.
 | 
				
			||||||
							
								
								
									
										565
									
								
								external/entt/entt/docs/md/signal.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										565
									
								
								external/entt/entt/docs/md/signal.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,565 @@
 | 
				
			|||||||
 | 
					# Crash Course: events, signals and everything in between
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Introduction](#introduction)
 | 
				
			||||||
 | 
					* [Delegate](#delegate)
 | 
				
			||||||
 | 
					  * [Runtime arguments](#runtime-arguments)
 | 
				
			||||||
 | 
					  * [Lambda support](#lambda-support)
 | 
				
			||||||
 | 
					  * [Raw access](#raw-access)
 | 
				
			||||||
 | 
					* [Signals](#signals)
 | 
				
			||||||
 | 
					* [Event dispatcher](#event-dispatcher)
 | 
				
			||||||
 | 
					  * [Named queues](#named-queues)
 | 
				
			||||||
 | 
					* [Event emitter](#event-emitter)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signals are more often than not a core part of games and software architectures
 | 
				
			||||||
 | 
					in general.<br/>
 | 
				
			||||||
 | 
					They help to decouple the various parts of a system while allowing them to
 | 
				
			||||||
 | 
					communicate with each other somehow.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The so called _modern C++_ comes with a tool that can be useful in this regard,
 | 
				
			||||||
 | 
					the `std::function`. As an example, it can be used to create delegates.<br/>
 | 
				
			||||||
 | 
					However, there is no guarantee that an `std::function` doesn't perform
 | 
				
			||||||
 | 
					allocations under the hood and this could be problematic sometimes. Furthermore,
 | 
				
			||||||
 | 
					it solves a problem but may not adapt well to other requirements that may arise
 | 
				
			||||||
 | 
					from time to time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In case that the flexibility and power of an `std::function` isn't required or
 | 
				
			||||||
 | 
					if the price to pay for them is too high, `EnTT` offers a complete set of
 | 
				
			||||||
 | 
					lightweight classes to solve the same and many other problems.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Delegate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A delegate can be used as a general purpose invoker with no memory overhead for
 | 
				
			||||||
 | 
					free functions, lambdas and members provided along with an instance on which to
 | 
				
			||||||
 | 
					invoke them.<br/>
 | 
				
			||||||
 | 
					It doesn't claim to be a drop-in replacement for an `std::function`, so don't
 | 
				
			||||||
 | 
					expect to use it whenever an `std::function` fits well. That said, it's most
 | 
				
			||||||
 | 
					likely even a better fit than an `std::function` in a lot of cases, so expect to
 | 
				
			||||||
 | 
					use it quite a lot anyway.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The interface is trivial. It offers a default constructor to create empty
 | 
				
			||||||
 | 
					delegates:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::delegate<int(int)> delegate{};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					What is needed to create an instance is to specify the type of the function the
 | 
				
			||||||
 | 
					delegate _accepts_, that is the signature of the functions it models.<br/>
 | 
				
			||||||
 | 
					However, attempting to use an empty delegate by invoking its function call
 | 
				
			||||||
 | 
					operator results in undefined behavior or most likely a crash.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There exist a few overloads of the `connect` member function to initialize a
 | 
				
			||||||
 | 
					delegate:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					int f(int i) { return i; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct my_struct {
 | 
				
			||||||
 | 
					    int f(const int &i) const { return i; }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// bind a free function to the delegate
 | 
				
			||||||
 | 
					delegate.connect<&f>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// bind a member function to the delegate
 | 
				
			||||||
 | 
					my_struct instance;
 | 
				
			||||||
 | 
					delegate.connect<&my_struct::f>(instance);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The delegate class also accepts data members, if needed. In this case, the
 | 
				
			||||||
 | 
					function type of the delegate is such that the parameter list is empty and the
 | 
				
			||||||
 | 
					value of the data member is at least convertible to the return type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Free functions having type equivalent to `void(T &, args...)` are accepted as
 | 
				
			||||||
 | 
					well. The first argument `T &` is considered a payload and the function will
 | 
				
			||||||
 | 
					receive it back every time it's invoked. In other terms, this works just fine
 | 
				
			||||||
 | 
					with the above definition:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					void g(const char &c, int i) { /* ... */ }
 | 
				
			||||||
 | 
					const char c = 'c';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					delegate.connect<&g>(c);
 | 
				
			||||||
 | 
					delegate(42);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Function `g` is invoked with a reference to `c` and `42`. However, the function
 | 
				
			||||||
 | 
					type of the delegate is still `void(int)`. This is also the signature of its
 | 
				
			||||||
 | 
					function call operator.<br/>
 | 
				
			||||||
 | 
					Another interesting aspect of the delegate class is that it accepts functions
 | 
				
			||||||
 | 
					with a list of parameters that is shorter than that of its function type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					void g() { /* ... */ }
 | 
				
			||||||
 | 
					delegate.connect<&g>();
 | 
				
			||||||
 | 
					delegate(42);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Where the function type of the delegate is `void(int)` as above. It goes without
 | 
				
			||||||
 | 
					saying that the extra arguments are silently discarded internally. This is a
 | 
				
			||||||
 | 
					nice-to-have feature in a lot of cases, as an example when the `delegate` class
 | 
				
			||||||
 | 
					is used as a building block of a signal-slot system.<br/>
 | 
				
			||||||
 | 
					In fact, this filtering works both ways. The class tries to pass its first
 | 
				
			||||||
 | 
					_count_ arguments **first**, then the last _count_. Watch out for conversion
 | 
				
			||||||
 | 
					rules if in doubt when connecting a listener!<br/>
 | 
				
			||||||
 | 
					Arbitrary functions that pull random arguments from the delegate list aren't
 | 
				
			||||||
 | 
					supported instead. Other feature were preferred, such as support for functions
 | 
				
			||||||
 | 
					with compatible argument lists although not equal to those of the delegate.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To create and initialize a delegate at once, there are a few specialized
 | 
				
			||||||
 | 
					constructors. Because of the rules of the language, the listener is provided by
 | 
				
			||||||
 | 
					means of the `entt::connect_arg` variable template:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::delegate<int(int)> func{entt::connect_arg<&f>};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Aside `connect`, a `disconnect` counterpart isn't provided. Instead, there
 | 
				
			||||||
 | 
					exists a `reset` member function to use to clear a delegate.<br/>
 | 
				
			||||||
 | 
					To know if a delegate is empty, it can be used explicitly in every conditional
 | 
				
			||||||
 | 
					statement:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					if(delegate) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Finally, to invoke a delegate, the function call operator is the way to go as
 | 
				
			||||||
 | 
					already shown in the examples above:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					auto ret = delegate(42);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In all cases, listeners don't have to strictly follow the signature of the
 | 
				
			||||||
 | 
					delegate. As long as a listener can be invoked with the given arguments to yield
 | 
				
			||||||
 | 
					a result that is convertible to the given result type, everything works just
 | 
				
			||||||
 | 
					fine.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As a side note, members of classes may or may not be associated with instances.
 | 
				
			||||||
 | 
					If they are not, the first argument of the function type must be that of the
 | 
				
			||||||
 | 
					class on which the members operate and an instance of this class must obviously
 | 
				
			||||||
 | 
					be passed when invoking the delegate:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::delegate<void(my_struct &, int)> delegate;
 | 
				
			||||||
 | 
					delegate.connect<&my_struct::f>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_struct instance;
 | 
				
			||||||
 | 
					delegate(instance, 42);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this case, it's not possible to _deduce_ the function type since the first
 | 
				
			||||||
 | 
					argument doesn't necessarily have to be a reference (for example, it can be a
 | 
				
			||||||
 | 
					pointer, as well as a const reference).<br/>
 | 
				
			||||||
 | 
					Therefore, the function type must be declared explicitly for unbound members.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Runtime arguments
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `delegate` class is meant to be used primarily with template arguments.
 | 
				
			||||||
 | 
					However, as a consequence of its design, it also offers minimal support for
 | 
				
			||||||
 | 
					runtime arguments.<br/>
 | 
				
			||||||
 | 
					When used like this, some features aren't supported though. In particular:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Curried functions aren't accepted.
 | 
				
			||||||
 | 
					* Functions with an argument list that differs from that of the delegate aren't
 | 
				
			||||||
 | 
					  supported.
 | 
				
			||||||
 | 
					* Return type and types of arguments **must** coincide with those of the
 | 
				
			||||||
 | 
					  delegate and _being at least convertible_ isn't enough anymore.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Moreover, for a given function type `Ret(Args...)`, the signature of the
 | 
				
			||||||
 | 
					functions connected at runtime must necessarily be `Ret(const void *, Args...)`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Runtime arguments can be passed both to the constructor of a delegate and to the
 | 
				
			||||||
 | 
					`connect` member function. An optional parameter is also accepted in both cases.
 | 
				
			||||||
 | 
					This argument is used to pass arbitrary user data back and forth as a
 | 
				
			||||||
 | 
					`const void *` upon invocation.<br/>
 | 
				
			||||||
 | 
					To connect a function to a delegate _in the hard way_:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					int func(const void *ptr, int i) { return *static_cast<const int *>(ptr) * i; }
 | 
				
			||||||
 | 
					const int value = 42;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// use the constructor ...
 | 
				
			||||||
 | 
					entt::delegate delegate{&func, &value};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ... or the connect member function
 | 
				
			||||||
 | 
					delegate.connect(&func, &value);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The type of the delegate is deduced from the function if possible. In this case,
 | 
				
			||||||
 | 
					since the first argument is an implementation detail, the deduced function type
 | 
				
			||||||
 | 
					is `int(int)`.<br/>
 | 
				
			||||||
 | 
					Invoking a delegate built in this way follows the same rules as previously
 | 
				
			||||||
 | 
					explained.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Lambda support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In general, the `delegate` class doesn't fully support lambda functions in all
 | 
				
			||||||
 | 
					their nuances. The reason is pretty simple: a `delegate` isn't a drop-in
 | 
				
			||||||
 | 
					replacement for an `std::function`. Instead, it tries to overcome the problems
 | 
				
			||||||
 | 
					with the latter.<br/>
 | 
				
			||||||
 | 
					That being said, non-capturing lambda functions are supported, even though some
 | 
				
			||||||
 | 
					features aren't available in this case.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is a logical consequence of the support for connecting functions at
 | 
				
			||||||
 | 
					runtime. Therefore, lambda functions undergo the same rules and
 | 
				
			||||||
 | 
					limitations.<br/>
 | 
				
			||||||
 | 
					In fact, since non-capturing lambda functions decay to pointers to functions,
 | 
				
			||||||
 | 
					they can be used with a `delegate` as if they were _normal functions_ with
 | 
				
			||||||
 | 
					optional payload:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					my_struct instance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// use the constructor ...
 | 
				
			||||||
 | 
					entt::delegate delegate{+[](const void *ptr, int value) {
 | 
				
			||||||
 | 
					    return static_cast<const my_struct *>(ptr)->f(value);
 | 
				
			||||||
 | 
					}, &instance};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ... or the connect member function
 | 
				
			||||||
 | 
					delegate.connect([](const void *ptr, int value) {
 | 
				
			||||||
 | 
					    return static_cast<const my_struct *>(ptr)->f(value);
 | 
				
			||||||
 | 
					}, &instance);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As above, the first parameter (`const void *`) isn't part of the function type
 | 
				
			||||||
 | 
					of the delegate and is used to dispatch arbitrary user data back and forth. In
 | 
				
			||||||
 | 
					other terms, the function type of the delegate above is `int(int)`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Raw access
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					While not recommended, a delegate also allows direct access to the stored
 | 
				
			||||||
 | 
					callable function target and underlying data, if any.<br/>
 | 
				
			||||||
 | 
					This makes it possible to bypass the behavior of the delegate itself and force
 | 
				
			||||||
 | 
					calls on different instances:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					my_struct other;
 | 
				
			||||||
 | 
					delegate.target(&other, 42);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It goes without saying that this type of approach is **very** risky, especially
 | 
				
			||||||
 | 
					since there is no way of knowing whether the contained function was originally a
 | 
				
			||||||
 | 
					member function of some class, a free function or a lambda.<br/>
 | 
				
			||||||
 | 
					Another possible (and meaningful) use of this feature is that of identifying a
 | 
				
			||||||
 | 
					particular delegate through its descriptive _traits_ instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Signals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signal handlers work with references to classes, function pointers and pointers
 | 
				
			||||||
 | 
					to members. Listeners can be any kind of objects and users are in charge of
 | 
				
			||||||
 | 
					connecting and disconnecting them from a signal to avoid crashes due to
 | 
				
			||||||
 | 
					different lifetimes. On the other side, performance shouldn't be affected that
 | 
				
			||||||
 | 
					much by the presence of such a signal handler.<br/>
 | 
				
			||||||
 | 
					Signals make use of delegates internally and therefore they undergo the same
 | 
				
			||||||
 | 
					rules and offer similar functionalities. It may be a good idea to consult the
 | 
				
			||||||
 | 
					documentation of the `delegate` class for further information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A signal handler is can be used as a private data member without exposing any
 | 
				
			||||||
 | 
					_publish_ functionality to the clients of a class.<br/>
 | 
				
			||||||
 | 
					The basic idea is to impose a clear separation between the signal itself and the
 | 
				
			||||||
 | 
					`sink` class, that is a tool to be used to connect and disconnect listeners on
 | 
				
			||||||
 | 
					the fly.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The API of a signal handler is straightforward. If a collector is supplied to
 | 
				
			||||||
 | 
					the signal when something is published, all the values returned by its listeners
 | 
				
			||||||
 | 
					are literally _collected_ and used later by the caller. Otherwise, the class
 | 
				
			||||||
 | 
					works just like a plain signal that emits events from time to time.<br/>
 | 
				
			||||||
 | 
					To create instances of signal handlers it's sufficient to provide the type of
 | 
				
			||||||
 | 
					function to which they refer:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					entt::sigh<void(int, char)> signal;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signals offer all the basic functionalities required to know how many listeners
 | 
				
			||||||
 | 
					they contain (`size`) or if they contain at least a listener (`empty`), as well
 | 
				
			||||||
 | 
					as a function to use to swap handlers (`swap`).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Besides them, there are member functions to use both to connect and disconnect
 | 
				
			||||||
 | 
					listeners in all their forms by means of a sink:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					void foo(int, char) { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct listener {
 | 
				
			||||||
 | 
					    void bar(const int &, char) { /* ... */ }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					entt::sink sink{signal};
 | 
				
			||||||
 | 
					listener instance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sink.connect<&foo>();
 | 
				
			||||||
 | 
					sink.connect<&listener::bar>(instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// disconnects a free function
 | 
				
			||||||
 | 
					sink.disconnect<&foo>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// disconnect a member function of an instance
 | 
				
			||||||
 | 
					sink.disconnect<&listener::bar>(instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// disconnect all member functions of an instance, if any
 | 
				
			||||||
 | 
					sink.disconnect(&instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// discards all listeners at once
 | 
				
			||||||
 | 
					sink.disconnect();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As shown above, listeners don't have to strictly follow the signature of the
 | 
				
			||||||
 | 
					signal. As long as a listener can be invoked with the given arguments to yield a
 | 
				
			||||||
 | 
					result that is convertible to the given return type, everything works just
 | 
				
			||||||
 | 
					fine.<br/>
 | 
				
			||||||
 | 
					In all cases, the `connect` member function returns by default a `connection`
 | 
				
			||||||
 | 
					object to be used as an alternative to break a connection by means of its
 | 
				
			||||||
 | 
					`release` member function.<br/>
 | 
				
			||||||
 | 
					A `scoped_connection` can also be created from a connection. In this case, the
 | 
				
			||||||
 | 
					link is broken automatically as soon as the object goes out of scope.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once listeners are attached (or even if there are no listeners at all), events
 | 
				
			||||||
 | 
					and data in general are published through a signal by means of the `publish`
 | 
				
			||||||
 | 
					member function:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					signal.publish(42, 'c');
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To collect data, the `collect` member function is used instead:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					int f() { return 0; }
 | 
				
			||||||
 | 
					int g() { return 1; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					entt::sigh<int()> signal;
 | 
				
			||||||
 | 
					entt::sink sink{signal};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sink.connect<&f>();
 | 
				
			||||||
 | 
					sink.connect<&g>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::vector<int> vec{};
 | 
				
			||||||
 | 
					signal.collect([&vec](int value) { vec.push_back(value); });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					assert(vec[0] == 0);
 | 
				
			||||||
 | 
					assert(vec[1] == 1);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A collector must expose a function operator that accepts as an argument a type
 | 
				
			||||||
 | 
					to which the return type of the listeners can be converted. Moreover, it can
 | 
				
			||||||
 | 
					optionally return a boolean value that is true to stop collecting data, false
 | 
				
			||||||
 | 
					otherwise. This way one can avoid calling all the listeners in case it isn't
 | 
				
			||||||
 | 
					necessary.<br/>
 | 
				
			||||||
 | 
					Functors can also be used in place of a lambda. Since the collector is copied
 | 
				
			||||||
 | 
					when invoking the `collect` member function, `std::ref` is the way to go in this
 | 
				
			||||||
 | 
					case:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct my_collector {
 | 
				
			||||||
 | 
					    std::vector<int> vec{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool operator()(int v) {
 | 
				
			||||||
 | 
					        vec.push_back(v);
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_collector collector;
 | 
				
			||||||
 | 
					signal.collect(std::ref(collector));
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Event dispatcher
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The event dispatcher class allows users to trigger immediate events or to queue
 | 
				
			||||||
 | 
					and publish them all together later.<br/>
 | 
				
			||||||
 | 
					This class lazily instantiates its queues. Therefore, it's not necessary to
 | 
				
			||||||
 | 
					_announce_ the event types in advance:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// define a general purpose dispatcher
 | 
				
			||||||
 | 
					entt::dispatcher dispatcher{};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A listener registered with a dispatcher is such that its type offers one or more
 | 
				
			||||||
 | 
					member functions that take arguments of type `Event &` for any type of event,
 | 
				
			||||||
 | 
					regardless of the return value.<br/>
 | 
				
			||||||
 | 
					These functions are linked directly via `connect` to a _sink_:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct an_event { int value; };
 | 
				
			||||||
 | 
					struct another_event {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct listener {
 | 
				
			||||||
 | 
					    void receive(const an_event &) { /* ... */ }
 | 
				
			||||||
 | 
					    void method(const another_event &) { /* ... */ }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					listener listener;
 | 
				
			||||||
 | 
					dispatcher.sink<an_event>().connect<&listener::receive>(listener);
 | 
				
			||||||
 | 
					dispatcher.sink<another_event>().connect<&listener::method>(listener);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note that connecting listeners within event handlers can result in undefined
 | 
				
			||||||
 | 
					behavior.<br/>
 | 
				
			||||||
 | 
					The `disconnect` member function is used to remove one listener at a time or all
 | 
				
			||||||
 | 
					of them at once:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					dispatcher.sink<an_event>().disconnect<&listener::receive>(listener);
 | 
				
			||||||
 | 
					dispatcher.sink<another_event>().disconnect(&listener);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `trigger` member function serves the purpose of sending an immediate event
 | 
				
			||||||
 | 
					to all the listeners registered so far:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					dispatcher.trigger(an_event{42});
 | 
				
			||||||
 | 
					dispatcher.trigger<another_event>();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Listeners are invoked immediately, order of execution isn't guaranteed. This
 | 
				
			||||||
 | 
					method can be used to push around urgent messages like an _is terminating_
 | 
				
			||||||
 | 
					notification on a mobile app.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					On the other hand, the `enqueue` member function queues messages together and
 | 
				
			||||||
 | 
					helps to maintain control over the moment they are sent to listeners:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					dispatcher.enqueue<an_event>(42);
 | 
				
			||||||
 | 
					dispatcher.enqueue(another_event{});
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Events are stored aside until the `update` member function is invoked:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// emits all the events of the given type at once
 | 
				
			||||||
 | 
					dispatcher.update<an_event>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// emits all the events queued so far at once
 | 
				
			||||||
 | 
					dispatcher.update();
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This way users can embed the dispatcher in a loop and literally dispatch events
 | 
				
			||||||
 | 
					once per tick to their systems.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Named queues
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All queues within a dispatcher are associated by default with an event type and
 | 
				
			||||||
 | 
					then retrieved from it.<br/>
 | 
				
			||||||
 | 
					However, it's possible to create queues with different _names_ (and therefore
 | 
				
			||||||
 | 
					also multiple queues for a single type). In fact, more or less all functions
 | 
				
			||||||
 | 
					also take an additional parameter. As an example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					dispatcher.sink<an_event>("custom"_hs).connect<&listener::receive>(listener);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this case, the term _name_ is misused as these are actual numeric identifiers
 | 
				
			||||||
 | 
					of type `id_type`.<br/>
 | 
				
			||||||
 | 
					An exception to this rule is the `enqueue` function. There is no additional
 | 
				
			||||||
 | 
					parameter for it but rather a different function:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					dispatcher.enqueue_hint<an_event>("custom"_hs, 42);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is mainly due to the template argument deduction rules and unfortunately
 | 
				
			||||||
 | 
					there is no real (elegant) way to avoid it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Event emitter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A general purpose event emitter thought mainly for those cases where it comes to
 | 
				
			||||||
 | 
					working with asynchronous stuff.<br/>
 | 
				
			||||||
 | 
					Originally designed to fit the requirements of
 | 
				
			||||||
 | 
					[`uvw`](https://github.com/skypjack/uvw) (a wrapper for `libuv` written in
 | 
				
			||||||
 | 
					modern C++), it was adapted later to be included in this library.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To create an emitter type, derived classes must inherit from the base as:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct my_emitter: emitter<my_emitter> {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Handlers for the different events are created internally on the fly. It's not
 | 
				
			||||||
 | 
					required to specify in advance the full list of accepted events.<br/>
 | 
				
			||||||
 | 
					Moreover, whenever an event is published, an emitter also passes a reference
 | 
				
			||||||
 | 
					to itself to its listeners.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To create new instances of an emitter, no arguments are required:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					my_emitter emitter{};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Listeners are movable and callable objects (free functions, lambdas, functors,
 | 
				
			||||||
 | 
					`std::function`s, whatever) whose function type is compatible with:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					void(Type &, my_emitter &)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Where `Type` is the type of event they want to receive.<br/>
 | 
				
			||||||
 | 
					To attach a listener to an emitter, there exists the `on` member function:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					emitter.on<my_event>([](const my_event &event, my_emitter &emitter) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Similarly, the `reset` member function is used to disconnect listeners given a
 | 
				
			||||||
 | 
					type while `clear` is used to disconnect all listeners at once:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					// resets the listener for my_event
 | 
				
			||||||
 | 
					emitter.erase<my_event>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// resets all listeners
 | 
				
			||||||
 | 
					emitter.clear()
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To send an event to the listener registered on a given type, the `publish`
 | 
				
			||||||
 | 
					function is the way to go:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					struct my_event { int i; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					emitter.publish(my_event{42});
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Finally, the `empty` member function tests if there exists at least a listener
 | 
				
			||||||
 | 
					registered with the event emitter while `contains` is used to check if a given
 | 
				
			||||||
 | 
					event type is associated with a valid listener:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					if(emitter.contains<my_event>()) {
 | 
				
			||||||
 | 
					    // ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This class introduces a _nice-to-have_ model based on events and listeners.<br/>
 | 
				
			||||||
 | 
					More in general, it's a handy tool when the derived classes _wrap_ asynchronous
 | 
				
			||||||
 | 
					operations but it's not limited to such uses.
 | 
				
			||||||
							
								
								
									
										107
									
								
								external/entt/entt/docs/md/unreal.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								external/entt/entt/docs/md/unreal.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
				
			|||||||
 | 
					# EnTT and Unreal Engine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					# Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Enable Cpp17](#enable-cpp17)
 | 
				
			||||||
 | 
					* [EnTT as a third party module](#entt-as-a-third-party-module)
 | 
				
			||||||
 | 
					* [Include EnTT](#include-entt)
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					@endcond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Enable Cpp17
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As of writing (Unreal Engine v4.25), the default C++ standard of Unreal Engine
 | 
				
			||||||
 | 
					is C++14.<br/>
 | 
				
			||||||
 | 
					On the other hand, note that `EnTT` requires C++17 to compile. To enable it, in
 | 
				
			||||||
 | 
					the main module of the project there should be a `<Game Name>.Build.cs` file,
 | 
				
			||||||
 | 
					the constructor of which must contain the following lines:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cs
 | 
				
			||||||
 | 
					PCHUsage = PCHUsageMode.NoSharedPCHs;
 | 
				
			||||||
 | 
					PrivatePCHHeaderFile = "<PCH filename>.h";
 | 
				
			||||||
 | 
					CppStandard = CppStandardVersion.Cpp17;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Replace `<PCH filename>.h` with the name of the already existing PCH header
 | 
				
			||||||
 | 
					file, if any.<br/>
 | 
				
			||||||
 | 
					In case the project doesn't already contain a file of this type, it's possible
 | 
				
			||||||
 | 
					to create one with the following content:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cpp
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "CoreMinimal.h"
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Remember to remove any old `PCHUsage = <...>` line that was previously there. At
 | 
				
			||||||
 | 
					this point, C++17 support should be in place.<br/>
 | 
				
			||||||
 | 
					Try to compile the project to ensure it works as expected before following
 | 
				
			||||||
 | 
					further steps.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note that updating a *project* to C++17 doesn't necessarily mean that the IDE in
 | 
				
			||||||
 | 
					use will also start to recognize its syntax.<br/>
 | 
				
			||||||
 | 
					If the plan is to use C++17 in the project too, check the specific instructions
 | 
				
			||||||
 | 
					for the IDE in use.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## EnTT as a third party module
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once this point is reached, the `Source` directory should look like this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Source
 | 
				
			||||||
 | 
					|  MyGame.Target.cs
 | 
				
			||||||
 | 
					|  MyGameEditor.Target.cs
 | 
				
			||||||
 | 
					|
 | 
				
			||||||
 | 
					+---MyGame
 | 
				
			||||||
 | 
					|  |  MyGame.Build.cs
 | 
				
			||||||
 | 
					|  |  MyGame.h (PCH Header file)
 | 
				
			||||||
 | 
					|
 | 
				
			||||||
 | 
					\---ThirdParty
 | 
				
			||||||
 | 
					   \---EnTT
 | 
				
			||||||
 | 
					      |   EnTT.Build.cs
 | 
				
			||||||
 | 
					      |
 | 
				
			||||||
 | 
					      \---entt (GitHub repository content inside)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To make this happen, create the folder `ThirdParty` under `Source` if it doesn't
 | 
				
			||||||
 | 
					exist already. Then, add an `EnTT` folder under `ThirdParty`.<br/>
 | 
				
			||||||
 | 
					Within the latter, create a new file `EnTT.Build.cs` with the following content:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cs
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using UnrealBuildTool;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class EnTT: ModuleRules {
 | 
				
			||||||
 | 
					    public EnTT(ReadOnlyTargetRules Target) : base(Target) {
 | 
				
			||||||
 | 
					        Type = ModuleType.External;
 | 
				
			||||||
 | 
					        PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "entt", "src", "entt"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The last line indicates that the actual files will be found in the directory
 | 
				
			||||||
 | 
					`EnTT/entt/src/entt`.<br/>
 | 
				
			||||||
 | 
					Download the repository for `EnTT` and place it next to `EnTT.Build.cs` or
 | 
				
			||||||
 | 
					update the path above accordingly.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Finally, open the `<Game Name>.Build.cs` file and add `EnTT` as a dependency at
 | 
				
			||||||
 | 
					the end of the list:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cs
 | 
				
			||||||
 | 
					PublicDependencyModuleNames.AddRange(new[] {
 | 
				
			||||||
 | 
					    "Core", "CoreUObject", "Engine", "InputCore", [...], "EnTT"
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note that some IDEs might require a restart to start recognizing the new module
 | 
				
			||||||
 | 
					for code-highlighting features and such.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Include EnTT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In any source file of the project, add `#include "entt.hpp"` or any other path
 | 
				
			||||||
 | 
					to the file from `EnTT` to use it.<br/>
 | 
				
			||||||
 | 
					Try to create a registry as `entt::registry registry;` to make sure everything
 | 
				
			||||||
 | 
					compiles fine.
 | 
				
			||||||
							
								
								
									
										34
									
								
								external/entt/entt/entt.imp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								external/entt/entt/entt.imp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					[
 | 
				
			||||||
 | 
					  { "include": [ "@<gtest/internal/.*>", "private", "<gtest/gtest.h>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@<gtest/gtest-.*>", "private", "<gtest/gtest.h>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/container/fwd.hpp[\">]", "private", "<entt/container/dense_map.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/container/fwd.hpp[\">]", "private", "<entt/container/dense_set.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/core/fwd.hpp[\">]", "private", "<entt/core/any.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/core/fwd.hpp[\">]", "private", "<entt/core/family.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/core/fwd.hpp[\">]", "private", "<entt/core/hashed_string.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/core/fwd.hpp[\">]", "private", "<entt/core/ident.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/core/fwd.hpp[\">]", "private", "<entt/core/monostate.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/core/fwd.hpp[\">]", "private", "<entt/core/type_info.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/core/fwd.hpp[\">]", "private", "<entt/core/type_traits.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/entity.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/group.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/handle.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/helper.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/observer.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/organizer.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/registry.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/runtime_view.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/snapshot.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/sparse_set.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/storage.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/view.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/meta/fwd.hpp[\">]", "private", "<entt/meta/meta.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/poly/fwd.hpp[\">]", "private", "<entt/poly/poly.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/resource/fwd.hpp[\">]", "private", "<entt/resource/cache.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/resource/fwd.hpp[\">]", "private", "<entt/resource/loader.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/resource/fwd.hpp[\">]", "private", "<entt/resource/resource.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/signal/fwd.hpp[\">]", "private", "<entt/signal/delegate.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/signal/fwd.hpp[\">]", "private", "<entt/signal/dispatcher.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/signal/fwd.hpp[\">]", "private", "<entt/signal/emitter.hpp>", "public" ] },
 | 
				
			||||||
 | 
					  { "include": [ "@[\"<].*/signal/fwd.hpp[\">]", "private", "<entt/signal/sigh.hpp>", "public" ] }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
							
								
								
									
										3
									
								
								external/entt/entt/natvis/entt/config.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								external/entt/entt/natvis/entt/config.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
 | 
				
			||||||
 | 
					</AutoVisualizer>
 | 
				
			||||||
							
								
								
									
										33
									
								
								external/entt/entt/natvis/entt/container.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								external/entt/entt/natvis/entt/container.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
 | 
				
			||||||
 | 
						<Type Name="entt::dense_map<*>">
 | 
				
			||||||
 | 
							<Intrinsic Name="size" Expression="packed.first_base::value.size()"/>
 | 
				
			||||||
 | 
							<Intrinsic Name="bucket_count" Expression="sparse.first_base::value.size()"/>
 | 
				
			||||||
 | 
							<DisplayString>{{ size={ size() } }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[capacity]" ExcludeView="simple">packed.first_base::value.capacity()</Item>
 | 
				
			||||||
 | 
								<Item Name="[bucket_count]" ExcludeView="simple">bucket_count()</Item>
 | 
				
			||||||
 | 
								<Item Name="[load_factor]" ExcludeView="simple">(float)size() / (float)bucket_count()</Item>
 | 
				
			||||||
 | 
								<Item Name="[max_load_factor]" ExcludeView="simple">threshold</Item>
 | 
				
			||||||
 | 
								<IndexListItems>
 | 
				
			||||||
 | 
									<Size>size()</Size>
 | 
				
			||||||
 | 
									<ValueNode>packed.first_base::value[$i].element</ValueNode>
 | 
				
			||||||
 | 
								</IndexListItems>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::dense_set<*>">
 | 
				
			||||||
 | 
							<Intrinsic Name="size" Expression="packed.first_base::value.size()"/>
 | 
				
			||||||
 | 
							<Intrinsic Name="bucket_count" Expression="sparse.first_base::value.size()"/>
 | 
				
			||||||
 | 
							<DisplayString>{{ size={ size() } }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[capacity]" ExcludeView="simple">packed.first_base::value.capacity()</Item>
 | 
				
			||||||
 | 
								<Item Name="[bucket_count]" ExcludeView="simple">bucket_count()</Item>
 | 
				
			||||||
 | 
								<Item Name="[load_factor]" ExcludeView="simple">(float)size() / (float)bucket_count()</Item>
 | 
				
			||||||
 | 
								<Item Name="[max_load_factor]" ExcludeView="simple">threshold</Item>
 | 
				
			||||||
 | 
								<IndexListItems>
 | 
				
			||||||
 | 
									<Size>size()</Size>
 | 
				
			||||||
 | 
									<ValueNode>packed.first_base::value[$i].second</ValueNode>
 | 
				
			||||||
 | 
								</IndexListItems>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
					</AutoVisualizer>
 | 
				
			||||||
							
								
								
									
										32
									
								
								external/entt/entt/natvis/entt/core.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								external/entt/entt/natvis/entt/core.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
 | 
				
			||||||
 | 
					    <Type Name="entt::basic_any<*>">
 | 
				
			||||||
 | 
							<DisplayString>{{ type={ info->alias,na }, policy={ mode,en } }}</DisplayString>
 | 
				
			||||||
 | 
					    </Type>
 | 
				
			||||||
 | 
						<Type Name="entt::compressed_pair<*>">
 | 
				
			||||||
 | 
							<Intrinsic Name="first" Optional="true" Expression="((first_base*)this)->value"/>
 | 
				
			||||||
 | 
							<Intrinsic Name="first" Optional="true" Expression="*(first_base::base_type*)this"/>
 | 
				
			||||||
 | 
							<Intrinsic Name="second" Optional="true" Expression="((second_base*)this)->value"/>
 | 
				
			||||||
 | 
							<Intrinsic Name="second" Optional="true" Expression="*(second_base::base_type*)this"/>
 | 
				
			||||||
 | 
							<DisplayString >({ first() }, { second() })</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[first]">first()</Item>
 | 
				
			||||||
 | 
								<Item Name="[second]">second()</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::basic_hashed_string<*>">
 | 
				
			||||||
 | 
							<DisplayString Condition="base_type::repr != nullptr">{{ hash={ base_type::hash } }}</DisplayString>
 | 
				
			||||||
 | 
							<DisplayString>{{}}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[data]">base_type::repr,na</Item>
 | 
				
			||||||
 | 
								<Item Name="[length]">base_type::length</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::type_info">
 | 
				
			||||||
 | 
							<DisplayString>{{ name={ alias,na } }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[hash]">identifier</Item>
 | 
				
			||||||
 | 
								<Item Name="[index]">seq</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
					</AutoVisualizer>
 | 
				
			||||||
							
								
								
									
										123
									
								
								external/entt/entt/natvis/entt/entity.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								external/entt/entt/natvis/entt/entity.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,123 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
 | 
				
			||||||
 | 
						<Type Name="entt::basic_registry<*>">
 | 
				
			||||||
 | 
							<Intrinsic Name="to_entity" Expression="*((traits_type::entity_type *)&entity) & traits_type::entity_mask">
 | 
				
			||||||
 | 
								<Parameter Name="entity" Type="traits_type::value_type &"/>
 | 
				
			||||||
 | 
							</Intrinsic>
 | 
				
			||||||
 | 
							<DisplayString>{{ pools={ pools.size() } }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[entities]">entities</Item>
 | 
				
			||||||
 | 
								<Synthetic Name="[pools]">
 | 
				
			||||||
 | 
									<DisplayString>{ pools.size() }</DisplayString>
 | 
				
			||||||
 | 
									<Expand>
 | 
				
			||||||
 | 
										<IndexListItems ExcludeView="simple">
 | 
				
			||||||
 | 
											<Size>pools.size()</Size>
 | 
				
			||||||
 | 
											<ValueNode>*pools.packed.first_base::value[$i].element.second</ValueNode>
 | 
				
			||||||
 | 
										</IndexListItems>
 | 
				
			||||||
 | 
										<IndexListItems IncludeView="simple">
 | 
				
			||||||
 | 
											<Size>pools.size()</Size>
 | 
				
			||||||
 | 
											<ValueNode>*pools.packed.first_base::value[$i].element.second,view(simple)</ValueNode>
 | 
				
			||||||
 | 
										</IndexListItems>
 | 
				
			||||||
 | 
									</Expand>
 | 
				
			||||||
 | 
								</Synthetic>
 | 
				
			||||||
 | 
								<Item Name="[groups]" ExcludeView="simple">groups.size()</Item>
 | 
				
			||||||
 | 
								<Synthetic Name="[vars]">
 | 
				
			||||||
 | 
									<DisplayString>{ vars.ctx.size() }</DisplayString>
 | 
				
			||||||
 | 
									<Expand>
 | 
				
			||||||
 | 
										<IndexListItems>
 | 
				
			||||||
 | 
											<Size>vars.ctx.size()</Size>
 | 
				
			||||||
 | 
											<ValueNode>vars.ctx.packed.first_base::value[$i].element.second</ValueNode>
 | 
				
			||||||
 | 
										</IndexListItems>
 | 
				
			||||||
 | 
									</Expand>
 | 
				
			||||||
 | 
								</Synthetic>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::basic_sparse_set<*>">
 | 
				
			||||||
 | 
							<DisplayString>{{ size={ packed.size() }, type={ info->alias,na } }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[capacity]" ExcludeView="simple">packed.capacity()</Item>
 | 
				
			||||||
 | 
								<Item Name="[policy]">mode,en</Item>
 | 
				
			||||||
 | 
								<Synthetic Name="[sparse]">
 | 
				
			||||||
 | 
									<DisplayString>{ sparse.size() * traits_type::page_size }</DisplayString>
 | 
				
			||||||
 | 
									<Expand>
 | 
				
			||||||
 | 
										<ExpandedItem IncludeView="simple">sparse,view(simple)</ExpandedItem>
 | 
				
			||||||
 | 
										<CustomListItems ExcludeView="simple">
 | 
				
			||||||
 | 
											<Variable Name="pos" InitialValue="0"/>
 | 
				
			||||||
 | 
											<Variable Name="page" InitialValue="0"/>
 | 
				
			||||||
 | 
											<Variable Name="offset" InitialValue="0"/>
 | 
				
			||||||
 | 
											<Variable Name="last" InitialValue="sparse.size() * traits_type::page_size"/>
 | 
				
			||||||
 | 
											<Loop>
 | 
				
			||||||
 | 
												<Break Condition="pos == last"/>
 | 
				
			||||||
 | 
												<Exec>page = pos / traits_type::page_size</Exec>
 | 
				
			||||||
 | 
												<Exec>offset = pos & (traits_type::page_size - 1)</Exec>
 | 
				
			||||||
 | 
												<If Condition="sparse[page] && (*((traits_type::entity_type *)&sparse[page][offset]) < ~traits_type::entity_mask)">
 | 
				
			||||||
 | 
													<Item Name="[{ pos }]">*((traits_type::entity_type *)&sparse[page][offset]) & traits_type::entity_mask</Item>
 | 
				
			||||||
 | 
												</If>
 | 
				
			||||||
 | 
												<Exec>++pos</Exec>
 | 
				
			||||||
 | 
											</Loop>
 | 
				
			||||||
 | 
										</CustomListItems>
 | 
				
			||||||
 | 
									</Expand>
 | 
				
			||||||
 | 
								</Synthetic>
 | 
				
			||||||
 | 
								<Synthetic Name="[packed]">
 | 
				
			||||||
 | 
									<DisplayString>{ packed.size() }</DisplayString>
 | 
				
			||||||
 | 
									<Expand>
 | 
				
			||||||
 | 
										<ExpandedItem IncludeView="simple">packed,view(simple)</ExpandedItem>
 | 
				
			||||||
 | 
										<CustomListItems ExcludeView="simple">
 | 
				
			||||||
 | 
											<Variable Name="pos" InitialValue="0"/>
 | 
				
			||||||
 | 
											<Variable Name="last" InitialValue="packed.size()"/>
 | 
				
			||||||
 | 
											<Loop>
 | 
				
			||||||
 | 
												<Break Condition="pos == last"/>
 | 
				
			||||||
 | 
												<If Condition="*((traits_type::entity_type *)&packed[pos]) < ~traits_type::entity_mask">
 | 
				
			||||||
 | 
													<Item Name="[{ pos }]">packed[pos]</Item>
 | 
				
			||||||
 | 
												</If>
 | 
				
			||||||
 | 
												<Exec>++pos</Exec>
 | 
				
			||||||
 | 
											</Loop>
 | 
				
			||||||
 | 
										</CustomListItems>
 | 
				
			||||||
 | 
									</Expand>
 | 
				
			||||||
 | 
								</Synthetic>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::basic_storage<*>">
 | 
				
			||||||
 | 
							<DisplayString>{{ size={ base_type::packed.size() }, type={ base_type::info->alias,na } }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[capacity]" Optional="true" ExcludeView="simple">payload.capacity() * traits_type::page_size</Item>
 | 
				
			||||||
 | 
								<Item Name="[page size]" Optional="true" ExcludeView="simple">traits_type::page_size</Item>
 | 
				
			||||||
 | 
								<Item Name="[length]" Optional="true" ExcludeView="simple">length</Item>
 | 
				
			||||||
 | 
								<Item Name="[base]" ExcludeView="simple">(base_type*)this,nand</Item>
 | 
				
			||||||
 | 
								<Item Name="[base]" IncludeView="simple">(base_type*)this,view(simple)nand</Item>
 | 
				
			||||||
 | 
								<!-- having SFINAE-like techniques in natvis is priceless :) -->
 | 
				
			||||||
 | 
								<CustomListItems Condition="payload.size() != 0" Optional="true">
 | 
				
			||||||
 | 
									<Variable Name="pos" InitialValue="0" />
 | 
				
			||||||
 | 
									<Variable Name="last" InitialValue="base_type::packed.size()"/>
 | 
				
			||||||
 | 
									<Loop>
 | 
				
			||||||
 | 
										<Break Condition="pos == last"/>
 | 
				
			||||||
 | 
										<If Condition="*((base_type::traits_type::entity_type *)&base_type::packed[pos]) < ~base_type::traits_type::entity_mask">
 | 
				
			||||||
 | 
											<Item Name="[{ pos }:{ base_type::packed[pos] }]">payload[pos / traits_type::page_size][pos & (traits_type::page_size - 1)]</Item>
 | 
				
			||||||
 | 
										</If>
 | 
				
			||||||
 | 
										<Exec>++pos</Exec>
 | 
				
			||||||
 | 
									</Loop>
 | 
				
			||||||
 | 
								</CustomListItems>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::basic_view<*>">
 | 
				
			||||||
 | 
							<DisplayString>{{ size_hint={ view->packed.size() } }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[pools]">pools,na</Item>
 | 
				
			||||||
 | 
								<Item Name="[filter]">filter,na</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::basic_runtime_view<*>">
 | 
				
			||||||
 | 
							<DisplayString Condition="pools.size() != 0u">{{ size_hint={ pools[0]->packed.size() } }}</DisplayString>
 | 
				
			||||||
 | 
							<DisplayString>{{ size_hint=0 }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[pools]">pools,na</Item>
 | 
				
			||||||
 | 
								<Item Name="[filter]">filter,na</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::null_t">
 | 
				
			||||||
 | 
							<DisplayString><null></DisplayString>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::tombstone_t">
 | 
				
			||||||
 | 
							<DisplayString><tombstone></DisplayString>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
					</AutoVisualizer>
 | 
				
			||||||
							
								
								
									
										19
									
								
								external/entt/entt/natvis/entt/graph.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								external/entt/entt/natvis/entt/graph.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
 | 
				
			||||||
 | 
					    <Type Name="entt::adjacency_matrix<*>">
 | 
				
			||||||
 | 
							<DisplayString>{{ size={ vert } }}</DisplayString>
 | 
				
			||||||
 | 
					        <Expand>
 | 
				
			||||||
 | 
								<CustomListItems>
 | 
				
			||||||
 | 
									<Variable Name="pos" InitialValue="0" />
 | 
				
			||||||
 | 
									<Variable Name="last" InitialValue="vert * vert"/>
 | 
				
			||||||
 | 
									<Loop>
 | 
				
			||||||
 | 
										<Break Condition="pos == last"/>
 | 
				
			||||||
 | 
										<If Condition="matrix[pos] != 0u">
 | 
				
			||||||
 | 
											<Item Name="{pos / vert}">pos % vert</Item>
 | 
				
			||||||
 | 
										</If>
 | 
				
			||||||
 | 
										<Exec>++pos</Exec>
 | 
				
			||||||
 | 
									</Loop>
 | 
				
			||||||
 | 
								</CustomListItems>
 | 
				
			||||||
 | 
					        </Expand>
 | 
				
			||||||
 | 
					    </Type>
 | 
				
			||||||
 | 
					</AutoVisualizer>
 | 
				
			||||||
							
								
								
									
										3
									
								
								external/entt/entt/natvis/entt/locator.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								external/entt/entt/natvis/entt/locator.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
 | 
				
			||||||
 | 
					</AutoVisualizer>
 | 
				
			||||||
							
								
								
									
										121
									
								
								external/entt/entt/natvis/entt/meta.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								external/entt/entt/natvis/entt/meta.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,121 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
 | 
				
			||||||
 | 
						<Type Name="entt::internal::meta_base_node">
 | 
				
			||||||
 | 
							<DisplayString>{{}}</DisplayString>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::internal::meta_conv_node">
 | 
				
			||||||
 | 
							<DisplayString>{{}}</DisplayString>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::internal::meta_ctor_node">
 | 
				
			||||||
 | 
							<DisplayString>{{ arity={ arity } }}</DisplayString>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::internal::meta_data_node">
 | 
				
			||||||
 | 
							<Intrinsic Name="has_property" Expression="!!(traits & property)">
 | 
				
			||||||
 | 
								<Parameter Name="property" Type="int"/>
 | 
				
			||||||
 | 
							</Intrinsic>
 | 
				
			||||||
 | 
							<DisplayString>{{ arity={ arity } }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[arity]">arity</Item>
 | 
				
			||||||
 | 
								<Item Name="[is_const]">has_property(entt::internal::meta_traits::is_const)</Item>
 | 
				
			||||||
 | 
								<Item Name="[is_static]">has_property(entt::internal::meta_traits::is_static)</Item>
 | 
				
			||||||
 | 
								<Item Name="[prop]">prop</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::internal::meta_func_node"	>
 | 
				
			||||||
 | 
							<Intrinsic Name="has_property" Expression="!!(traits & property)">
 | 
				
			||||||
 | 
								<Parameter Name="property" Type="int"/>
 | 
				
			||||||
 | 
							</Intrinsic>
 | 
				
			||||||
 | 
							<DisplayString>{{ arity={ arity } }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[is_const]">has_property(entt::internal::meta_traits::is_const)</Item>
 | 
				
			||||||
 | 
								<Item Name="[is_static]">has_property(entt::internal::meta_traits::is_static)</Item>
 | 
				
			||||||
 | 
								<Item Name="[next]" Condition="next != nullptr">*next</Item>
 | 
				
			||||||
 | 
								<Item Name="[prop]">prop</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::internal::meta_prop_node">
 | 
				
			||||||
 | 
							<DisplayString>{ value }</DisplayString>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::internal::meta_template_node">
 | 
				
			||||||
 | 
							<DisplayString>{{ arity={ arity } }}</DisplayString>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::internal::meta_type_node">
 | 
				
			||||||
 | 
							<Intrinsic Name="has_property" Expression="!!(traits & property)">
 | 
				
			||||||
 | 
								<Parameter Name="property" Type="int"/>
 | 
				
			||||||
 | 
							</Intrinsic>
 | 
				
			||||||
 | 
							<DisplayString Condition="info != nullptr">{{ type={ info->alias,na } }}</DisplayString>
 | 
				
			||||||
 | 
							<DisplayString>{{}}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[id]">id</Item>
 | 
				
			||||||
 | 
								<Item Name="[sizeof]">size_of</Item>
 | 
				
			||||||
 | 
								<Item Name="[is_arithmetic]">has_property(entt::internal::meta_traits::is_arithmetic)</Item>
 | 
				
			||||||
 | 
								<Item Name="[is_integral]">has_property(entt::internal::meta_traits::is_integral)</Item>
 | 
				
			||||||
 | 
								<Item Name="[is_signed]">has_property(entt::internal::meta_traits::is_signed)</Item>
 | 
				
			||||||
 | 
								<Item Name="[is_array]">has_property(entt::internal::meta_traits::is_array)</Item>
 | 
				
			||||||
 | 
								<Item Name="[is_enum]">has_property(entt::internal::meta_traits::is_enum)</Item>
 | 
				
			||||||
 | 
								<Item Name="[is_class]">has_property(entt::internal::meta_traits::is_class)</Item>
 | 
				
			||||||
 | 
								<Item Name="[is_meta_pointer_like]">has_property(entt::internal::meta_traits::is_meta_pointer_like)</Item>
 | 
				
			||||||
 | 
								<Item Name="[is_meta_sequence_container]">has_property(entt::internal::meta_traits::is_meta_sequence_container)</Item>
 | 
				
			||||||
 | 
								<Item Name="[is_meta_associative_container]">has_property(entt::internal::meta_traits::is_meta_associative_container)</Item>
 | 
				
			||||||
 | 
								<Item Name="[default_constructor]">default_constructor != nullptr</Item>
 | 
				
			||||||
 | 
								<Item Name="[conversion_helper]">conversion_helper != nullptr</Item>
 | 
				
			||||||
 | 
								<Item Name="[from_void]">from_void != nullptr</Item>
 | 
				
			||||||
 | 
								<Item Name="[template_info]">templ</Item>
 | 
				
			||||||
 | 
								<Item Name="[details]" Condition="details != nullptr">*details</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::meta_any">
 | 
				
			||||||
 | 
							<DisplayString Condition="node.info != nullptr">{{ type={ node.info->alias,na }, policy={ storage.mode,en } }}</DisplayString>
 | 
				
			||||||
 | 
							<DisplayString>{{}}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<ExpandedItem>node</ExpandedItem>
 | 
				
			||||||
 | 
								<Item Name="[context]" Condition="ctx != nullptr">ctx->value</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::meta_handle">
 | 
				
			||||||
 | 
							<DisplayString>{ any }</DisplayString>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::meta_associative_container">
 | 
				
			||||||
 | 
							<DisplayString>{ storage }</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[context]" Condition="ctx != nullptr">ctx->value</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::meta_sequence_container">
 | 
				
			||||||
 | 
							<DisplayString>{ storage }</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[context]" Condition="ctx != nullptr">ctx->value</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::meta_data">
 | 
				
			||||||
 | 
							<DisplayString Condition="node != nullptr">{ *node }</DisplayString>
 | 
				
			||||||
 | 
							<DisplayString>{{}}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<ExpandedItem Condition="node != nullptr">node</ExpandedItem>
 | 
				
			||||||
 | 
								<Item Name="[context]" Condition="ctx != nullptr">ctx->value</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::meta_func">
 | 
				
			||||||
 | 
							<DisplayString Condition="node != nullptr">{ *node }</DisplayString>
 | 
				
			||||||
 | 
							<DisplayString>{{}}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<ExpandedItem Condition="node != nullptr">node</ExpandedItem>
 | 
				
			||||||
 | 
								<Item Name="[context]" Condition="ctx != nullptr">ctx->value</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::meta_prop">
 | 
				
			||||||
 | 
							<DisplayString Condition="node != nullptr">{ *node }</DisplayString>
 | 
				
			||||||
 | 
							<DisplayString>{{}}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<ExpandedItem Condition="node != nullptr">node</ExpandedItem>
 | 
				
			||||||
 | 
								<Item Name="[context]" Condition="ctx != nullptr">ctx->value</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::meta_type">
 | 
				
			||||||
 | 
							<DisplayString>{ node }</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<ExpandedItem>node</ExpandedItem>
 | 
				
			||||||
 | 
								<Item Name="[context]" Condition="ctx != nullptr">ctx->value</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
					</AutoVisualizer>
 | 
				
			||||||
							
								
								
									
										3
									
								
								external/entt/entt/natvis/entt/platform.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								external/entt/entt/natvis/entt/platform.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
 | 
				
			||||||
 | 
					</AutoVisualizer>
 | 
				
			||||||
							
								
								
									
										6
									
								
								external/entt/entt/natvis/entt/poly.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								external/entt/entt/natvis/entt/poly.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
 | 
				
			||||||
 | 
						<Type Name="entt::basic_poly<*>">
 | 
				
			||||||
 | 
							<DisplayString>{ storage }</DisplayString>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
					</AutoVisualizer>
 | 
				
			||||||
							
								
								
									
										3
									
								
								external/entt/entt/natvis/entt/process.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								external/entt/entt/natvis/entt/process.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
 | 
				
			||||||
 | 
					</AutoVisualizer>
 | 
				
			||||||
							
								
								
									
										15
									
								
								external/entt/entt/natvis/entt/resource.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								external/entt/entt/natvis/entt/resource.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
 | 
				
			||||||
 | 
						<Type Name="entt::resource<*>">
 | 
				
			||||||
 | 
							<DisplayString>{ value }</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<ExpandedItem>value</ExpandedItem>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::resource_cache<*>">
 | 
				
			||||||
 | 
							<DisplayString>{ pool.first_base::value }</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<ExpandedItem>pool.first_base::value</ExpandedItem>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
					</AutoVisualizer>
 | 
				
			||||||
							
								
								
									
										55
									
								
								external/entt/entt/natvis/entt/signal.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								external/entt/entt/natvis/entt/signal.natvis
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
 | 
				
			||||||
 | 
						<Type Name="entt::delegate<*>">
 | 
				
			||||||
 | 
							<DisplayString>{{ type={ "$T1" } }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[empty]">fn == nullptr</Item>
 | 
				
			||||||
 | 
								<Item Name="[data]">instance</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::basic_dispatcher<*>">
 | 
				
			||||||
 | 
							<Intrinsic Name="size" Expression="pools.first_base::value.size()"/>
 | 
				
			||||||
 | 
							<DisplayString>{{ size={ size() } }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Synthetic Name="[pools]">
 | 
				
			||||||
 | 
									<DisplayString>{ size() }</DisplayString>
 | 
				
			||||||
 | 
									<Expand>
 | 
				
			||||||
 | 
										<IndexListItems>
 | 
				
			||||||
 | 
											<Size>size()</Size>
 | 
				
			||||||
 | 
											<ValueNode>*pools.first_base::value.packed.first_base::value[$i].element.second</ValueNode>
 | 
				
			||||||
 | 
										</IndexListItems>
 | 
				
			||||||
 | 
									</Expand>
 | 
				
			||||||
 | 
								</Synthetic>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::internal::dispatcher_handler<*>">
 | 
				
			||||||
 | 
							<DisplayString>{{ size={ events.size() }, event={ "$T1" } }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[signal]">signal</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::emitter<*>">
 | 
				
			||||||
 | 
							<DisplayString>{{ size={ handlers.first_base::value.packed.first_base::value.size() } }}</DisplayString>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::connection">
 | 
				
			||||||
 | 
							<DisplayString>{{ bound={ signal != nullptr } }}</DisplayString>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::scoped_connection">
 | 
				
			||||||
 | 
							<DisplayString>{ conn }</DisplayString>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::sigh<*>">
 | 
				
			||||||
 | 
							<DisplayString>{{ size={ calls.size() }, type={ "$T1" } }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<IndexListItems>
 | 
				
			||||||
 | 
									<Size>calls.size()</Size>
 | 
				
			||||||
 | 
									<ValueNode>calls[$i]</ValueNode>
 | 
				
			||||||
 | 
								</IndexListItems>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
						<Type Name="entt::sink<*>">
 | 
				
			||||||
 | 
							<DisplayString>{{ type={ "$T1" } }}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="[signal]">signal,na</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
					</AutoVisualizer>
 | 
				
			||||||
							
								
								
									
										299
									
								
								external/entt/entt/scripts/amalgamate.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										299
									
								
								external/entt/entt/scripts/amalgamate.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,299 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					# coding=utf-8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# amalgamate.py - Amalgamate C source and header files.
 | 
				
			||||||
 | 
					# Copyright (c) 2012, Erik Edlund <erik.edlund@32767.se>
 | 
				
			||||||
 | 
					# 
 | 
				
			||||||
 | 
					# Redistribution and use in source and binary forms, with or without modification,
 | 
				
			||||||
 | 
					# are permitted provided that the following conditions are met:
 | 
				
			||||||
 | 
					# 
 | 
				
			||||||
 | 
					#  * Redistributions of source code must retain the above copyright notice,
 | 
				
			||||||
 | 
					#  this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					# 
 | 
				
			||||||
 | 
					#  * Redistributions in binary form must reproduce the above copyright notice,
 | 
				
			||||||
 | 
					#  this list of conditions and the following disclaimer in the documentation
 | 
				
			||||||
 | 
					#  and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					# 
 | 
				
			||||||
 | 
					#  * Neither the name of Erik Edlund, nor the names of its contributors may
 | 
				
			||||||
 | 
					#  be used to endorse or promote products derived from this software without
 | 
				
			||||||
 | 
					#  specific prior written permission.
 | 
				
			||||||
 | 
					# 
 | 
				
			||||||
 | 
					# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 | 
				
			||||||
 | 
					# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
				
			||||||
 | 
					# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
				
			||||||
 | 
					# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 | 
				
			||||||
 | 
					# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
				
			||||||
 | 
					# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
				
			||||||
 | 
					# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 | 
				
			||||||
 | 
					# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
				
			||||||
 | 
					# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from __future__ import division
 | 
				
			||||||
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import argparse
 | 
				
			||||||
 | 
					import datetime
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Amalgamation(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Prepends self.source_path to file_path if needed.
 | 
				
			||||||
 | 
					    def actual_path(self, file_path):
 | 
				
			||||||
 | 
					        if not os.path.isabs(file_path):
 | 
				
			||||||
 | 
					            file_path = os.path.join(self.source_path, file_path)
 | 
				
			||||||
 | 
					        return file_path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Search included file_path in self.include_paths and
 | 
				
			||||||
 | 
					    # in source_dir if specified.
 | 
				
			||||||
 | 
					    def find_included_file(self, file_path, source_dir):
 | 
				
			||||||
 | 
					        search_dirs = self.include_paths[:]
 | 
				
			||||||
 | 
					        if source_dir:
 | 
				
			||||||
 | 
					            search_dirs.insert(0, source_dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for search_dir in search_dirs:
 | 
				
			||||||
 | 
					            search_path = os.path.join(search_dir, file_path)
 | 
				
			||||||
 | 
					            if os.path.isfile(self.actual_path(search_path)):
 | 
				
			||||||
 | 
					                return search_path
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, args):
 | 
				
			||||||
 | 
					        with open(args.config, 'r') as f:
 | 
				
			||||||
 | 
					            config = json.loads(f.read())
 | 
				
			||||||
 | 
					            for key in config:
 | 
				
			||||||
 | 
					                setattr(self, key, config[key])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.verbose = args.verbose == "yes"
 | 
				
			||||||
 | 
					            self.prologue = args.prologue
 | 
				
			||||||
 | 
					            self.source_path = args.source_path
 | 
				
			||||||
 | 
					            self.included_files = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Generate the amalgamation and write it to the target file.
 | 
				
			||||||
 | 
					    def generate(self):
 | 
				
			||||||
 | 
					        amalgamation = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.prologue:
 | 
				
			||||||
 | 
					            with open(self.prologue, 'r') as f:
 | 
				
			||||||
 | 
					                amalgamation += datetime.datetime.now().strftime(f.read())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.verbose:
 | 
				
			||||||
 | 
					            print("Config:")
 | 
				
			||||||
 | 
					            print(" target        = {0}".format(self.target))
 | 
				
			||||||
 | 
					            print(" working_dir   = {0}".format(os.getcwd()))
 | 
				
			||||||
 | 
					            print(" include_paths = {0}".format(self.include_paths))
 | 
				
			||||||
 | 
					        print("Creating amalgamation:")
 | 
				
			||||||
 | 
					        for file_path in self.sources:
 | 
				
			||||||
 | 
					            # Do not check the include paths while processing the source
 | 
				
			||||||
 | 
					            # list, all given source paths must be correct.
 | 
				
			||||||
 | 
					            # actual_path = self.actual_path(file_path)
 | 
				
			||||||
 | 
					            print(" - processing \"{0}\"".format(file_path))
 | 
				
			||||||
 | 
					            t = TranslationUnit(file_path, self, True)
 | 
				
			||||||
 | 
					            amalgamation += t.content
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with open(self.target, 'w') as f:
 | 
				
			||||||
 | 
					            f.write(amalgamation)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        print("...done!\n")
 | 
				
			||||||
 | 
					        if self.verbose:
 | 
				
			||||||
 | 
					            print("Files processed: {0}".format(self.sources))
 | 
				
			||||||
 | 
					            print("Files included: {0}".format(self.included_files))
 | 
				
			||||||
 | 
					        print("")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _is_within(match, matches):
 | 
				
			||||||
 | 
					    for m in matches:
 | 
				
			||||||
 | 
					        if match.start() > m.start() and \
 | 
				
			||||||
 | 
					                match.end() < m.end():
 | 
				
			||||||
 | 
					            return True
 | 
				
			||||||
 | 
					    return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TranslationUnit(object):
 | 
				
			||||||
 | 
					    # // C++ comment.
 | 
				
			||||||
 | 
					    cpp_comment_pattern = re.compile(r"//.*?\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # /* C comment. */
 | 
				
			||||||
 | 
					    c_comment_pattern = re.compile(r"/\*.*?\*/", re.S)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # "complex \"stri\\\ng\" value".
 | 
				
			||||||
 | 
					    string_pattern = re.compile("[^']" r'".*?(?<=[^\\])"', re.S)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Handle simple include directives. Support for advanced
 | 
				
			||||||
 | 
					    # directives where macros and defines needs to expanded is
 | 
				
			||||||
 | 
					    # not a concern right now.
 | 
				
			||||||
 | 
					    include_pattern = re.compile(
 | 
				
			||||||
 | 
					        r'#\s*include\s+(<|")(?P<path>.*?)("|>)', re.S)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # #pragma once
 | 
				
			||||||
 | 
					    pragma_once_pattern = re.compile(r'#\s*pragma\s+once', re.S)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Search for pattern in self.content, add the match to
 | 
				
			||||||
 | 
					    # contexts if found and update the index accordingly.
 | 
				
			||||||
 | 
					    def _search_content(self, index, pattern, contexts):
 | 
				
			||||||
 | 
					        match = pattern.search(self.content, index)
 | 
				
			||||||
 | 
					        if match:
 | 
				
			||||||
 | 
					            contexts.append(match)
 | 
				
			||||||
 | 
					            return match.end()
 | 
				
			||||||
 | 
					        return index + 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Return all the skippable contexts, i.e., comments and strings
 | 
				
			||||||
 | 
					    def _find_skippable_contexts(self):
 | 
				
			||||||
 | 
					        # Find contexts in the content in which a found include
 | 
				
			||||||
 | 
					        # directive should not be processed.
 | 
				
			||||||
 | 
					        skippable_contexts = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Walk through the content char by char, and try to grab
 | 
				
			||||||
 | 
					        # skippable contexts using regular expressions when found.
 | 
				
			||||||
 | 
					        i = 1
 | 
				
			||||||
 | 
					        content_len = len(self.content)
 | 
				
			||||||
 | 
					        while i < content_len:
 | 
				
			||||||
 | 
					            j = i - 1
 | 
				
			||||||
 | 
					            current = self.content[i]
 | 
				
			||||||
 | 
					            previous = self.content[j]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if current == '"':
 | 
				
			||||||
 | 
					                # String value.
 | 
				
			||||||
 | 
					                i = self._search_content(j, self.string_pattern,
 | 
				
			||||||
 | 
					                                         skippable_contexts)
 | 
				
			||||||
 | 
					            elif current == '*' and previous == '/':
 | 
				
			||||||
 | 
					                # C style comment.
 | 
				
			||||||
 | 
					                i = self._search_content(j, self.c_comment_pattern,
 | 
				
			||||||
 | 
					                                         skippable_contexts)
 | 
				
			||||||
 | 
					            elif current == '/' and previous == '/':
 | 
				
			||||||
 | 
					                # C++ style comment.
 | 
				
			||||||
 | 
					                i = self._search_content(j, self.cpp_comment_pattern,
 | 
				
			||||||
 | 
					                                         skippable_contexts)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                # Skip to the next char.
 | 
				
			||||||
 | 
					                i += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return skippable_contexts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Returns True if the match is within list of other matches
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Removes pragma once from content
 | 
				
			||||||
 | 
					    def _process_pragma_once(self):
 | 
				
			||||||
 | 
					        content_len = len(self.content)
 | 
				
			||||||
 | 
					        if content_len < len("#include <x>"):
 | 
				
			||||||
 | 
					            return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Find contexts in the content in which a found include
 | 
				
			||||||
 | 
					        # directive should not be processed.
 | 
				
			||||||
 | 
					        skippable_contexts = self._find_skippable_contexts()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        pragmas = []
 | 
				
			||||||
 | 
					        pragma_once_match = self.pragma_once_pattern.search(self.content)
 | 
				
			||||||
 | 
					        while pragma_once_match:
 | 
				
			||||||
 | 
					            if not _is_within(pragma_once_match, skippable_contexts):
 | 
				
			||||||
 | 
					                pragmas.append(pragma_once_match)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            pragma_once_match = self.pragma_once_pattern.search(self.content,
 | 
				
			||||||
 | 
					                                                                pragma_once_match.end())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Handle all collected pragma once directives.
 | 
				
			||||||
 | 
					        prev_end = 0
 | 
				
			||||||
 | 
					        tmp_content = ''
 | 
				
			||||||
 | 
					        for pragma_match in pragmas:
 | 
				
			||||||
 | 
					            tmp_content += self.content[prev_end:pragma_match.start()]
 | 
				
			||||||
 | 
					            prev_end = pragma_match.end()
 | 
				
			||||||
 | 
					        tmp_content += self.content[prev_end:]
 | 
				
			||||||
 | 
					        self.content = tmp_content
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Include all trivial #include directives into self.content.
 | 
				
			||||||
 | 
					    def _process_includes(self):
 | 
				
			||||||
 | 
					        content_len = len(self.content)
 | 
				
			||||||
 | 
					        if content_len < len("#include <x>"):
 | 
				
			||||||
 | 
					            return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Find contexts in the content in which a found include
 | 
				
			||||||
 | 
					        # directive should not be processed.
 | 
				
			||||||
 | 
					        skippable_contexts = self._find_skippable_contexts()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Search for include directives in the content, collect those
 | 
				
			||||||
 | 
					        # which should be included into the content.
 | 
				
			||||||
 | 
					        includes = []
 | 
				
			||||||
 | 
					        include_match = self.include_pattern.search(self.content)
 | 
				
			||||||
 | 
					        while include_match:
 | 
				
			||||||
 | 
					            if not _is_within(include_match, skippable_contexts):
 | 
				
			||||||
 | 
					                include_path = include_match.group("path")
 | 
				
			||||||
 | 
					                search_same_dir = include_match.group(1) == '"'
 | 
				
			||||||
 | 
					                found_included_path = self.amalgamation.find_included_file(
 | 
				
			||||||
 | 
					                    include_path, self.file_dir if search_same_dir else None)
 | 
				
			||||||
 | 
					                if found_included_path:
 | 
				
			||||||
 | 
					                    includes.append((include_match, found_included_path))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            include_match = self.include_pattern.search(self.content,
 | 
				
			||||||
 | 
					                                                        include_match.end())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Handle all collected include directives.
 | 
				
			||||||
 | 
					        prev_end = 0
 | 
				
			||||||
 | 
					        tmp_content = ''
 | 
				
			||||||
 | 
					        for include in includes:
 | 
				
			||||||
 | 
					            include_match, found_included_path = include
 | 
				
			||||||
 | 
					            tmp_content += self.content[prev_end:include_match.start()]
 | 
				
			||||||
 | 
					            tmp_content += "// {0}\n".format(include_match.group(0))
 | 
				
			||||||
 | 
					            if found_included_path not in self.amalgamation.included_files:
 | 
				
			||||||
 | 
					                t = TranslationUnit(found_included_path, self.amalgamation, False)
 | 
				
			||||||
 | 
					                tmp_content += t.content
 | 
				
			||||||
 | 
					            prev_end = include_match.end()
 | 
				
			||||||
 | 
					        tmp_content += self.content[prev_end:]
 | 
				
			||||||
 | 
					        self.content = tmp_content
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return len(includes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Make all content processing
 | 
				
			||||||
 | 
					    def _process(self):
 | 
				
			||||||
 | 
					        if not self.is_root:
 | 
				
			||||||
 | 
					            self._process_pragma_once()
 | 
				
			||||||
 | 
					        self._process_includes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, file_path, amalgamation, is_root):
 | 
				
			||||||
 | 
					        self.file_path = file_path
 | 
				
			||||||
 | 
					        self.file_dir = os.path.dirname(file_path)
 | 
				
			||||||
 | 
					        self.amalgamation = amalgamation
 | 
				
			||||||
 | 
					        self.is_root = is_root
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.amalgamation.included_files.append(self.file_path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        actual_path = self.amalgamation.actual_path(file_path)
 | 
				
			||||||
 | 
					        if not os.path.isfile(actual_path):
 | 
				
			||||||
 | 
					            raise IOError("File not found: \"{0}\"".format(file_path))
 | 
				
			||||||
 | 
					        with open(actual_path, 'r') as f:
 | 
				
			||||||
 | 
					            self.content = f.read()
 | 
				
			||||||
 | 
					            self._process()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    description = "Amalgamate C source and header files."
 | 
				
			||||||
 | 
					    usage = " ".join([
 | 
				
			||||||
 | 
					        "amalgamate.py",
 | 
				
			||||||
 | 
					        "[-v]",
 | 
				
			||||||
 | 
					        "-c path/to/config.json",
 | 
				
			||||||
 | 
					        "-s path/to/source/dir",
 | 
				
			||||||
 | 
					        "[-p path/to/prologue.(c|h)]"
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
 | 
					    argsparser = argparse.ArgumentParser(
 | 
				
			||||||
 | 
					        description=description, usage=usage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    argsparser.add_argument("-v", "--verbose", dest="verbose",
 | 
				
			||||||
 | 
					                            choices=["yes", "no"], metavar="", help="be verbose")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    argsparser.add_argument("-c", "--config", dest="config",
 | 
				
			||||||
 | 
					                            required=True, metavar="", help="path to a JSON config file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    argsparser.add_argument("-s", "--source", dest="source_path",
 | 
				
			||||||
 | 
					                            required=True, metavar="", help="source code path")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    argsparser.add_argument("-p", "--prologue", dest="prologue",
 | 
				
			||||||
 | 
					                            required=False, metavar="", help="path to a C prologue file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    amalgamation = Amalgamation(argsparser.parse_args())
 | 
				
			||||||
 | 
					    amalgamation.generate()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    main()
 | 
				
			||||||
							
								
								
									
										8
									
								
								external/entt/entt/scripts/config.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								external/entt/entt/scripts/config.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
						"project": "entt",
 | 
				
			||||||
 | 
						"target": "single_include/entt/entt.hpp",
 | 
				
			||||||
 | 
						"sources": [
 | 
				
			||||||
 | 
							"src/entt/entt.hpp"
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						"include_paths": ["src"]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										60
									
								
								external/entt/entt/scripts/update_homebrew.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										60
									
								
								external/entt/entt/scripts/update_homebrew.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							@@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# only argument should be the version to upgrade to
 | 
				
			||||||
 | 
					if [ $# != 1 ]
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
					  echo "Expected a version tag like v2.7.1"
 | 
				
			||||||
 | 
					  exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VERSION="$1"
 | 
				
			||||||
 | 
					URL="https://github.com/skypjack/entt/archive/$VERSION.tar.gz"
 | 
				
			||||||
 | 
					FORMULA="entt.rb"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "Updating homebrew package to $VERSION"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "Cloning..."
 | 
				
			||||||
 | 
					git clone https://github.com/skypjack/homebrew-entt.git
 | 
				
			||||||
 | 
					if [ $? != 0 ]
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
					  exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					cd homebrew-entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# download the repo at the version
 | 
				
			||||||
 | 
					# exit with error messages if curl fails
 | 
				
			||||||
 | 
					echo "Curling..."
 | 
				
			||||||
 | 
					curl "$URL" --location --fail --silent --show-error --output archive.tar.gz
 | 
				
			||||||
 | 
					if [ $? != 0 ]
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
					  exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# compute sha256 hash
 | 
				
			||||||
 | 
					echo "Hashing..."
 | 
				
			||||||
 | 
					HASH="$(openssl sha256 archive.tar.gz | cut -d " " -f 2)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# delete the archive
 | 
				
			||||||
 | 
					rm archive.tar.gz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "Sedding..."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# change the url in the formula file
 | 
				
			||||||
 | 
					# the slashes in the URL must be escaped
 | 
				
			||||||
 | 
					ESCAPED_URL="$(echo "$URL" | sed -e 's/[\/&]/\\&/g')"
 | 
				
			||||||
 | 
					sed -i -e '/url/s/".*"/"'$ESCAPED_URL'"/' $FORMULA
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# change the hash in the formula file
 | 
				
			||||||
 | 
					sed -i -e '/sha256/s/".*"/"'$HASH'"/' $FORMULA
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# delete temporary file created by sed
 | 
				
			||||||
 | 
					rm -rf "$FORMULA-e"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# update remote repo
 | 
				
			||||||
 | 
					echo "Gitting..."
 | 
				
			||||||
 | 
					git add entt.rb
 | 
				
			||||||
 | 
					git commit -m "Update to $VERSION"
 | 
				
			||||||
 | 
					git push origin master
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# out of homebrew-entt dir
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
							
								
								
									
										88701
									
								
								external/entt/entt/single_include/entt/entt.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										88701
									
								
								external/entt/entt/single_include/entt/entt.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										83
									
								
								external/entt/entt/src/entt/config/config.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								external/entt/entt/src/entt/config/config.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CONFIG_CONFIG_H
 | 
				
			||||||
 | 
					#define ENTT_CONFIG_CONFIG_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "version.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
 | 
				
			||||||
 | 
					#    define ENTT_CONSTEXPR
 | 
				
			||||||
 | 
					#    define ENTT_THROW throw
 | 
				
			||||||
 | 
					#    define ENTT_TRY try
 | 
				
			||||||
 | 
					#    define ENTT_CATCH catch(...)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#    define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
 | 
				
			||||||
 | 
					#    define ENTT_THROW
 | 
				
			||||||
 | 
					#    define ENTT_TRY if(true)
 | 
				
			||||||
 | 
					#    define ENTT_CATCH if(false)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef ENTT_USE_ATOMIC
 | 
				
			||||||
 | 
					#    include <atomic>
 | 
				
			||||||
 | 
					#    define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#    define ENTT_MAYBE_ATOMIC(Type) Type
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ENTT_ID_TYPE
 | 
				
			||||||
 | 
					#    include <cstdint>
 | 
				
			||||||
 | 
					#    define ENTT_ID_TYPE std::uint32_t
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ENTT_SPARSE_PAGE
 | 
				
			||||||
 | 
					#    define ENTT_SPARSE_PAGE 4096
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ENTT_PACKED_PAGE
 | 
				
			||||||
 | 
					#    define ENTT_PACKED_PAGE 1024
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef ENTT_DISABLE_ASSERT
 | 
				
			||||||
 | 
					#    undef ENTT_ASSERT
 | 
				
			||||||
 | 
					#    define ENTT_ASSERT(condition, msg) (void(0))
 | 
				
			||||||
 | 
					#elif !defined ENTT_ASSERT
 | 
				
			||||||
 | 
					#    include <cassert>
 | 
				
			||||||
 | 
					#    define ENTT_ASSERT(condition, msg) assert(condition)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef ENTT_DISABLE_ASSERT
 | 
				
			||||||
 | 
					#    undef ENTT_ASSERT_CONSTEXPR
 | 
				
			||||||
 | 
					#    define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
 | 
				
			||||||
 | 
					#elif !defined ENTT_ASSERT_CONSTEXPR
 | 
				
			||||||
 | 
					#    define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef ENTT_NO_ETO
 | 
				
			||||||
 | 
					#    define ENTT_ETO_TYPE(Type) void
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#    define ENTT_ETO_TYPE(Type) Type
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef ENTT_STANDARD_CPP
 | 
				
			||||||
 | 
					#    define ENTT_NONSTD false
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#    define ENTT_NONSTD true
 | 
				
			||||||
 | 
					#    if defined __clang__ || defined __GNUC__
 | 
				
			||||||
 | 
					#        define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
 | 
				
			||||||
 | 
					#        define ENTT_PRETTY_FUNCTION_PREFIX '='
 | 
				
			||||||
 | 
					#        define ENTT_PRETTY_FUNCTION_SUFFIX ']'
 | 
				
			||||||
 | 
					#    elif defined _MSC_VER
 | 
				
			||||||
 | 
					#        define ENTT_PRETTY_FUNCTION __FUNCSIG__
 | 
				
			||||||
 | 
					#        define ENTT_PRETTY_FUNCTION_PREFIX '<'
 | 
				
			||||||
 | 
					#        define ENTT_PRETTY_FUNCTION_SUFFIX '>'
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined _MSC_VER
 | 
				
			||||||
 | 
					#    pragma detect_mismatch("entt.version", ENTT_VERSION)
 | 
				
			||||||
 | 
					#    pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
 | 
				
			||||||
 | 
					#    pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
 | 
				
			||||||
 | 
					#    pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										7
									
								
								external/entt/entt/src/entt/config/macro.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								external/entt/entt/src/entt/config/macro.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CONFIG_MACRO_H
 | 
				
			||||||
 | 
					#define ENTT_CONFIG_MACRO_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ENTT_STR(arg) #arg
 | 
				
			||||||
 | 
					#define ENTT_XSTR(arg) ENTT_STR(arg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										14
									
								
								external/entt/entt/src/entt/config/version.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								external/entt/entt/src/entt/config/version.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CONFIG_VERSION_H
 | 
				
			||||||
 | 
					#define ENTT_CONFIG_VERSION_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "macro.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ENTT_VERSION_MAJOR 3
 | 
				
			||||||
 | 
					#define ENTT_VERSION_MINOR 12
 | 
				
			||||||
 | 
					#define ENTT_VERSION_PATCH 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ENTT_VERSION \
 | 
				
			||||||
 | 
					    ENTT_XSTR(ENTT_VERSION_MAJOR) \
 | 
				
			||||||
 | 
					    "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										1054
									
								
								external/entt/entt/src/entt/container/dense_map.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1054
									
								
								external/entt/entt/src/entt/container/dense_map.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										889
									
								
								external/entt/entt/src/entt/container/dense_set.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										889
									
								
								external/entt/entt/src/entt/container/dense_set.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,889 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CONTAINER_DENSE_SET_HPP
 | 
				
			||||||
 | 
					#define ENTT_CONTAINER_DENSE_SET_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cmath>
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					#include <functional>
 | 
				
			||||||
 | 
					#include <iterator>
 | 
				
			||||||
 | 
					#include <limits>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include "../config/config.h"
 | 
				
			||||||
 | 
					#include "../core/compressed_pair.hpp"
 | 
				
			||||||
 | 
					#include "../core/memory.hpp"
 | 
				
			||||||
 | 
					#include "../core/type_traits.hpp"
 | 
				
			||||||
 | 
					#include "fwd.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename It>
 | 
				
			||||||
 | 
					class dense_set_iterator final {
 | 
				
			||||||
 | 
					    template<typename>
 | 
				
			||||||
 | 
					    friend class dense_set_iterator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    using value_type = typename It::value_type::second_type;
 | 
				
			||||||
 | 
					    using pointer = const value_type *;
 | 
				
			||||||
 | 
					    using reference = const value_type &;
 | 
				
			||||||
 | 
					    using difference_type = std::ptrdiff_t;
 | 
				
			||||||
 | 
					    using iterator_category = std::random_access_iterator_tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr dense_set_iterator() noexcept
 | 
				
			||||||
 | 
					        : it{} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr dense_set_iterator(const It iter) noexcept
 | 
				
			||||||
 | 
					        : it{iter} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
 | 
				
			||||||
 | 
					    constexpr dense_set_iterator(const dense_set_iterator<Other> &other) noexcept
 | 
				
			||||||
 | 
					        : it{other.it} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr dense_set_iterator &operator++() noexcept {
 | 
				
			||||||
 | 
					        return ++it, *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr dense_set_iterator operator++(int) noexcept {
 | 
				
			||||||
 | 
					        dense_set_iterator orig = *this;
 | 
				
			||||||
 | 
					        return ++(*this), orig;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr dense_set_iterator &operator--() noexcept {
 | 
				
			||||||
 | 
					        return --it, *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr dense_set_iterator operator--(int) noexcept {
 | 
				
			||||||
 | 
					        dense_set_iterator orig = *this;
 | 
				
			||||||
 | 
					        return operator--(), orig;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr dense_set_iterator &operator+=(const difference_type value) noexcept {
 | 
				
			||||||
 | 
					        it += value;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr dense_set_iterator operator+(const difference_type value) const noexcept {
 | 
				
			||||||
 | 
					        dense_set_iterator copy = *this;
 | 
				
			||||||
 | 
					        return (copy += value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr dense_set_iterator &operator-=(const difference_type value) noexcept {
 | 
				
			||||||
 | 
					        return (*this += -value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr dense_set_iterator operator-(const difference_type value) const noexcept {
 | 
				
			||||||
 | 
					        return (*this + -value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
 | 
				
			||||||
 | 
					        return it[value].second;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr pointer operator->() const noexcept {
 | 
				
			||||||
 | 
					        return std::addressof(it->second);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr reference operator*() const noexcept {
 | 
				
			||||||
 | 
					        return *operator->();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Lhs, typename Rhs>
 | 
				
			||||||
 | 
					    friend constexpr std::ptrdiff_t operator-(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Lhs, typename Rhs>
 | 
				
			||||||
 | 
					    friend constexpr bool operator==(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Lhs, typename Rhs>
 | 
				
			||||||
 | 
					    friend constexpr bool operator<(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    It it;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Lhs, typename Rhs>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return lhs.it - rhs.it;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Lhs, typename Rhs>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator==(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return lhs.it == rhs.it;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Lhs, typename Rhs>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator!=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return !(lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Lhs, typename Rhs>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator<(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return lhs.it < rhs.it;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Lhs, typename Rhs>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator>(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return rhs < lhs;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Lhs, typename Rhs>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator<=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return !(lhs > rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Lhs, typename Rhs>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator>=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return !(lhs < rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename It>
 | 
				
			||||||
 | 
					class dense_set_local_iterator final {
 | 
				
			||||||
 | 
					    template<typename>
 | 
				
			||||||
 | 
					    friend class dense_set_local_iterator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    using value_type = typename It::value_type::second_type;
 | 
				
			||||||
 | 
					    using pointer = const value_type *;
 | 
				
			||||||
 | 
					    using reference = const value_type &;
 | 
				
			||||||
 | 
					    using difference_type = std::ptrdiff_t;
 | 
				
			||||||
 | 
					    using iterator_category = std::forward_iterator_tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr dense_set_local_iterator() noexcept
 | 
				
			||||||
 | 
					        : it{},
 | 
				
			||||||
 | 
					          offset{} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr dense_set_local_iterator(It iter, const std::size_t pos) noexcept
 | 
				
			||||||
 | 
					        : it{iter},
 | 
				
			||||||
 | 
					          offset{pos} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
 | 
				
			||||||
 | 
					    constexpr dense_set_local_iterator(const dense_set_local_iterator<Other> &other) noexcept
 | 
				
			||||||
 | 
					        : it{other.it},
 | 
				
			||||||
 | 
					          offset{other.offset} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr dense_set_local_iterator &operator++() noexcept {
 | 
				
			||||||
 | 
					        return offset = it[offset].first, *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr dense_set_local_iterator operator++(int) noexcept {
 | 
				
			||||||
 | 
					        dense_set_local_iterator orig = *this;
 | 
				
			||||||
 | 
					        return ++(*this), orig;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr pointer operator->() const noexcept {
 | 
				
			||||||
 | 
					        return std::addressof(it[offset].second);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr reference operator*() const noexcept {
 | 
				
			||||||
 | 
					        return *operator->();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr std::size_t index() const noexcept {
 | 
				
			||||||
 | 
					        return offset;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    It it;
 | 
				
			||||||
 | 
					    std::size_t offset;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Lhs, typename Rhs>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator==(const dense_set_local_iterator<Lhs> &lhs, const dense_set_local_iterator<Rhs> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return lhs.index() == rhs.index();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Lhs, typename Rhs>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator!=(const dense_set_local_iterator<Lhs> &lhs, const dense_set_local_iterator<Rhs> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return !(lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 * @endcond
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Associative container for unique objects of a given type.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Internally, elements are organized into buckets. Which bucket an element is
 | 
				
			||||||
 | 
					 * placed into depends entirely on its hash. Elements with the same hash code
 | 
				
			||||||
 | 
					 * appear in the same bucket.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tparam Type Value type of the associative container.
 | 
				
			||||||
 | 
					 * @tparam Hash Type of function to use to hash the values.
 | 
				
			||||||
 | 
					 * @tparam KeyEqual Type of function to use to compare the values for equality.
 | 
				
			||||||
 | 
					 * @tparam Allocator Type of allocator used to manage memory and elements.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename Hash, typename KeyEqual, typename Allocator>
 | 
				
			||||||
 | 
					class dense_set {
 | 
				
			||||||
 | 
					    static constexpr float default_threshold = 0.875f;
 | 
				
			||||||
 | 
					    static constexpr std::size_t minimum_capacity = 8u;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using node_type = std::pair<std::size_t, Type>;
 | 
				
			||||||
 | 
					    using alloc_traits = std::allocator_traits<Allocator>;
 | 
				
			||||||
 | 
					    static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
 | 
				
			||||||
 | 
					    using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
 | 
				
			||||||
 | 
					    using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Other>
 | 
				
			||||||
 | 
					    [[nodiscard]] std::size_t value_to_bucket(const Other &value) const noexcept {
 | 
				
			||||||
 | 
					        return fast_mod(static_cast<size_type>(sparse.second()(value)), bucket_count());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Other>
 | 
				
			||||||
 | 
					    [[nodiscard]] auto constrained_find(const Other &value, std::size_t bucket) {
 | 
				
			||||||
 | 
					        for(auto it = begin(bucket), last = end(bucket); it != last; ++it) {
 | 
				
			||||||
 | 
					            if(packed.second()(*it, value)) {
 | 
				
			||||||
 | 
					                return begin() + static_cast<typename iterator::difference_type>(it.index());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return end();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Other>
 | 
				
			||||||
 | 
					    [[nodiscard]] auto constrained_find(const Other &value, std::size_t bucket) const {
 | 
				
			||||||
 | 
					        for(auto it = cbegin(bucket), last = cend(bucket); it != last; ++it) {
 | 
				
			||||||
 | 
					            if(packed.second()(*it, value)) {
 | 
				
			||||||
 | 
					                return cbegin() + static_cast<typename iterator::difference_type>(it.index());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return cend();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Other>
 | 
				
			||||||
 | 
					    [[nodiscard]] auto insert_or_do_nothing(Other &&value) {
 | 
				
			||||||
 | 
					        const auto index = value_to_bucket(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(auto it = constrained_find(value, index); it != end()) {
 | 
				
			||||||
 | 
					            return std::make_pair(it, false);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        packed.first().emplace_back(sparse.first()[index], std::forward<Other>(value));
 | 
				
			||||||
 | 
					        sparse.first()[index] = packed.first().size() - 1u;
 | 
				
			||||||
 | 
					        rehash_if_required();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return std::make_pair(--end(), true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void move_and_pop(const std::size_t pos) {
 | 
				
			||||||
 | 
					        if(const auto last = size() - 1u; pos != last) {
 | 
				
			||||||
 | 
					            size_type *curr = sparse.first().data() + value_to_bucket(packed.first().back().second);
 | 
				
			||||||
 | 
					            packed.first()[pos] = std::move(packed.first().back());
 | 
				
			||||||
 | 
					            for(; *curr != last; curr = &packed.first()[*curr].first) {}
 | 
				
			||||||
 | 
					            *curr = pos;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        packed.first().pop_back();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void rehash_if_required() {
 | 
				
			||||||
 | 
					        if(size() > (bucket_count() * max_load_factor())) {
 | 
				
			||||||
 | 
					            rehash(bucket_count() * 2u);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /*! @brief Key type of the container. */
 | 
				
			||||||
 | 
					    using key_type = Type;
 | 
				
			||||||
 | 
					    /*! @brief Value type of the container. */
 | 
				
			||||||
 | 
					    using value_type = Type;
 | 
				
			||||||
 | 
					    /*! @brief Unsigned integer type. */
 | 
				
			||||||
 | 
					    using size_type = std::size_t;
 | 
				
			||||||
 | 
					    /*! @brief Type of function to use to hash the elements. */
 | 
				
			||||||
 | 
					    using hasher = Hash;
 | 
				
			||||||
 | 
					    /*! @brief Type of function to use to compare the elements for equality. */
 | 
				
			||||||
 | 
					    using key_equal = KeyEqual;
 | 
				
			||||||
 | 
					    /*! @brief Allocator type. */
 | 
				
			||||||
 | 
					    using allocator_type = Allocator;
 | 
				
			||||||
 | 
					    /*! @brief Random access iterator type. */
 | 
				
			||||||
 | 
					    using iterator = internal::dense_set_iterator<typename packed_container_type::iterator>;
 | 
				
			||||||
 | 
					    /*! @brief Constant random access iterator type. */
 | 
				
			||||||
 | 
					    using const_iterator = internal::dense_set_iterator<typename packed_container_type::const_iterator>;
 | 
				
			||||||
 | 
					    /*! @brief Forward iterator type. */
 | 
				
			||||||
 | 
					    using local_iterator = internal::dense_set_local_iterator<typename packed_container_type::iterator>;
 | 
				
			||||||
 | 
					    /*! @brief Constant forward iterator type. */
 | 
				
			||||||
 | 
					    using const_local_iterator = internal::dense_set_local_iterator<typename packed_container_type::const_iterator>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Default constructor. */
 | 
				
			||||||
 | 
					    dense_set()
 | 
				
			||||||
 | 
					        : dense_set{minimum_capacity} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs an empty container with a given allocator.
 | 
				
			||||||
 | 
					     * @param allocator The allocator to use.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    explicit dense_set(const allocator_type &allocator)
 | 
				
			||||||
 | 
					        : dense_set{minimum_capacity, hasher{}, key_equal{}, allocator} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs an empty container with a given allocator and user
 | 
				
			||||||
 | 
					     * supplied minimal number of buckets.
 | 
				
			||||||
 | 
					     * @param cnt Minimal number of buckets.
 | 
				
			||||||
 | 
					     * @param allocator The allocator to use.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    dense_set(const size_type cnt, const allocator_type &allocator)
 | 
				
			||||||
 | 
					        : dense_set{cnt, hasher{}, key_equal{}, allocator} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs an empty container with a given allocator, hash
 | 
				
			||||||
 | 
					     * function and user supplied minimal number of buckets.
 | 
				
			||||||
 | 
					     * @param cnt Minimal number of buckets.
 | 
				
			||||||
 | 
					     * @param hash Hash function to use.
 | 
				
			||||||
 | 
					     * @param allocator The allocator to use.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    dense_set(const size_type cnt, const hasher &hash, const allocator_type &allocator)
 | 
				
			||||||
 | 
					        : dense_set{cnt, hash, key_equal{}, allocator} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs an empty container with a given allocator, hash
 | 
				
			||||||
 | 
					     * function, compare function and user supplied minimal number of buckets.
 | 
				
			||||||
 | 
					     * @param cnt Minimal number of buckets.
 | 
				
			||||||
 | 
					     * @param hash Hash function to use.
 | 
				
			||||||
 | 
					     * @param equal Compare function to use.
 | 
				
			||||||
 | 
					     * @param allocator The allocator to use.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    explicit dense_set(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
 | 
				
			||||||
 | 
					        : sparse{allocator, hash},
 | 
				
			||||||
 | 
					          packed{allocator, equal},
 | 
				
			||||||
 | 
					          threshold{default_threshold} {
 | 
				
			||||||
 | 
					        rehash(cnt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Default copy constructor. */
 | 
				
			||||||
 | 
					    dense_set(const dense_set &) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Allocator-extended copy constructor.
 | 
				
			||||||
 | 
					     * @param other The instance to copy from.
 | 
				
			||||||
 | 
					     * @param allocator The allocator to use.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    dense_set(const dense_set &other, const allocator_type &allocator)
 | 
				
			||||||
 | 
					        : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
 | 
				
			||||||
 | 
					          packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
 | 
				
			||||||
 | 
					          threshold{other.threshold} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Default move constructor. */
 | 
				
			||||||
 | 
					    dense_set(dense_set &&) noexcept(std::is_nothrow_move_constructible_v<compressed_pair<sparse_container_type, hasher>> &&std::is_nothrow_move_constructible_v<compressed_pair<packed_container_type, key_equal>>) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Allocator-extended move constructor.
 | 
				
			||||||
 | 
					     * @param other The instance to move from.
 | 
				
			||||||
 | 
					     * @param allocator The allocator to use.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    dense_set(dense_set &&other, const allocator_type &allocator)
 | 
				
			||||||
 | 
					        : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
 | 
				
			||||||
 | 
					          packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
 | 
				
			||||||
 | 
					          threshold{other.threshold} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Default copy assignment operator.
 | 
				
			||||||
 | 
					     * @return This container.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    dense_set &operator=(const dense_set &) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Default move assignment operator.
 | 
				
			||||||
 | 
					     * @return This container.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    dense_set &operator=(dense_set &&) noexcept(std::is_nothrow_move_assignable_v<compressed_pair<sparse_container_type, hasher>> &&std::is_nothrow_move_assignable_v<compressed_pair<packed_container_type, key_equal>>) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the associated allocator.
 | 
				
			||||||
 | 
					     * @return The associated allocator.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
 | 
				
			||||||
 | 
					        return sparse.first().get_allocator();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an iterator to the beginning.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * If the array is empty, the returned iterator will be equal to `end()`.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return An iterator to the first instance of the internal array.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] const_iterator cbegin() const noexcept {
 | 
				
			||||||
 | 
					        return packed.first().begin();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc cbegin */
 | 
				
			||||||
 | 
					    [[nodiscard]] const_iterator begin() const noexcept {
 | 
				
			||||||
 | 
					        return cbegin();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc begin */
 | 
				
			||||||
 | 
					    [[nodiscard]] iterator begin() noexcept {
 | 
				
			||||||
 | 
					        return packed.first().begin();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an iterator to the end.
 | 
				
			||||||
 | 
					     * @return An iterator to the element following the last instance of the
 | 
				
			||||||
 | 
					     * internal array.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] const_iterator cend() const noexcept {
 | 
				
			||||||
 | 
					        return packed.first().end();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc cend */
 | 
				
			||||||
 | 
					    [[nodiscard]] const_iterator end() const noexcept {
 | 
				
			||||||
 | 
					        return cend();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc end */
 | 
				
			||||||
 | 
					    [[nodiscard]] iterator end() noexcept {
 | 
				
			||||||
 | 
					        return packed.first().end();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Checks whether a container is empty.
 | 
				
			||||||
 | 
					     * @return True if the container is empty, false otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] bool empty() const noexcept {
 | 
				
			||||||
 | 
					        return packed.first().empty();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the number of elements in a container.
 | 
				
			||||||
 | 
					     * @return Number of elements in a container.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] size_type size() const noexcept {
 | 
				
			||||||
 | 
					        return packed.first().size();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the maximum possible number of elements.
 | 
				
			||||||
 | 
					     * @return Maximum possible number of elements.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] size_type max_size() const noexcept {
 | 
				
			||||||
 | 
					        return packed.first().max_size();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Clears the container. */
 | 
				
			||||||
 | 
					    void clear() noexcept {
 | 
				
			||||||
 | 
					        sparse.first().clear();
 | 
				
			||||||
 | 
					        packed.first().clear();
 | 
				
			||||||
 | 
					        rehash(0u);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Inserts an element into the container, if it does not exist.
 | 
				
			||||||
 | 
					     * @param value An element to insert into the container.
 | 
				
			||||||
 | 
					     * @return A pair consisting of an iterator to the inserted element (or to
 | 
				
			||||||
 | 
					     * the element that prevented the insertion) and a bool denoting whether the
 | 
				
			||||||
 | 
					     * insertion took place.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    std::pair<iterator, bool> insert(const value_type &value) {
 | 
				
			||||||
 | 
					        return insert_or_do_nothing(value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc insert */
 | 
				
			||||||
 | 
					    std::pair<iterator, bool> insert(value_type &&value) {
 | 
				
			||||||
 | 
					        return insert_or_do_nothing(std::move(value));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Inserts elements into the container, if they do not exist.
 | 
				
			||||||
 | 
					     * @tparam It Type of input iterator.
 | 
				
			||||||
 | 
					     * @param first An iterator to the first element of the range of elements.
 | 
				
			||||||
 | 
					     * @param last An iterator past the last element of the range of elements.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename It>
 | 
				
			||||||
 | 
					    void insert(It first, It last) {
 | 
				
			||||||
 | 
					        for(; first != last; ++first) {
 | 
				
			||||||
 | 
					            insert(*first);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs an element in-place, if it does not exist.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * The element is also constructed when the container already has the key,
 | 
				
			||||||
 | 
					     * in which case the newly constructed object is destroyed immediately.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @tparam Args Types of arguments to forward to the constructor of the
 | 
				
			||||||
 | 
					     * element.
 | 
				
			||||||
 | 
					     * @param args Arguments to forward to the constructor of the element.
 | 
				
			||||||
 | 
					     * @return A pair consisting of an iterator to the inserted element (or to
 | 
				
			||||||
 | 
					     * the element that prevented the insertion) and a bool denoting whether the
 | 
				
			||||||
 | 
					     * insertion took place.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename... Args>
 | 
				
			||||||
 | 
					    std::pair<iterator, bool> emplace(Args &&...args) {
 | 
				
			||||||
 | 
					        if constexpr(((sizeof...(Args) == 1u) && ... && std::is_same_v<std::decay_t<Args>, value_type>)) {
 | 
				
			||||||
 | 
					            return insert_or_do_nothing(std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            auto &node = packed.first().emplace_back(std::piecewise_construct, std::make_tuple(packed.first().size()), std::forward_as_tuple(std::forward<Args>(args)...));
 | 
				
			||||||
 | 
					            const auto index = value_to_bucket(node.second);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(auto it = constrained_find(node.second, index); it != end()) {
 | 
				
			||||||
 | 
					                packed.first().pop_back();
 | 
				
			||||||
 | 
					                return std::make_pair(it, false);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::swap(node.first, sparse.first()[index]);
 | 
				
			||||||
 | 
					            rehash_if_required();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return std::make_pair(--end(), true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Removes an element from a given position.
 | 
				
			||||||
 | 
					     * @param pos An iterator to the element to remove.
 | 
				
			||||||
 | 
					     * @return An iterator following the removed element.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    iterator erase(const_iterator pos) {
 | 
				
			||||||
 | 
					        const auto diff = pos - cbegin();
 | 
				
			||||||
 | 
					        erase(*pos);
 | 
				
			||||||
 | 
					        return begin() + diff;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Removes the given elements from a container.
 | 
				
			||||||
 | 
					     * @param first An iterator to the first element of the range of elements.
 | 
				
			||||||
 | 
					     * @param last An iterator past the last element of the range of elements.
 | 
				
			||||||
 | 
					     * @return An iterator following the last removed element.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    iterator erase(const_iterator first, const_iterator last) {
 | 
				
			||||||
 | 
					        const auto dist = first - cbegin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for(auto from = last - cbegin(); from != dist; --from) {
 | 
				
			||||||
 | 
					            erase(packed.first()[from - 1u].second);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (begin() + dist);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Removes the element associated with a given value.
 | 
				
			||||||
 | 
					     * @param value Value of an element to remove.
 | 
				
			||||||
 | 
					     * @return Number of elements removed (either 0 or 1).
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    size_type erase(const value_type &value) {
 | 
				
			||||||
 | 
					        for(size_type *curr = sparse.first().data() + value_to_bucket(value); *curr != (std::numeric_limits<size_type>::max)(); curr = &packed.first()[*curr].first) {
 | 
				
			||||||
 | 
					            if(packed.second()(packed.first()[*curr].second, value)) {
 | 
				
			||||||
 | 
					                const auto index = *curr;
 | 
				
			||||||
 | 
					                *curr = packed.first()[*curr].first;
 | 
				
			||||||
 | 
					                move_and_pop(index);
 | 
				
			||||||
 | 
					                return 1u;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return 0u;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Exchanges the contents with those of a given container.
 | 
				
			||||||
 | 
					     * @param other Container to exchange the content with.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void swap(dense_set &other) {
 | 
				
			||||||
 | 
					        using std::swap;
 | 
				
			||||||
 | 
					        swap(sparse, other.sparse);
 | 
				
			||||||
 | 
					        swap(packed, other.packed);
 | 
				
			||||||
 | 
					        swap(threshold, other.threshold);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the number of elements matching a value (either 1 or 0).
 | 
				
			||||||
 | 
					     * @param key Key value of an element to search for.
 | 
				
			||||||
 | 
					     * @return Number of elements matching the key (either 1 or 0).
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] size_type count(const value_type &key) const {
 | 
				
			||||||
 | 
					        return find(key) != end();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the number of elements matching a key (either 1 or 0).
 | 
				
			||||||
 | 
					     * @tparam Other Type of the key value of an element to search for.
 | 
				
			||||||
 | 
					     * @param key Key value of an element to search for.
 | 
				
			||||||
 | 
					     * @return Number of elements matching the key (either 1 or 0).
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Other>
 | 
				
			||||||
 | 
					    [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>>
 | 
				
			||||||
 | 
					    count(const Other &key) const {
 | 
				
			||||||
 | 
					        return find(key) != end();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Finds an element with a given value.
 | 
				
			||||||
 | 
					     * @param value Value of an element to search for.
 | 
				
			||||||
 | 
					     * @return An iterator to an element with the given value. If no such
 | 
				
			||||||
 | 
					     * element is found, a past-the-end iterator is returned.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] iterator find(const value_type &value) {
 | 
				
			||||||
 | 
					        return constrained_find(value, value_to_bucket(value));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc find */
 | 
				
			||||||
 | 
					    [[nodiscard]] const_iterator find(const value_type &value) const {
 | 
				
			||||||
 | 
					        return constrained_find(value, value_to_bucket(value));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Finds an element that compares _equivalent_ to a given value.
 | 
				
			||||||
 | 
					     * @tparam Other Type of an element to search for.
 | 
				
			||||||
 | 
					     * @param value Value of an element to search for.
 | 
				
			||||||
 | 
					     * @return An iterator to an element with the given value. If no such
 | 
				
			||||||
 | 
					     * element is found, a past-the-end iterator is returned.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Other>
 | 
				
			||||||
 | 
					    [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
 | 
				
			||||||
 | 
					    find(const Other &value) {
 | 
				
			||||||
 | 
					        return constrained_find(value, value_to_bucket(value));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc find */
 | 
				
			||||||
 | 
					    template<typename Other>
 | 
				
			||||||
 | 
					    [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
 | 
				
			||||||
 | 
					    find(const Other &value) const {
 | 
				
			||||||
 | 
					        return constrained_find(value, value_to_bucket(value));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns a range containing all elements with a given value.
 | 
				
			||||||
 | 
					     * @param value Value of an element to search for.
 | 
				
			||||||
 | 
					     * @return A pair of iterators pointing to the first element and past the
 | 
				
			||||||
 | 
					     * last element of the range.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] std::pair<iterator, iterator> equal_range(const value_type &value) {
 | 
				
			||||||
 | 
					        const auto it = find(value);
 | 
				
			||||||
 | 
					        return {it, it + !(it == end())};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc equal_range */
 | 
				
			||||||
 | 
					    [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const value_type &value) const {
 | 
				
			||||||
 | 
					        const auto it = find(value);
 | 
				
			||||||
 | 
					        return {it, it + !(it == cend())};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns a range containing all elements that compare _equivalent_
 | 
				
			||||||
 | 
					     * to a given value.
 | 
				
			||||||
 | 
					     * @tparam Other Type of an element to search for.
 | 
				
			||||||
 | 
					     * @param value Value of an element to search for.
 | 
				
			||||||
 | 
					     * @return A pair of iterators pointing to the first element and past the
 | 
				
			||||||
 | 
					     * last element of the range.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Other>
 | 
				
			||||||
 | 
					    [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
 | 
				
			||||||
 | 
					    equal_range(const Other &value) {
 | 
				
			||||||
 | 
					        const auto it = find(value);
 | 
				
			||||||
 | 
					        return {it, it + !(it == end())};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc equal_range */
 | 
				
			||||||
 | 
					    template<typename Other>
 | 
				
			||||||
 | 
					    [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
 | 
				
			||||||
 | 
					    equal_range(const Other &value) const {
 | 
				
			||||||
 | 
					        const auto it = find(value);
 | 
				
			||||||
 | 
					        return {it, it + !(it == cend())};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Checks if the container contains an element with a given value.
 | 
				
			||||||
 | 
					     * @param value Value of an element to search for.
 | 
				
			||||||
 | 
					     * @return True if there is such an element, false otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] bool contains(const value_type &value) const {
 | 
				
			||||||
 | 
					        return (find(value) != cend());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Checks if the container contains an element that compares
 | 
				
			||||||
 | 
					     * _equivalent_ to a given value.
 | 
				
			||||||
 | 
					     * @tparam Other Type of an element to search for.
 | 
				
			||||||
 | 
					     * @param value Value of an element to search for.
 | 
				
			||||||
 | 
					     * @return True if there is such an element, false otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Other>
 | 
				
			||||||
 | 
					    [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
 | 
				
			||||||
 | 
					    contains(const Other &value) const {
 | 
				
			||||||
 | 
					        return (find(value) != cend());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an iterator to the beginning of a given bucket.
 | 
				
			||||||
 | 
					     * @param index An index of a bucket to access.
 | 
				
			||||||
 | 
					     * @return An iterator to the beginning of the given bucket.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] const_local_iterator cbegin(const size_type index) const {
 | 
				
			||||||
 | 
					        return {packed.first().begin(), sparse.first()[index]};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an iterator to the beginning of a given bucket.
 | 
				
			||||||
 | 
					     * @param index An index of a bucket to access.
 | 
				
			||||||
 | 
					     * @return An iterator to the beginning of the given bucket.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] const_local_iterator begin(const size_type index) const {
 | 
				
			||||||
 | 
					        return cbegin(index);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an iterator to the beginning of a given bucket.
 | 
				
			||||||
 | 
					     * @param index An index of a bucket to access.
 | 
				
			||||||
 | 
					     * @return An iterator to the beginning of the given bucket.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] local_iterator begin(const size_type index) {
 | 
				
			||||||
 | 
					        return {packed.first().begin(), sparse.first()[index]};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an iterator to the end of a given bucket.
 | 
				
			||||||
 | 
					     * @param index An index of a bucket to access.
 | 
				
			||||||
 | 
					     * @return An iterator to the end of the given bucket.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
 | 
				
			||||||
 | 
					        return {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an iterator to the end of a given bucket.
 | 
				
			||||||
 | 
					     * @param index An index of a bucket to access.
 | 
				
			||||||
 | 
					     * @return An iterator to the end of the given bucket.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] const_local_iterator end(const size_type index) const {
 | 
				
			||||||
 | 
					        return cend(index);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an iterator to the end of a given bucket.
 | 
				
			||||||
 | 
					     * @param index An index of a bucket to access.
 | 
				
			||||||
 | 
					     * @return An iterator to the end of the given bucket.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
 | 
				
			||||||
 | 
					        return {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the number of buckets.
 | 
				
			||||||
 | 
					     * @return The number of buckets.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] size_type bucket_count() const {
 | 
				
			||||||
 | 
					        return sparse.first().size();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the maximum number of buckets.
 | 
				
			||||||
 | 
					     * @return The maximum number of buckets.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] size_type max_bucket_count() const {
 | 
				
			||||||
 | 
					        return sparse.first().max_size();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the number of elements in a given bucket.
 | 
				
			||||||
 | 
					     * @param index The index of the bucket to examine.
 | 
				
			||||||
 | 
					     * @return The number of elements in the given bucket.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] size_type bucket_size(const size_type index) const {
 | 
				
			||||||
 | 
					        return static_cast<size_type>(std::distance(begin(index), end(index)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the bucket for a given element.
 | 
				
			||||||
 | 
					     * @param value The value of the element to examine.
 | 
				
			||||||
 | 
					     * @return The bucket for the given element.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] size_type bucket(const value_type &value) const {
 | 
				
			||||||
 | 
					        return value_to_bucket(value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the average number of elements per bucket.
 | 
				
			||||||
 | 
					     * @return The average number of elements per bucket.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] float load_factor() const {
 | 
				
			||||||
 | 
					        return size() / static_cast<float>(bucket_count());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the maximum average number of elements per bucket.
 | 
				
			||||||
 | 
					     * @return The maximum average number of elements per bucket.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] float max_load_factor() const {
 | 
				
			||||||
 | 
					        return threshold;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Sets the desired maximum average number of elements per bucket.
 | 
				
			||||||
 | 
					     * @param value A desired maximum average number of elements per bucket.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void max_load_factor(const float value) {
 | 
				
			||||||
 | 
					        ENTT_ASSERT(value > 0.f, "Invalid load factor");
 | 
				
			||||||
 | 
					        threshold = value;
 | 
				
			||||||
 | 
					        rehash(0u);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Reserves at least the specified number of buckets and regenerates
 | 
				
			||||||
 | 
					     * the hash table.
 | 
				
			||||||
 | 
					     * @param cnt New number of buckets.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void rehash(const size_type cnt) {
 | 
				
			||||||
 | 
					        auto value = cnt > minimum_capacity ? cnt : minimum_capacity;
 | 
				
			||||||
 | 
					        const auto cap = static_cast<size_type>(size() / max_load_factor());
 | 
				
			||||||
 | 
					        value = value > cap ? value : cap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
 | 
				
			||||||
 | 
					            sparse.first().resize(sz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for(auto &&elem: sparse.first()) {
 | 
				
			||||||
 | 
					                elem = std::numeric_limits<size_type>::max();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for(size_type pos{}, last = size(); pos < last; ++pos) {
 | 
				
			||||||
 | 
					                const auto index = value_to_bucket(packed.first()[pos].second);
 | 
				
			||||||
 | 
					                packed.first()[pos].first = std::exchange(sparse.first()[index], pos);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Reserves space for at least the specified number of elements and
 | 
				
			||||||
 | 
					     * regenerates the hash table.
 | 
				
			||||||
 | 
					     * @param cnt New number of elements.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void reserve(const size_type cnt) {
 | 
				
			||||||
 | 
					        packed.first().reserve(cnt);
 | 
				
			||||||
 | 
					        rehash(static_cast<size_type>(std::ceil(cnt / max_load_factor())));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the function used to hash the elements.
 | 
				
			||||||
 | 
					     * @return The function used to hash the elements.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] hasher hash_function() const {
 | 
				
			||||||
 | 
					        return sparse.second();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the function used to compare elements for equality.
 | 
				
			||||||
 | 
					     * @return The function used to compare elements for equality.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] key_equal key_eq() const {
 | 
				
			||||||
 | 
					        return packed.second();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    compressed_pair<sparse_container_type, hasher> sparse;
 | 
				
			||||||
 | 
					    compressed_pair<packed_container_type, key_equal> packed;
 | 
				
			||||||
 | 
					    float threshold;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										26
									
								
								external/entt/entt/src/entt/container/fwd.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								external/entt/entt/src/entt/container/fwd.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CONTAINER_FWD_HPP
 | 
				
			||||||
 | 
					#define ENTT_CONTAINER_FWD_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <functional>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<
 | 
				
			||||||
 | 
					    typename Key,
 | 
				
			||||||
 | 
					    typename Type,
 | 
				
			||||||
 | 
					    typename = std::hash<Key>,
 | 
				
			||||||
 | 
					    typename = std::equal_to<Key>,
 | 
				
			||||||
 | 
					    typename = std::allocator<std::pair<const Key, Type>>>
 | 
				
			||||||
 | 
					class dense_map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<
 | 
				
			||||||
 | 
					    typename Type,
 | 
				
			||||||
 | 
					    typename = std::hash<Type>,
 | 
				
			||||||
 | 
					    typename = std::equal_to<Type>,
 | 
				
			||||||
 | 
					    typename = std::allocator<Type>>
 | 
				
			||||||
 | 
					class dense_set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										138
									
								
								external/entt/entt/src/entt/core/algorithm.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								external/entt/entt/src/entt/core/algorithm.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,138 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_ALGORITHM_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_ALGORITHM_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <algorithm>
 | 
				
			||||||
 | 
					#include <functional>
 | 
				
			||||||
 | 
					#include <iterator>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include "utility.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Function object to wrap `std::sort` in a class type.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unfortunately, `std::sort` cannot be passed as template argument to a class
 | 
				
			||||||
 | 
					 * template or a function template.<br/>
 | 
				
			||||||
 | 
					 * This class fills the gap by wrapping some flavors of `std::sort` in a
 | 
				
			||||||
 | 
					 * function object.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct std_sort {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Sorts the elements in a range.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Sorts the elements in a range using the given binary comparison function.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @tparam It Type of random access iterator.
 | 
				
			||||||
 | 
					     * @tparam Compare Type of comparison function object.
 | 
				
			||||||
 | 
					     * @tparam Args Types of arguments to forward to the sort function.
 | 
				
			||||||
 | 
					     * @param first An iterator to the first element of the range to sort.
 | 
				
			||||||
 | 
					     * @param last An iterator past the last element of the range to sort.
 | 
				
			||||||
 | 
					     * @param compare A valid comparison function object.
 | 
				
			||||||
 | 
					     * @param args Arguments to forward to the sort function, if any.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename It, typename Compare = std::less<>, typename... Args>
 | 
				
			||||||
 | 
					    void operator()(It first, It last, Compare compare = Compare{}, Args &&...args) const {
 | 
				
			||||||
 | 
					        std::sort(std::forward<Args>(args)..., std::move(first), std::move(last), std::move(compare));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Function object for performing insertion sort. */
 | 
				
			||||||
 | 
					struct insertion_sort {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Sorts the elements in a range.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Sorts the elements in a range using the given binary comparison function.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @tparam It Type of random access iterator.
 | 
				
			||||||
 | 
					     * @tparam Compare Type of comparison function object.
 | 
				
			||||||
 | 
					     * @param first An iterator to the first element of the range to sort.
 | 
				
			||||||
 | 
					     * @param last An iterator past the last element of the range to sort.
 | 
				
			||||||
 | 
					     * @param compare A valid comparison function object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename It, typename Compare = std::less<>>
 | 
				
			||||||
 | 
					    void operator()(It first, It last, Compare compare = Compare{}) const {
 | 
				
			||||||
 | 
					        if(first < last) {
 | 
				
			||||||
 | 
					            for(auto it = first + 1; it < last; ++it) {
 | 
				
			||||||
 | 
					                auto value = std::move(*it);
 | 
				
			||||||
 | 
					                auto pre = it;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for(; pre > first && compare(value, *(pre - 1)); --pre) {
 | 
				
			||||||
 | 
					                    *pre = std::move(*(pre - 1));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                *pre = std::move(value);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Function object for performing LSD radix sort.
 | 
				
			||||||
 | 
					 * @tparam Bit Number of bits processed per pass.
 | 
				
			||||||
 | 
					 * @tparam N Maximum number of bits to sort.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<std::size_t Bit, std::size_t N>
 | 
				
			||||||
 | 
					struct radix_sort {
 | 
				
			||||||
 | 
					    static_assert((N % Bit) == 0, "The maximum number of bits to sort must be a multiple of the number of bits processed per pass");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Sorts the elements in a range.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Sorts the elements in a range using the given _getter_ to access the
 | 
				
			||||||
 | 
					     * actual data to be sorted.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * This implementation is inspired by the online book
 | 
				
			||||||
 | 
					     * [Physically Based Rendering](http://www.pbr-book.org/3ed-2018/Primitives_and_Intersection_Acceleration/Bounding_Volume_Hierarchies.html#RadixSort).
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @tparam It Type of random access iterator.
 | 
				
			||||||
 | 
					     * @tparam Getter Type of _getter_ function object.
 | 
				
			||||||
 | 
					     * @param first An iterator to the first element of the range to sort.
 | 
				
			||||||
 | 
					     * @param last An iterator past the last element of the range to sort.
 | 
				
			||||||
 | 
					     * @param getter A valid _getter_ function object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename It, typename Getter = identity>
 | 
				
			||||||
 | 
					    void operator()(It first, It last, Getter getter = Getter{}) const {
 | 
				
			||||||
 | 
					        if(first < last) {
 | 
				
			||||||
 | 
					            constexpr auto passes = N / Bit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            using value_type = typename std::iterator_traits<It>::value_type;
 | 
				
			||||||
 | 
					            std::vector<value_type> aux(std::distance(first, last));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            auto part = [getter = std::move(getter)](auto from, auto to, auto out, auto start) {
 | 
				
			||||||
 | 
					                constexpr auto mask = (1 << Bit) - 1;
 | 
				
			||||||
 | 
					                constexpr auto buckets = 1 << Bit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                std::size_t index[buckets]{};
 | 
				
			||||||
 | 
					                std::size_t count[buckets]{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for(auto it = from; it != to; ++it) {
 | 
				
			||||||
 | 
					                    ++count[(getter(*it) >> start) & mask];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for(std::size_t pos{}, end = buckets - 1u; pos < end; ++pos) {
 | 
				
			||||||
 | 
					                    index[pos + 1u] = index[pos] + count[pos];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for(auto it = from; it != to; ++it) {
 | 
				
			||||||
 | 
					                    out[index[(getter(*it) >> start) & mask]++] = std::move(*it);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for(std::size_t pass = 0; pass < (passes & ~1); pass += 2) {
 | 
				
			||||||
 | 
					                part(first, last, aux.begin(), pass * Bit);
 | 
				
			||||||
 | 
					                part(aux.begin(), aux.end(), first, (pass + 1) * Bit);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if constexpr(passes & 1) {
 | 
				
			||||||
 | 
					                part(first, last, aux.begin(), (passes - 1) * Bit);
 | 
				
			||||||
 | 
					                std::move(aux.begin(), aux.end(), first);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										510
									
								
								external/entt/entt/src/entt/core/any.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										510
									
								
								external/entt/entt/src/entt/core/any.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,510 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_ANY_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_ANY_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include "../config/config.h"
 | 
				
			||||||
 | 
					#include "../core/utility.hpp"
 | 
				
			||||||
 | 
					#include "fwd.hpp"
 | 
				
			||||||
 | 
					#include "type_info.hpp"
 | 
				
			||||||
 | 
					#include "type_traits.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class any_operation : std::uint8_t {
 | 
				
			||||||
 | 
					    copy,
 | 
				
			||||||
 | 
					    move,
 | 
				
			||||||
 | 
					    transfer,
 | 
				
			||||||
 | 
					    assign,
 | 
				
			||||||
 | 
					    destroy,
 | 
				
			||||||
 | 
					    compare,
 | 
				
			||||||
 | 
					    get
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class any_policy : std::uint8_t {
 | 
				
			||||||
 | 
					    owner,
 | 
				
			||||||
 | 
					    ref,
 | 
				
			||||||
 | 
					    cref
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 * @endcond
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief A SBO friendly, type-safe container for single values of any type.
 | 
				
			||||||
 | 
					 * @tparam Len Size of the storage reserved for the small buffer optimization.
 | 
				
			||||||
 | 
					 * @tparam Align Optional alignment requirement.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<std::size_t Len, std::size_t Align>
 | 
				
			||||||
 | 
					class basic_any {
 | 
				
			||||||
 | 
					    using operation = internal::any_operation;
 | 
				
			||||||
 | 
					    using policy = internal::any_policy;
 | 
				
			||||||
 | 
					    using vtable_type = const void *(const operation, const basic_any &, const void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct storage_type {
 | 
				
			||||||
 | 
					        alignas(Align) std::byte data[Len + !Len];
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Type>
 | 
				
			||||||
 | 
					    static constexpr bool in_situ = Len && alignof(Type) <= Align && sizeof(Type) <= Len && std::is_nothrow_move_constructible_v<Type>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Type>
 | 
				
			||||||
 | 
					    static const void *basic_vtable(const operation op, const basic_any &value, const void *other) {
 | 
				
			||||||
 | 
					        static_assert(!std::is_same_v<Type, void> && std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
 | 
				
			||||||
 | 
					        const Type *element = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if constexpr(in_situ<Type>) {
 | 
				
			||||||
 | 
					            element = value.owner() ? reinterpret_cast<const Type *>(&value.storage) : static_cast<const Type *>(value.instance);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            element = static_cast<const Type *>(value.instance);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch(op) {
 | 
				
			||||||
 | 
					        case operation::copy:
 | 
				
			||||||
 | 
					            if constexpr(std::is_copy_constructible_v<Type>) {
 | 
				
			||||||
 | 
					                static_cast<basic_any *>(const_cast<void *>(other))->initialize<Type>(*element);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case operation::move:
 | 
				
			||||||
 | 
					            if constexpr(in_situ<Type>) {
 | 
				
			||||||
 | 
					                if(value.owner()) {
 | 
				
			||||||
 | 
					                    return new(&static_cast<basic_any *>(const_cast<void *>(other))->storage) Type{std::move(*const_cast<Type *>(element))};
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return (static_cast<basic_any *>(const_cast<void *>(other))->instance = std::exchange(const_cast<basic_any &>(value).instance, nullptr));
 | 
				
			||||||
 | 
					        case operation::transfer:
 | 
				
			||||||
 | 
					            if constexpr(std::is_move_assignable_v<Type>) {
 | 
				
			||||||
 | 
					                *const_cast<Type *>(element) = std::move(*static_cast<Type *>(const_cast<void *>(other)));
 | 
				
			||||||
 | 
					                return other;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            [[fallthrough]];
 | 
				
			||||||
 | 
					        case operation::assign:
 | 
				
			||||||
 | 
					            if constexpr(std::is_copy_assignable_v<Type>) {
 | 
				
			||||||
 | 
					                *const_cast<Type *>(element) = *static_cast<const Type *>(other);
 | 
				
			||||||
 | 
					                return other;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case operation::destroy:
 | 
				
			||||||
 | 
					            if constexpr(in_situ<Type>) {
 | 
				
			||||||
 | 
					                element->~Type();
 | 
				
			||||||
 | 
					            } else if constexpr(std::is_array_v<Type>) {
 | 
				
			||||||
 | 
					                delete[] element;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                delete element;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case operation::compare:
 | 
				
			||||||
 | 
					            if constexpr(!std::is_function_v<Type> && !std::is_array_v<Type> && is_equality_comparable_v<Type>) {
 | 
				
			||||||
 | 
					                return *element == *static_cast<const Type *>(other) ? other : nullptr;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                return (element == other) ? other : nullptr;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        case operation::get:
 | 
				
			||||||
 | 
					            return element;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Type, typename... Args>
 | 
				
			||||||
 | 
					    void initialize([[maybe_unused]] Args &&...args) {
 | 
				
			||||||
 | 
					        info = &type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if constexpr(!std::is_void_v<Type>) {
 | 
				
			||||||
 | 
					            vtable = basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if constexpr(std::is_lvalue_reference_v<Type>) {
 | 
				
			||||||
 | 
					                static_assert((std::is_lvalue_reference_v<Args> && ...) && (sizeof...(Args) == 1u), "Invalid arguments");
 | 
				
			||||||
 | 
					                mode = std::is_const_v<std::remove_reference_t<Type>> ? policy::cref : policy::ref;
 | 
				
			||||||
 | 
					                instance = (std::addressof(args), ...);
 | 
				
			||||||
 | 
					            } else if constexpr(in_situ<std::remove_cv_t<std::remove_reference_t<Type>>>) {
 | 
				
			||||||
 | 
					                if constexpr(std::is_aggregate_v<std::remove_cv_t<std::remove_reference_t<Type>>> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<std::remove_cv_t<std::remove_reference_t<Type>>>)) {
 | 
				
			||||||
 | 
					                    new(&storage) std::remove_cv_t<std::remove_reference_t<Type>>{std::forward<Args>(args)...};
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    new(&storage) std::remove_cv_t<std::remove_reference_t<Type>>(std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                if constexpr(std::is_aggregate_v<std::remove_cv_t<std::remove_reference_t<Type>>> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<std::remove_cv_t<std::remove_reference_t<Type>>>)) {
 | 
				
			||||||
 | 
					                    instance = new std::remove_cv_t<std::remove_reference_t<Type>>{std::forward<Args>(args)...};
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    instance = new std::remove_cv_t<std::remove_reference_t<Type>>(std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    basic_any(const basic_any &other, const policy pol) noexcept
 | 
				
			||||||
 | 
					        : instance{other.data()},
 | 
				
			||||||
 | 
					          info{other.info},
 | 
				
			||||||
 | 
					          vtable{other.vtable},
 | 
				
			||||||
 | 
					          mode{pol} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /*! @brief Size of the internal storage. */
 | 
				
			||||||
 | 
					    static constexpr auto length = Len;
 | 
				
			||||||
 | 
					    /*! @brief Alignment requirement. */
 | 
				
			||||||
 | 
					    static constexpr auto alignment = Align;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Default constructor. */
 | 
				
			||||||
 | 
					    constexpr basic_any() noexcept
 | 
				
			||||||
 | 
					        : basic_any{std::in_place_type<void>} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a wrapper by directly initializing the new object.
 | 
				
			||||||
 | 
					     * @tparam Type Type of object to use to initialize the wrapper.
 | 
				
			||||||
 | 
					     * @tparam Args Types of arguments to use to construct the new instance.
 | 
				
			||||||
 | 
					     * @param args Parameters to use to construct the instance.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Type, typename... Args>
 | 
				
			||||||
 | 
					    explicit basic_any(std::in_place_type_t<Type>, Args &&...args)
 | 
				
			||||||
 | 
					        : instance{},
 | 
				
			||||||
 | 
					          info{},
 | 
				
			||||||
 | 
					          vtable{},
 | 
				
			||||||
 | 
					          mode{policy::owner} {
 | 
				
			||||||
 | 
					        initialize<Type>(std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a wrapper from a given value.
 | 
				
			||||||
 | 
					     * @tparam Type Type of object to use to initialize the wrapper.
 | 
				
			||||||
 | 
					     * @param value An instance of an object to use to initialize the wrapper.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>>
 | 
				
			||||||
 | 
					    basic_any(Type &&value)
 | 
				
			||||||
 | 
					        : basic_any{std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Copy constructor.
 | 
				
			||||||
 | 
					     * @param other The instance to copy from.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    basic_any(const basic_any &other)
 | 
				
			||||||
 | 
					        : basic_any{} {
 | 
				
			||||||
 | 
					        if(other.vtable) {
 | 
				
			||||||
 | 
					            other.vtable(operation::copy, other, this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Move constructor.
 | 
				
			||||||
 | 
					     * @param other The instance to move from.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    basic_any(basic_any &&other) noexcept
 | 
				
			||||||
 | 
					        : instance{},
 | 
				
			||||||
 | 
					          info{other.info},
 | 
				
			||||||
 | 
					          vtable{other.vtable},
 | 
				
			||||||
 | 
					          mode{other.mode} {
 | 
				
			||||||
 | 
					        if(other.vtable) {
 | 
				
			||||||
 | 
					            other.vtable(operation::move, other, this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Frees the internal storage, whatever it means. */
 | 
				
			||||||
 | 
					    ~basic_any() {
 | 
				
			||||||
 | 
					        if(vtable && owner()) {
 | 
				
			||||||
 | 
					            vtable(operation::destroy, *this, nullptr);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Copy assignment operator.
 | 
				
			||||||
 | 
					     * @param other The instance to copy from.
 | 
				
			||||||
 | 
					     * @return This any object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    basic_any &operator=(const basic_any &other) {
 | 
				
			||||||
 | 
					        reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(other.vtable) {
 | 
				
			||||||
 | 
					            other.vtable(operation::copy, other, this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Move assignment operator.
 | 
				
			||||||
 | 
					     * @param other The instance to move from.
 | 
				
			||||||
 | 
					     * @return This any object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    basic_any &operator=(basic_any &&other) noexcept {
 | 
				
			||||||
 | 
					        reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(other.vtable) {
 | 
				
			||||||
 | 
					            other.vtable(operation::move, other, this);
 | 
				
			||||||
 | 
					            info = other.info;
 | 
				
			||||||
 | 
					            vtable = other.vtable;
 | 
				
			||||||
 | 
					            mode = other.mode;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Value assignment operator.
 | 
				
			||||||
 | 
					     * @tparam Type Type of object to use to initialize the wrapper.
 | 
				
			||||||
 | 
					     * @param value An instance of an object to use to initialize the wrapper.
 | 
				
			||||||
 | 
					     * @return This any object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Type>
 | 
				
			||||||
 | 
					    std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>, basic_any &>
 | 
				
			||||||
 | 
					    operator=(Type &&value) {
 | 
				
			||||||
 | 
					        emplace<std::decay_t<Type>>(std::forward<Type>(value));
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the object type if any, `type_id<void>()` otherwise.
 | 
				
			||||||
 | 
					     * @return The object type if any, `type_id<void>()` otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] const type_info &type() const noexcept {
 | 
				
			||||||
 | 
					        return *info;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an opaque pointer to the contained instance.
 | 
				
			||||||
 | 
					     * @return An opaque pointer the contained instance, if any.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] const void *data() const noexcept {
 | 
				
			||||||
 | 
					        return vtable ? vtable(operation::get, *this, nullptr) : nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an opaque pointer to the contained instance.
 | 
				
			||||||
 | 
					     * @param req Expected type.
 | 
				
			||||||
 | 
					     * @return An opaque pointer the contained instance, if any.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] const void *data(const type_info &req) const noexcept {
 | 
				
			||||||
 | 
					        return *info == req ? data() : nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an opaque pointer to the contained instance.
 | 
				
			||||||
 | 
					     * @return An opaque pointer the contained instance, if any.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] void *data() noexcept {
 | 
				
			||||||
 | 
					        return mode == policy::cref ? nullptr : const_cast<void *>(std::as_const(*this).data());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an opaque pointer to the contained instance.
 | 
				
			||||||
 | 
					     * @param req Expected type.
 | 
				
			||||||
 | 
					     * @return An opaque pointer the contained instance, if any.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] void *data(const type_info &req) noexcept {
 | 
				
			||||||
 | 
					        return mode == policy::cref ? nullptr : const_cast<void *>(std::as_const(*this).data(req));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Replaces the contained object by creating a new instance directly.
 | 
				
			||||||
 | 
					     * @tparam Type Type of object to use to initialize the wrapper.
 | 
				
			||||||
 | 
					     * @tparam Args Types of arguments to use to construct the new instance.
 | 
				
			||||||
 | 
					     * @param args Parameters to use to construct the instance.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Type, typename... Args>
 | 
				
			||||||
 | 
					    void emplace(Args &&...args) {
 | 
				
			||||||
 | 
					        reset();
 | 
				
			||||||
 | 
					        initialize<Type>(std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Assigns a value to the contained object without replacing it.
 | 
				
			||||||
 | 
					     * @param other The value to assign to the contained object.
 | 
				
			||||||
 | 
					     * @return True in case of success, false otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    bool assign(const basic_any &other) {
 | 
				
			||||||
 | 
					        if(vtable && mode != policy::cref && *info == *other.info) {
 | 
				
			||||||
 | 
					            return (vtable(operation::assign, *this, other.data()) != nullptr);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc assign */
 | 
				
			||||||
 | 
					    bool assign(basic_any &&other) {
 | 
				
			||||||
 | 
					        if(vtable && mode != policy::cref && *info == *other.info) {
 | 
				
			||||||
 | 
					            if(auto *val = other.data(); val) {
 | 
				
			||||||
 | 
					                return (vtable(operation::transfer, *this, val) != nullptr);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                return (vtable(operation::assign, *this, std::as_const(other).data()) != nullptr);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Destroys contained object */
 | 
				
			||||||
 | 
					    void reset() {
 | 
				
			||||||
 | 
					        if(vtable && owner()) {
 | 
				
			||||||
 | 
					            vtable(operation::destroy, *this, nullptr);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // unnecessary but it helps to detect nasty bugs
 | 
				
			||||||
 | 
					        ENTT_ASSERT((instance = nullptr) == nullptr, "");
 | 
				
			||||||
 | 
					        info = &type_id<void>();
 | 
				
			||||||
 | 
					        vtable = nullptr;
 | 
				
			||||||
 | 
					        mode = policy::owner;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns false if a wrapper is empty, true otherwise.
 | 
				
			||||||
 | 
					     * @return False if the wrapper is empty, true otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] explicit operator bool() const noexcept {
 | 
				
			||||||
 | 
					        return vtable != nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Checks if two wrappers differ in their content.
 | 
				
			||||||
 | 
					     * @param other Wrapper with which to compare.
 | 
				
			||||||
 | 
					     * @return False if the two objects differ in their content, true otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] bool operator==(const basic_any &other) const noexcept {
 | 
				
			||||||
 | 
					        if(vtable && *info == *other.info) {
 | 
				
			||||||
 | 
					            return (vtable(operation::compare, *this, other.data()) != nullptr);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (!vtable && !other.vtable);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Checks if two wrappers differ in their content.
 | 
				
			||||||
 | 
					     * @param other Wrapper with which to compare.
 | 
				
			||||||
 | 
					     * @return True if the two objects differ in their content, false otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] bool operator!=(const basic_any &other) const noexcept {
 | 
				
			||||||
 | 
					        return !(*this == other);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Aliasing constructor.
 | 
				
			||||||
 | 
					     * @return A wrapper that shares a reference to an unmanaged object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] basic_any as_ref() noexcept {
 | 
				
			||||||
 | 
					        return basic_any{*this, (mode == policy::cref ? policy::cref : policy::ref)};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc as_ref */
 | 
				
			||||||
 | 
					    [[nodiscard]] basic_any as_ref() const noexcept {
 | 
				
			||||||
 | 
					        return basic_any{*this, policy::cref};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns true if a wrapper owns its object, false otherwise.
 | 
				
			||||||
 | 
					     * @return True if the wrapper owns its object, false otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] bool owner() const noexcept {
 | 
				
			||||||
 | 
					        return (mode == policy::owner);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    union {
 | 
				
			||||||
 | 
					        const void *instance;
 | 
				
			||||||
 | 
					        storage_type storage;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    const type_info *info;
 | 
				
			||||||
 | 
					    vtable_type *vtable;
 | 
				
			||||||
 | 
					    policy mode;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Performs type-safe access to the contained object.
 | 
				
			||||||
 | 
					 * @tparam Type Type to which conversion is required.
 | 
				
			||||||
 | 
					 * @tparam Len Size of the storage reserved for the small buffer optimization.
 | 
				
			||||||
 | 
					 * @tparam Align Alignment requirement.
 | 
				
			||||||
 | 
					 * @param data Target any object.
 | 
				
			||||||
 | 
					 * @return The element converted to the requested type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, std::size_t Len, std::size_t Align>
 | 
				
			||||||
 | 
					[[nodiscard]] Type any_cast(const basic_any<Len, Align> &data) noexcept {
 | 
				
			||||||
 | 
					    const auto *const instance = any_cast<std::remove_reference_t<Type>>(&data);
 | 
				
			||||||
 | 
					    ENTT_ASSERT(instance, "Invalid instance");
 | 
				
			||||||
 | 
					    return static_cast<Type>(*instance);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc any_cast */
 | 
				
			||||||
 | 
					template<typename Type, std::size_t Len, std::size_t Align>
 | 
				
			||||||
 | 
					[[nodiscard]] Type any_cast(basic_any<Len, Align> &data) noexcept {
 | 
				
			||||||
 | 
					    // forces const on non-reference types to make them work also with wrappers for const references
 | 
				
			||||||
 | 
					    auto *const instance = any_cast<std::remove_reference_t<const Type>>(&data);
 | 
				
			||||||
 | 
					    ENTT_ASSERT(instance, "Invalid instance");
 | 
				
			||||||
 | 
					    return static_cast<Type>(*instance);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc any_cast */
 | 
				
			||||||
 | 
					template<typename Type, std::size_t Len, std::size_t Align>
 | 
				
			||||||
 | 
					[[nodiscard]] Type any_cast(basic_any<Len, Align> &&data) noexcept {
 | 
				
			||||||
 | 
					    if constexpr(std::is_copy_constructible_v<std::remove_cv_t<std::remove_reference_t<Type>>>) {
 | 
				
			||||||
 | 
					        if(auto *const instance = any_cast<std::remove_reference_t<Type>>(&data); instance) {
 | 
				
			||||||
 | 
					            return static_cast<Type>(std::move(*instance));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return any_cast<Type>(data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        auto *const instance = any_cast<std::remove_reference_t<Type>>(&data);
 | 
				
			||||||
 | 
					        ENTT_ASSERT(instance, "Invalid instance");
 | 
				
			||||||
 | 
					        return static_cast<Type>(std::move(*instance));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc any_cast */
 | 
				
			||||||
 | 
					template<typename Type, std::size_t Len, std::size_t Align>
 | 
				
			||||||
 | 
					[[nodiscard]] const Type *any_cast(const basic_any<Len, Align> *data) noexcept {
 | 
				
			||||||
 | 
					    const auto &info = type_id<std::remove_cv_t<Type>>();
 | 
				
			||||||
 | 
					    return static_cast<const Type *>(data->data(info));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc any_cast */
 | 
				
			||||||
 | 
					template<typename Type, std::size_t Len, std::size_t Align>
 | 
				
			||||||
 | 
					[[nodiscard]] Type *any_cast(basic_any<Len, Align> *data) noexcept {
 | 
				
			||||||
 | 
					    if constexpr(std::is_const_v<Type>) {
 | 
				
			||||||
 | 
					        // last attempt to make wrappers for const references return their values
 | 
				
			||||||
 | 
					        return any_cast<Type>(&std::as_const(*data));
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        const auto &info = type_id<std::remove_cv_t<Type>>();
 | 
				
			||||||
 | 
					        return static_cast<Type *>(data->data(info));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Constructs a wrapper from a given type, passing it all arguments.
 | 
				
			||||||
 | 
					 * @tparam Type Type of object to use to initialize the wrapper.
 | 
				
			||||||
 | 
					 * @tparam Len Size of the storage reserved for the small buffer optimization.
 | 
				
			||||||
 | 
					 * @tparam Align Optional alignment requirement.
 | 
				
			||||||
 | 
					 * @tparam Args Types of arguments to use to construct the new instance.
 | 
				
			||||||
 | 
					 * @param args Parameters to use to construct the instance.
 | 
				
			||||||
 | 
					 * @return A properly initialized wrapper for an object of the given type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename... Args>
 | 
				
			||||||
 | 
					[[nodiscard]] basic_any<Len, Align> make_any(Args &&...args) {
 | 
				
			||||||
 | 
					    return basic_any<Len, Align>{std::in_place_type<Type>, std::forward<Args>(args)...};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Forwards its argument and avoids copies for lvalue references.
 | 
				
			||||||
 | 
					 * @tparam Len Size of the storage reserved for the small buffer optimization.
 | 
				
			||||||
 | 
					 * @tparam Align Optional alignment requirement.
 | 
				
			||||||
 | 
					 * @tparam Type Type of argument to use to construct the new instance.
 | 
				
			||||||
 | 
					 * @param value Parameter to use to construct the instance.
 | 
				
			||||||
 | 
					 * @return A properly initialized and not necessarily owning wrapper.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] basic_any<Len, Align> forward_as_any(Type &&value) {
 | 
				
			||||||
 | 
					    return basic_any<Len, Align>{std::in_place_type<Type &&>, std::forward<Type>(value)};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										30
									
								
								external/entt/entt/src/entt/core/attribute.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								external/entt/entt/src/entt/core/attribute.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_ATTRIBUTE_H
 | 
				
			||||||
 | 
					#define ENTT_CORE_ATTRIBUTE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ENTT_EXPORT
 | 
				
			||||||
 | 
					#    if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
 | 
				
			||||||
 | 
					#        define ENTT_EXPORT __declspec(dllexport)
 | 
				
			||||||
 | 
					#        define ENTT_IMPORT __declspec(dllimport)
 | 
				
			||||||
 | 
					#        define ENTT_HIDDEN
 | 
				
			||||||
 | 
					#    elif defined __GNUC__ && __GNUC__ >= 4
 | 
				
			||||||
 | 
					#        define ENTT_EXPORT __attribute__((visibility("default")))
 | 
				
			||||||
 | 
					#        define ENTT_IMPORT __attribute__((visibility("default")))
 | 
				
			||||||
 | 
					#        define ENTT_HIDDEN __attribute__((visibility("hidden")))
 | 
				
			||||||
 | 
					#    else /* Unsupported compiler */
 | 
				
			||||||
 | 
					#        define ENTT_EXPORT
 | 
				
			||||||
 | 
					#        define ENTT_IMPORT
 | 
				
			||||||
 | 
					#        define ENTT_HIDDEN
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ENTT_API
 | 
				
			||||||
 | 
					#    if defined ENTT_API_EXPORT
 | 
				
			||||||
 | 
					#        define ENTT_API ENTT_EXPORT
 | 
				
			||||||
 | 
					#    elif defined ENTT_API_IMPORT
 | 
				
			||||||
 | 
					#        define ENTT_API ENTT_IMPORT
 | 
				
			||||||
 | 
					#    else /* No API */
 | 
				
			||||||
 | 
					#        define ENTT_API
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										279
									
								
								external/entt/entt/src/entt/core/compressed_pair.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										279
									
								
								external/entt/entt/src/entt/core/compressed_pair.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,279 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_COMPRESSED_PAIR_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include "type_traits.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type, std::size_t, typename = void>
 | 
				
			||||||
 | 
					struct compressed_pair_element {
 | 
				
			||||||
 | 
					    using reference = Type &;
 | 
				
			||||||
 | 
					    using const_reference = const Type &;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<Type>>>
 | 
				
			||||||
 | 
					    constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>)
 | 
				
			||||||
 | 
					        : value{} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
 | 
				
			||||||
 | 
					    constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
 | 
				
			||||||
 | 
					        : value{std::forward<Arg>(arg)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename... Args, std::size_t... Index>
 | 
				
			||||||
 | 
					    constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
 | 
				
			||||||
 | 
					        : value{std::forward<Args>(std::get<Index>(args))...} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr reference get() noexcept {
 | 
				
			||||||
 | 
					        return value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr const_reference get() const noexcept {
 | 
				
			||||||
 | 
					        return value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    Type value;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type, std::size_t Tag>
 | 
				
			||||||
 | 
					struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
 | 
				
			||||||
 | 
					    using reference = Type &;
 | 
				
			||||||
 | 
					    using const_reference = const Type &;
 | 
				
			||||||
 | 
					    using base_type = Type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<base_type>>>
 | 
				
			||||||
 | 
					    constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
 | 
				
			||||||
 | 
					        : base_type{} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
 | 
				
			||||||
 | 
					    constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
 | 
				
			||||||
 | 
					        : base_type{std::forward<Arg>(arg)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename... Args, std::size_t... Index>
 | 
				
			||||||
 | 
					    constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
 | 
				
			||||||
 | 
					        : base_type{std::forward<Args>(std::get<Index>(args))...} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr reference get() noexcept {
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr const_reference get() const noexcept {
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 * @endcond
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief A compressed pair.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
 | 
				
			||||||
 | 
					 * reduce its final size to a minimum.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tparam First The type of the first element that the pair stores.
 | 
				
			||||||
 | 
					 * @tparam Second The type of the second element that the pair stores.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename First, typename Second>
 | 
				
			||||||
 | 
					class compressed_pair final
 | 
				
			||||||
 | 
					    : internal::compressed_pair_element<First, 0u>,
 | 
				
			||||||
 | 
					      internal::compressed_pair_element<Second, 1u> {
 | 
				
			||||||
 | 
					    using first_base = internal::compressed_pair_element<First, 0u>;
 | 
				
			||||||
 | 
					    using second_base = internal::compressed_pair_element<Second, 1u>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /*! @brief The type of the first element that the pair stores. */
 | 
				
			||||||
 | 
					    using first_type = First;
 | 
				
			||||||
 | 
					    /*! @brief The type of the second element that the pair stores. */
 | 
				
			||||||
 | 
					    using second_type = Second;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Default constructor, conditionally enabled.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * This constructor is only available when the types that the pair stores
 | 
				
			||||||
 | 
					     * are both at least default constructible.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @tparam Dummy Dummy template parameter used for internal purposes.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
 | 
				
			||||||
 | 
					    constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> &&std::is_nothrow_default_constructible_v<second_base>)
 | 
				
			||||||
 | 
					        : first_base{},
 | 
				
			||||||
 | 
					          second_base{} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Copy constructor.
 | 
				
			||||||
 | 
					     * @param other The instance to copy from.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constexpr compressed_pair(const compressed_pair &other) noexcept(std::is_nothrow_copy_constructible_v<first_base> &&std::is_nothrow_copy_constructible_v<second_base>) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Move constructor.
 | 
				
			||||||
 | 
					     * @param other The instance to move from.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constexpr compressed_pair(compressed_pair &&other) noexcept(std::is_nothrow_move_constructible_v<first_base> &&std::is_nothrow_move_constructible_v<second_base>) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a pair from its values.
 | 
				
			||||||
 | 
					     * @tparam Arg Type of value to use to initialize the first element.
 | 
				
			||||||
 | 
					     * @tparam Other Type of value to use to initialize the second element.
 | 
				
			||||||
 | 
					     * @param arg Value to use to initialize the first element.
 | 
				
			||||||
 | 
					     * @param other Value to use to initialize the second element.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Arg, typename Other>
 | 
				
			||||||
 | 
					    constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> &&std::is_nothrow_constructible_v<second_base, Other>)
 | 
				
			||||||
 | 
					        : first_base{std::forward<Arg>(arg)},
 | 
				
			||||||
 | 
					          second_base{std::forward<Other>(other)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a pair by forwarding the arguments to its parts.
 | 
				
			||||||
 | 
					     * @tparam Args Types of arguments to use to initialize the first element.
 | 
				
			||||||
 | 
					     * @tparam Other Types of arguments to use to initialize the second element.
 | 
				
			||||||
 | 
					     * @param args Arguments to use to initialize the first element.
 | 
				
			||||||
 | 
					     * @param other Arguments to use to initialize the second element.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename... Args, typename... Other>
 | 
				
			||||||
 | 
					    constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> &&std::is_nothrow_constructible_v<second_base, Other...>)
 | 
				
			||||||
 | 
					        : first_base{std::move(args), std::index_sequence_for<Args...>{}},
 | 
				
			||||||
 | 
					          second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Copy assignment operator.
 | 
				
			||||||
 | 
					     * @param other The instance to copy from.
 | 
				
			||||||
 | 
					     * @return This compressed pair object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constexpr compressed_pair &operator=(const compressed_pair &other) noexcept(std::is_nothrow_copy_assignable_v<first_base> &&std::is_nothrow_copy_assignable_v<second_base>) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Move assignment operator.
 | 
				
			||||||
 | 
					     * @param other The instance to move from.
 | 
				
			||||||
 | 
					     * @return This compressed pair object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constexpr compressed_pair &operator=(compressed_pair &&other) noexcept(std::is_nothrow_move_assignable_v<first_base> &&std::is_nothrow_move_assignable_v<second_base>) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the first element that a pair stores.
 | 
				
			||||||
 | 
					     * @return The first element that a pair stores.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr first_type &first() noexcept {
 | 
				
			||||||
 | 
					        return static_cast<first_base &>(*this).get();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc first */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr const first_type &first() const noexcept {
 | 
				
			||||||
 | 
					        return static_cast<const first_base &>(*this).get();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the second element that a pair stores.
 | 
				
			||||||
 | 
					     * @return The second element that a pair stores.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr second_type &second() noexcept {
 | 
				
			||||||
 | 
					        return static_cast<second_base &>(*this).get();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc second */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr const second_type &second() const noexcept {
 | 
				
			||||||
 | 
					        return static_cast<const second_base &>(*this).get();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Swaps two compressed pair objects.
 | 
				
			||||||
 | 
					     * @param other The compressed pair to swap with.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constexpr void swap(compressed_pair &other) noexcept(std::is_nothrow_swappable_v<first_type> &&std::is_nothrow_swappable_v<second_type>) {
 | 
				
			||||||
 | 
					        using std::swap;
 | 
				
			||||||
 | 
					        swap(first(), other.first());
 | 
				
			||||||
 | 
					        swap(second(), other.second());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Extracts an element from the compressed pair.
 | 
				
			||||||
 | 
					     * @tparam Index An integer value that is either 0 or 1.
 | 
				
			||||||
 | 
					     * @return Returns a reference to the first element if `Index` is 0 and a
 | 
				
			||||||
 | 
					     * reference to the second element if `Index` is 1.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<std::size_t Index>
 | 
				
			||||||
 | 
					    constexpr decltype(auto) get() noexcept {
 | 
				
			||||||
 | 
					        if constexpr(Index == 0u) {
 | 
				
			||||||
 | 
					            return first();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            static_assert(Index == 1u, "Index out of bounds");
 | 
				
			||||||
 | 
					            return second();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc get */
 | 
				
			||||||
 | 
					    template<std::size_t Index>
 | 
				
			||||||
 | 
					    constexpr decltype(auto) get() const noexcept {
 | 
				
			||||||
 | 
					        if constexpr(Index == 0u) {
 | 
				
			||||||
 | 
					            return first();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            static_assert(Index == 1u, "Index out of bounds");
 | 
				
			||||||
 | 
					            return second();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Deduction guide.
 | 
				
			||||||
 | 
					 * @tparam Type Type of value to use to initialize the first element.
 | 
				
			||||||
 | 
					 * @tparam Other Type of value to use to initialize the second element.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename Other>
 | 
				
			||||||
 | 
					compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Swaps two compressed pair objects.
 | 
				
			||||||
 | 
					 * @tparam First The type of the first element that the pairs store.
 | 
				
			||||||
 | 
					 * @tparam Second The type of the second element that the pairs store.
 | 
				
			||||||
 | 
					 * @param lhs A valid compressed pair object.
 | 
				
			||||||
 | 
					 * @param rhs A valid compressed pair object.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename First, typename Second>
 | 
				
			||||||
 | 
					inline constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) {
 | 
				
			||||||
 | 
					    lhs.swap(rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// disable structured binding support for clang 6, it messes when specializing tuple_size
 | 
				
			||||||
 | 
					#if !defined __clang_major__ || __clang_major__ > 6
 | 
				
			||||||
 | 
					namespace std {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief `std::tuple_size` specialization for `compressed_pair`s.
 | 
				
			||||||
 | 
					 * @tparam First The type of the first element that the pair stores.
 | 
				
			||||||
 | 
					 * @tparam Second The type of the second element that the pair stores.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename First, typename Second>
 | 
				
			||||||
 | 
					struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief `std::tuple_element` specialization for `compressed_pair`s.
 | 
				
			||||||
 | 
					 * @tparam Index The index of the type to return.
 | 
				
			||||||
 | 
					 * @tparam First The type of the first element that the pair stores.
 | 
				
			||||||
 | 
					 * @tparam Second The type of the second element that the pair stores.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<size_t Index, typename First, typename Second>
 | 
				
			||||||
 | 
					struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
 | 
				
			||||||
 | 
					    static_assert(Index < 2u, "Index out of bounds");
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace std
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										97
									
								
								external/entt/entt/src/entt/core/enum.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								external/entt/entt/src/entt/core/enum.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_ENUM_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_ENUM_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Enable bitmask support for enum classes.
 | 
				
			||||||
 | 
					 * @tparam Type The enum type for which to enable bitmask support.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename = void>
 | 
				
			||||||
 | 
					struct enum_as_bitmask: std::false_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc enum_as_bitmask */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct enum_as_bitmask<Type, std::void_t<decltype(Type::_entt_enum_as_bitmask)>>: std::is_enum<Type> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam Type The enum class type for which to enable bitmask support.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					inline constexpr bool enum_as_bitmask_v = enum_as_bitmask<Type>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Operator available for enums for which bitmask support is enabled.
 | 
				
			||||||
 | 
					 * @tparam Type Enum class type.
 | 
				
			||||||
 | 
					 * @param lhs The first value to use.
 | 
				
			||||||
 | 
					 * @param rhs The second value to use.
 | 
				
			||||||
 | 
					 * @return The result of invoking the operator on the underlying types of the
 | 
				
			||||||
 | 
					 * two values provided.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
 | 
				
			||||||
 | 
					operator|(const Type lhs, const Type rhs) noexcept {
 | 
				
			||||||
 | 
					    return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) | static_cast<std::underlying_type_t<Type>>(rhs));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc operator| */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
 | 
				
			||||||
 | 
					operator&(const Type lhs, const Type rhs) noexcept {
 | 
				
			||||||
 | 
					    return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) & static_cast<std::underlying_type_t<Type>>(rhs));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc operator| */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
 | 
				
			||||||
 | 
					operator^(const Type lhs, const Type rhs) noexcept {
 | 
				
			||||||
 | 
					    return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) ^ static_cast<std::underlying_type_t<Type>>(rhs));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Operator available for enums for which bitmask support is enabled.
 | 
				
			||||||
 | 
					 * @tparam Type Enum class type.
 | 
				
			||||||
 | 
					 * @param value The value to use.
 | 
				
			||||||
 | 
					 * @return The result of invoking the operator on the underlying types of the
 | 
				
			||||||
 | 
					 * value provided.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
 | 
				
			||||||
 | 
					operator~(const Type value) noexcept {
 | 
				
			||||||
 | 
					    return static_cast<Type>(~static_cast<std::underlying_type_t<Type>>(value));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc operator~ */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, bool>
 | 
				
			||||||
 | 
					operator!(const Type value) noexcept {
 | 
				
			||||||
 | 
					    return !static_cast<std::underlying_type_t<Type>>(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc operator| */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &>
 | 
				
			||||||
 | 
					operator|=(Type &lhs, const Type rhs) noexcept {
 | 
				
			||||||
 | 
					    return (lhs = (lhs | rhs));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc operator| */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &>
 | 
				
			||||||
 | 
					operator&=(Type &lhs, const Type rhs) noexcept {
 | 
				
			||||||
 | 
					    return (lhs = (lhs & rhs));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc operator| */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &>
 | 
				
			||||||
 | 
					operator^=(Type &lhs, const Type rhs) noexcept {
 | 
				
			||||||
 | 
					    return (lhs = (lhs ^ rhs));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										32
									
								
								external/entt/entt/src/entt/core/family.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								external/entt/entt/src/entt/core/family.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_FAMILY_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_FAMILY_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../config/config.h"
 | 
				
			||||||
 | 
					#include "fwd.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Dynamic identifier generator.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Utility class template that can be used to assign unique identifiers to types
 | 
				
			||||||
 | 
					 * at runtime. Use different specializations to create separate sets of
 | 
				
			||||||
 | 
					 * identifiers.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename...>
 | 
				
			||||||
 | 
					class family {
 | 
				
			||||||
 | 
					    inline static ENTT_MAYBE_ATOMIC(id_type) identifier{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /*! @brief Unsigned integer type. */
 | 
				
			||||||
 | 
					    using value_type = id_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Statically generated unique identifier for the given type. */
 | 
				
			||||||
 | 
					    template<typename... Type>
 | 
				
			||||||
 | 
					    // at the time I'm writing, clang crashes during compilation if auto is used instead of family_type
 | 
				
			||||||
 | 
					    inline static const value_type value = identifier++;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										20
									
								
								external/entt/entt/src/entt/core/fwd.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								external/entt/entt/src/entt/core/fwd.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_FWD_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_FWD_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					#include "../config/config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
 | 
				
			||||||
 | 
					class basic_any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Alias declaration for type identifiers. */
 | 
				
			||||||
 | 
					using id_type = ENTT_ID_TYPE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Alias declaration for the most common use case. */
 | 
				
			||||||
 | 
					using any = basic_any<>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										334
									
								
								external/entt/entt/src/entt/core/hashed_string.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										334
									
								
								external/entt/entt/src/entt/core/hashed_string.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,334 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_HASHED_STRING_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_HASHED_STRING_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					#include "fwd.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename>
 | 
				
			||||||
 | 
					struct fnv1a_traits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct fnv1a_traits<std::uint32_t> {
 | 
				
			||||||
 | 
					    using type = std::uint32_t;
 | 
				
			||||||
 | 
					    static constexpr std::uint32_t offset = 2166136261;
 | 
				
			||||||
 | 
					    static constexpr std::uint32_t prime = 16777619;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct fnv1a_traits<std::uint64_t> {
 | 
				
			||||||
 | 
					    using type = std::uint64_t;
 | 
				
			||||||
 | 
					    static constexpr std::uint64_t offset = 14695981039346656037ull;
 | 
				
			||||||
 | 
					    static constexpr std::uint64_t prime = 1099511628211ull;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Char>
 | 
				
			||||||
 | 
					struct basic_hashed_string {
 | 
				
			||||||
 | 
					    using value_type = Char;
 | 
				
			||||||
 | 
					    using size_type = std::size_t;
 | 
				
			||||||
 | 
					    using hash_type = id_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const value_type *repr;
 | 
				
			||||||
 | 
					    size_type length;
 | 
				
			||||||
 | 
					    hash_type hash;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 * @endcond
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Zero overhead unique identifier.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * A hashed string is a compile-time tool that allows users to use
 | 
				
			||||||
 | 
					 * human-readable identifiers in the codebase while using their numeric
 | 
				
			||||||
 | 
					 * counterparts at runtime.<br/>
 | 
				
			||||||
 | 
					 * Because of that, a hashed string can also be used in constant expressions if
 | 
				
			||||||
 | 
					 * required.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @warning
 | 
				
			||||||
 | 
					 * This class doesn't take ownership of user-supplied strings nor does it make a
 | 
				
			||||||
 | 
					 * copy of them.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tparam Char Character type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Char>
 | 
				
			||||||
 | 
					class basic_hashed_string: internal::basic_hashed_string<Char> {
 | 
				
			||||||
 | 
					    using base_type = internal::basic_hashed_string<Char>;
 | 
				
			||||||
 | 
					    using traits_type = internal::fnv1a_traits<id_type>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct const_wrapper {
 | 
				
			||||||
 | 
					        // non-explicit constructor on purpose
 | 
				
			||||||
 | 
					        constexpr const_wrapper(const Char *str) noexcept
 | 
				
			||||||
 | 
					            : repr{str} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const Char *repr;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Fowler–Noll–Vo hash function v. 1a - the good
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr auto helper(const Char *str) noexcept {
 | 
				
			||||||
 | 
					        base_type base{str, 0u, traits_type::offset};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for(; str[base.length]; ++base.length) {
 | 
				
			||||||
 | 
					            base.hash = (base.hash ^ static_cast<traits_type::type>(str[base.length])) * traits_type::prime;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return base;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Fowler–Noll–Vo hash function v. 1a - the good
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr auto helper(const Char *str, const std::size_t len) noexcept {
 | 
				
			||||||
 | 
					        base_type base{str, len, traits_type::offset};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for(size_type pos{}; pos < len; ++pos) {
 | 
				
			||||||
 | 
					            base.hash = (base.hash ^ static_cast<traits_type::type>(str[pos])) * traits_type::prime;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return base;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /*! @brief Character type. */
 | 
				
			||||||
 | 
					    using value_type = typename base_type::value_type;
 | 
				
			||||||
 | 
					    /*! @brief Unsigned integer type. */
 | 
				
			||||||
 | 
					    using size_type = typename base_type::size_type;
 | 
				
			||||||
 | 
					    /*! @brief Unsigned integer type. */
 | 
				
			||||||
 | 
					    using hash_type = typename base_type::hash_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns directly the numeric representation of a string view.
 | 
				
			||||||
 | 
					     * @param str Human-readable identifier.
 | 
				
			||||||
 | 
					     * @param len Length of the string to hash.
 | 
				
			||||||
 | 
					     * @return The numeric representation of the string.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr hash_type value(const value_type *str, const size_type len) noexcept {
 | 
				
			||||||
 | 
					        return basic_hashed_string{str, len};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns directly the numeric representation of a string.
 | 
				
			||||||
 | 
					     * @tparam N Number of characters of the identifier.
 | 
				
			||||||
 | 
					     * @param str Human-readable identifier.
 | 
				
			||||||
 | 
					     * @return The numeric representation of the string.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<std::size_t N>
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) noexcept {
 | 
				
			||||||
 | 
					        return basic_hashed_string{str};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns directly the numeric representation of a string.
 | 
				
			||||||
 | 
					     * @param wrapper Helps achieving the purpose by relying on overloading.
 | 
				
			||||||
 | 
					     * @return The numeric representation of the string.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr hash_type value(const_wrapper wrapper) noexcept {
 | 
				
			||||||
 | 
					        return basic_hashed_string{wrapper};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Constructs an empty hashed string. */
 | 
				
			||||||
 | 
					    constexpr basic_hashed_string() noexcept
 | 
				
			||||||
 | 
					        : base_type{} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a hashed string from a string view.
 | 
				
			||||||
 | 
					     * @param str Human-readable identifier.
 | 
				
			||||||
 | 
					     * @param len Length of the string to hash.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constexpr basic_hashed_string(const value_type *str, const size_type len) noexcept
 | 
				
			||||||
 | 
					        : base_type{helper(str, len)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a hashed string from an array of const characters.
 | 
				
			||||||
 | 
					     * @tparam N Number of characters of the identifier.
 | 
				
			||||||
 | 
					     * @param str Human-readable identifier.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<std::size_t N>
 | 
				
			||||||
 | 
					    constexpr basic_hashed_string(const value_type (&str)[N]) noexcept
 | 
				
			||||||
 | 
					        : base_type{helper(str)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Explicit constructor on purpose to avoid constructing a hashed
 | 
				
			||||||
 | 
					     * string directly from a `const value_type *`.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @warning
 | 
				
			||||||
 | 
					     * The lifetime of the string is not extended nor is it copied.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param wrapper Helps achieving the purpose by relying on overloading.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    explicit constexpr basic_hashed_string(const_wrapper wrapper) noexcept
 | 
				
			||||||
 | 
					        : base_type{helper(wrapper.repr)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the size a hashed string.
 | 
				
			||||||
 | 
					     * @return The size of the hashed string.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr size_type size() const noexcept {
 | 
				
			||||||
 | 
					        return base_type::length;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the human-readable representation of a hashed string.
 | 
				
			||||||
 | 
					     * @return The string used to initialize the hashed string.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr const value_type *data() const noexcept {
 | 
				
			||||||
 | 
					        return base_type::repr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the numeric representation of a hashed string.
 | 
				
			||||||
 | 
					     * @return The numeric representation of the hashed string.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr hash_type value() const noexcept {
 | 
				
			||||||
 | 
					        return base_type::hash;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc data */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr operator const value_type *() const noexcept {
 | 
				
			||||||
 | 
					        return data();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the numeric representation of a hashed string.
 | 
				
			||||||
 | 
					     * @return The numeric representation of the hashed string.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr operator hash_type() const noexcept {
 | 
				
			||||||
 | 
					        return value();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Deduction guide.
 | 
				
			||||||
 | 
					 * @tparam Char Character type.
 | 
				
			||||||
 | 
					 * @param str Human-readable identifier.
 | 
				
			||||||
 | 
					 * @param len Length of the string to hash.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Char>
 | 
				
			||||||
 | 
					basic_hashed_string(const Char *str, const std::size_t len) -> basic_hashed_string<Char>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Deduction guide.
 | 
				
			||||||
 | 
					 * @tparam Char Character type.
 | 
				
			||||||
 | 
					 * @tparam N Number of characters of the identifier.
 | 
				
			||||||
 | 
					 * @param str Human-readable identifier.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Char, std::size_t N>
 | 
				
			||||||
 | 
					basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string<Char>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares two hashed strings.
 | 
				
			||||||
 | 
					 * @tparam Char Character type.
 | 
				
			||||||
 | 
					 * @param lhs A valid hashed string.
 | 
				
			||||||
 | 
					 * @param rhs A valid hashed string.
 | 
				
			||||||
 | 
					 * @return True if the two hashed strings are identical, false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Char>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator==(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return lhs.value() == rhs.value();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares two hashed strings.
 | 
				
			||||||
 | 
					 * @tparam Char Character type.
 | 
				
			||||||
 | 
					 * @param lhs A valid hashed string.
 | 
				
			||||||
 | 
					 * @param rhs A valid hashed string.
 | 
				
			||||||
 | 
					 * @return True if the two hashed strings differ, false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Char>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return !(lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares two hashed strings.
 | 
				
			||||||
 | 
					 * @tparam Char Character type.
 | 
				
			||||||
 | 
					 * @param lhs A valid hashed string.
 | 
				
			||||||
 | 
					 * @param rhs A valid hashed string.
 | 
				
			||||||
 | 
					 * @return True if the first element is less than the second, false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Char>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator<(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return lhs.value() < rhs.value();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares two hashed strings.
 | 
				
			||||||
 | 
					 * @tparam Char Character type.
 | 
				
			||||||
 | 
					 * @param lhs A valid hashed string.
 | 
				
			||||||
 | 
					 * @param rhs A valid hashed string.
 | 
				
			||||||
 | 
					 * @return True if the first element is less than or equal to the second, false
 | 
				
			||||||
 | 
					 * otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Char>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator<=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return !(rhs < lhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares two hashed strings.
 | 
				
			||||||
 | 
					 * @tparam Char Character type.
 | 
				
			||||||
 | 
					 * @param lhs A valid hashed string.
 | 
				
			||||||
 | 
					 * @param rhs A valid hashed string.
 | 
				
			||||||
 | 
					 * @return True if the first element is greater than the second, false
 | 
				
			||||||
 | 
					 * otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Char>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator>(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return rhs < lhs;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares two hashed strings.
 | 
				
			||||||
 | 
					 * @tparam Char Character type.
 | 
				
			||||||
 | 
					 * @param lhs A valid hashed string.
 | 
				
			||||||
 | 
					 * @param rhs A valid hashed string.
 | 
				
			||||||
 | 
					 * @return True if the first element is greater than or equal to the second,
 | 
				
			||||||
 | 
					 * false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Char>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator>=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return !(lhs < rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Aliases for common character types. */
 | 
				
			||||||
 | 
					using hashed_string = basic_hashed_string<char>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Aliases for common character types. */
 | 
				
			||||||
 | 
					using hashed_wstring = basic_hashed_string<wchar_t>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline namespace literals {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief User defined literal for hashed strings.
 | 
				
			||||||
 | 
					 * @param str The literal without its suffix.
 | 
				
			||||||
 | 
					 * @return A properly initialized hashed string.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr hashed_string operator"" _hs(const char *str, std::size_t) noexcept {
 | 
				
			||||||
 | 
					    return hashed_string{str};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief User defined literal for hashed wstrings.
 | 
				
			||||||
 | 
					 * @param str The literal without its suffix.
 | 
				
			||||||
 | 
					 * @return A properly initialized hashed wstring.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) noexcept {
 | 
				
			||||||
 | 
					    return hashed_wstring{str};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										35
									
								
								external/entt/entt/src/entt/core/ident.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								external/entt/entt/src/entt/core/ident.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_IDENT_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_IDENT_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include "fwd.hpp"
 | 
				
			||||||
 | 
					#include "type_traits.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Type integral identifiers.
 | 
				
			||||||
 | 
					 * @tparam Type List of types for which to generate identifiers.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type>
 | 
				
			||||||
 | 
					class ident {
 | 
				
			||||||
 | 
					    template<typename Curr, std::size_t... Index>
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr id_type get(std::index_sequence<Index...>) noexcept {
 | 
				
			||||||
 | 
					        static_assert((std::is_same_v<Curr, Type> || ...), "Invalid type");
 | 
				
			||||||
 | 
					        return (0 + ... + (std::is_same_v<Curr, type_list_element_t<Index, type_list<std::decay_t<Type>...>>> ? id_type{Index} : id_type{}));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /*! @brief Unsigned integer type. */
 | 
				
			||||||
 | 
					    using value_type = id_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Statically generated unique identifier for the given type. */
 | 
				
			||||||
 | 
					    template<typename Curr>
 | 
				
			||||||
 | 
					    static constexpr value_type value = get<std::decay_t<Curr>>(std::index_sequence_for<Type...>{});
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										197
									
								
								external/entt/entt/src/entt/core/iterator.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								external/entt/entt/src/entt/core/iterator.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,197 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_ITERATOR_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_ITERATOR_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iterator>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type to use as pointer with input iterators.
 | 
				
			||||||
 | 
					 * @tparam Type of wrapped value.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct input_iterator_pointer final {
 | 
				
			||||||
 | 
					    /*! @brief Value type. */
 | 
				
			||||||
 | 
					    using value_type = Type;
 | 
				
			||||||
 | 
					    /*! @brief Pointer type. */
 | 
				
			||||||
 | 
					    using pointer = Type *;
 | 
				
			||||||
 | 
					    /*! @brief Reference type. */
 | 
				
			||||||
 | 
					    using reference = Type &;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a proxy object by move.
 | 
				
			||||||
 | 
					     * @param val Value to use to initialize the proxy object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
 | 
				
			||||||
 | 
					        : value{std::move(val)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Access operator for accessing wrapped values.
 | 
				
			||||||
 | 
					     * @return A pointer to the wrapped value.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr pointer operator->() noexcept {
 | 
				
			||||||
 | 
					        return std::addressof(value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Dereference operator for accessing wrapped values.
 | 
				
			||||||
 | 
					     * @return A reference to the wrapped value.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr reference operator*() noexcept {
 | 
				
			||||||
 | 
					        return value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    Type value;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Plain iota iterator (waiting for C++20).
 | 
				
			||||||
 | 
					 * @tparam Type Value type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					class iota_iterator final {
 | 
				
			||||||
 | 
					    static_assert(std::is_integral_v<Type>, "Not an integral type");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /*! @brief Value type, likely an integral one. */
 | 
				
			||||||
 | 
					    using value_type = Type;
 | 
				
			||||||
 | 
					    /*! @brief Invalid pointer type. */
 | 
				
			||||||
 | 
					    using pointer = void;
 | 
				
			||||||
 | 
					    /*! @brief Non-reference type, same as value type. */
 | 
				
			||||||
 | 
					    using reference = value_type;
 | 
				
			||||||
 | 
					    /*! @brief Difference type. */
 | 
				
			||||||
 | 
					    using difference_type = std::ptrdiff_t;
 | 
				
			||||||
 | 
					    /*! @brief Iterator category. */
 | 
				
			||||||
 | 
					    using iterator_category = std::input_iterator_tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Default constructor. */
 | 
				
			||||||
 | 
					    constexpr iota_iterator() noexcept
 | 
				
			||||||
 | 
					        : current{} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs an iota iterator from a given value.
 | 
				
			||||||
 | 
					     * @param init The initial value assigned to the iota iterator.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constexpr iota_iterator(const value_type init) noexcept
 | 
				
			||||||
 | 
					        : current{init} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Pre-increment operator.
 | 
				
			||||||
 | 
					     * @return This iota iterator.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constexpr iota_iterator &operator++() noexcept {
 | 
				
			||||||
 | 
					        return ++current, *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Post-increment operator.
 | 
				
			||||||
 | 
					     * @return This iota iterator.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constexpr iota_iterator operator++(int) noexcept {
 | 
				
			||||||
 | 
					        iota_iterator orig = *this;
 | 
				
			||||||
 | 
					        return ++(*this), orig;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Dereference operator.
 | 
				
			||||||
 | 
					     * @return The underlying value.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr reference operator*() const noexcept {
 | 
				
			||||||
 | 
					        return current;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    value_type current;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Comparison operator.
 | 
				
			||||||
 | 
					 * @tparam Type Value type of the iota iterator.
 | 
				
			||||||
 | 
					 * @param lhs A properly initialized iota iterator.
 | 
				
			||||||
 | 
					 * @param rhs A properly initialized iota iterator.
 | 
				
			||||||
 | 
					 * @return True if the two iterators are identical, false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return *lhs == *rhs;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Comparison operator.
 | 
				
			||||||
 | 
					 * @tparam Type Value type of the iota iterator.
 | 
				
			||||||
 | 
					 * @param lhs A properly initialized iota iterator.
 | 
				
			||||||
 | 
					 * @param rhs A properly initialized iota iterator.
 | 
				
			||||||
 | 
					 * @return True if the two iterators differ, false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return !(lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Utility class to create an iterable object from a pair of iterators.
 | 
				
			||||||
 | 
					 * @tparam It Type of iterator.
 | 
				
			||||||
 | 
					 * @tparam Sentinel Type of sentinel.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename It, typename Sentinel = It>
 | 
				
			||||||
 | 
					struct iterable_adaptor final {
 | 
				
			||||||
 | 
					    /*! @brief Value type. */
 | 
				
			||||||
 | 
					    using value_type = typename std::iterator_traits<It>::value_type;
 | 
				
			||||||
 | 
					    /*! @brief Iterator type. */
 | 
				
			||||||
 | 
					    using iterator = It;
 | 
				
			||||||
 | 
					    /*! @brief Sentinel type. */
 | 
				
			||||||
 | 
					    using sentinel = Sentinel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Default constructor. */
 | 
				
			||||||
 | 
					    constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> &&std::is_nothrow_default_constructible_v<sentinel>)
 | 
				
			||||||
 | 
					        : first{},
 | 
				
			||||||
 | 
					          last{} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Creates an iterable object from a pair of iterators.
 | 
				
			||||||
 | 
					     * @param from Begin iterator.
 | 
				
			||||||
 | 
					     * @param to End iterator.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> &&std::is_nothrow_move_constructible_v<sentinel>)
 | 
				
			||||||
 | 
					        : first{std::move(from)},
 | 
				
			||||||
 | 
					          last{std::move(to)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an iterator to the beginning.
 | 
				
			||||||
 | 
					     * @return An iterator to the first element of the range.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr iterator begin() const noexcept {
 | 
				
			||||||
 | 
					        return first;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an iterator to the end.
 | 
				
			||||||
 | 
					     * @return An iterator to the element following the last element of the
 | 
				
			||||||
 | 
					     * range.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr sentinel end() const noexcept {
 | 
				
			||||||
 | 
					        return last;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc begin */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr iterator cbegin() const noexcept {
 | 
				
			||||||
 | 
					        return begin();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc end */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr sentinel cend() const noexcept {
 | 
				
			||||||
 | 
					        return end();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    It first;
 | 
				
			||||||
 | 
					    Sentinel last;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										289
									
								
								external/entt/entt/src/entt/core/memory.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								external/entt/entt/src/entt/core/memory.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,289 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_MEMORY_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_MEMORY_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					#include <limits>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include "../config/config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Checks whether a value is a power of two or not.
 | 
				
			||||||
 | 
					 * @param value A value that may or may not be a power of two.
 | 
				
			||||||
 | 
					 * @return True if the value is a power of two, false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					[[nodiscard]] inline constexpr bool is_power_of_two(const std::size_t value) noexcept {
 | 
				
			||||||
 | 
					    return value && ((value & (value - 1)) == 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Computes the smallest power of two greater than or equal to a value.
 | 
				
			||||||
 | 
					 * @param value The value to use.
 | 
				
			||||||
 | 
					 * @return The smallest power of two greater than or equal to the given value.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					[[nodiscard]] inline constexpr std::size_t next_power_of_two(const std::size_t value) noexcept {
 | 
				
			||||||
 | 
					    ENTT_ASSERT_CONSTEXPR(value < (std::size_t{1u} << (std::numeric_limits<std::size_t>::digits - 1)), "Numeric limits exceeded");
 | 
				
			||||||
 | 
					    std::size_t curr = value - (value != 0u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for(int next = 1; next < std::numeric_limits<std::size_t>::digits; next = next * 2) {
 | 
				
			||||||
 | 
					        curr |= curr >> next;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ++curr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Fast module utility function (powers of two only).
 | 
				
			||||||
 | 
					 * @param value A value for which to calculate the modulus.
 | 
				
			||||||
 | 
					 * @param mod _Modulus_, it must be a power of two.
 | 
				
			||||||
 | 
					 * @return The common remainder.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					[[nodiscard]] inline constexpr std::size_t fast_mod(const std::size_t value, const std::size_t mod) noexcept {
 | 
				
			||||||
 | 
					    ENTT_ASSERT_CONSTEXPR(is_power_of_two(mod), "Value must be a power of two");
 | 
				
			||||||
 | 
					    return value & (mod - 1u);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
 | 
				
			||||||
 | 
					 * @tparam Type Pointer type.
 | 
				
			||||||
 | 
					 * @param ptr Fancy or raw pointer.
 | 
				
			||||||
 | 
					 * @return A raw pointer that represents the address of the original pointer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr auto to_address(Type &&ptr) noexcept {
 | 
				
			||||||
 | 
					    if constexpr(std::is_pointer_v<std::decay_t<Type>>) {
 | 
				
			||||||
 | 
					        return ptr;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return to_address(std::forward<Type>(ptr).operator->());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Utility function to design allocation-aware containers.
 | 
				
			||||||
 | 
					 * @tparam Allocator Type of allocator.
 | 
				
			||||||
 | 
					 * @param lhs A valid allocator.
 | 
				
			||||||
 | 
					 * @param rhs Another valid allocator.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Allocator>
 | 
				
			||||||
 | 
					constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
 | 
				
			||||||
 | 
					    if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
 | 
				
			||||||
 | 
					        lhs = rhs;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Utility function to design allocation-aware containers.
 | 
				
			||||||
 | 
					 * @tparam Allocator Type of allocator.
 | 
				
			||||||
 | 
					 * @param lhs A valid allocator.
 | 
				
			||||||
 | 
					 * @param rhs Another valid allocator.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Allocator>
 | 
				
			||||||
 | 
					constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
 | 
				
			||||||
 | 
					    if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
 | 
				
			||||||
 | 
					        lhs = std::move(rhs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Utility function to design allocation-aware containers.
 | 
				
			||||||
 | 
					 * @tparam Allocator Type of allocator.
 | 
				
			||||||
 | 
					 * @param lhs A valid allocator.
 | 
				
			||||||
 | 
					 * @param rhs Another valid allocator.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Allocator>
 | 
				
			||||||
 | 
					constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
 | 
				
			||||||
 | 
					    if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
 | 
				
			||||||
 | 
					        using std::swap;
 | 
				
			||||||
 | 
					        swap(lhs, rhs);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        ENTT_ASSERT_CONSTEXPR(lhs == rhs, "Cannot swap the containers");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
 | 
				
			||||||
 | 
					 * @tparam Allocator Type of allocator used to manage memory and elements.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Allocator>
 | 
				
			||||||
 | 
					struct allocation_deleter: private Allocator {
 | 
				
			||||||
 | 
					    /*! @brief Allocator type. */
 | 
				
			||||||
 | 
					    using allocator_type = Allocator;
 | 
				
			||||||
 | 
					    /*! @brief Pointer type. */
 | 
				
			||||||
 | 
					    using pointer = typename std::allocator_traits<Allocator>::pointer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Inherited constructors.
 | 
				
			||||||
 | 
					     * @param alloc The allocator to use.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constexpr allocation_deleter(const allocator_type &alloc) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
 | 
				
			||||||
 | 
					        : Allocator{alloc} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Destroys the pointed object and deallocates its memory.
 | 
				
			||||||
 | 
					     * @param ptr A valid pointer to an object of the given type.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constexpr void operator()(pointer ptr) noexcept(std::is_nothrow_destructible_v<typename allocator_type::value_type>) {
 | 
				
			||||||
 | 
					        using alloc_traits = std::allocator_traits<Allocator>;
 | 
				
			||||||
 | 
					        alloc_traits::destroy(*this, to_address(ptr));
 | 
				
			||||||
 | 
					        alloc_traits::deallocate(*this, ptr, 1u);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Allows `std::unique_ptr` to use allocators (waiting for C++20).
 | 
				
			||||||
 | 
					 * @tparam Type Type of object to allocate for and to construct.
 | 
				
			||||||
 | 
					 * @tparam Allocator Type of allocator used to manage memory and elements.
 | 
				
			||||||
 | 
					 * @tparam Args Types of arguments to use to construct the object.
 | 
				
			||||||
 | 
					 * @param allocator The allocator to use.
 | 
				
			||||||
 | 
					 * @param args Parameters to use to construct the object.
 | 
				
			||||||
 | 
					 * @return A properly initialized unique pointer with a custom deleter.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename Allocator, typename... Args>
 | 
				
			||||||
 | 
					ENTT_CONSTEXPR auto allocate_unique(Allocator &allocator, Args &&...args) {
 | 
				
			||||||
 | 
					    static_assert(!std::is_array_v<Type>, "Array types are not supported");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
 | 
				
			||||||
 | 
					    using allocator_type = typename alloc_traits::allocator_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    allocator_type alloc{allocator};
 | 
				
			||||||
 | 
					    auto ptr = alloc_traits::allocate(alloc, 1u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ENTT_TRY {
 | 
				
			||||||
 | 
					        alloc_traits::construct(alloc, to_address(ptr), std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    ENTT_CATCH {
 | 
				
			||||||
 | 
					        alloc_traits::deallocate(alloc, ptr, 1u);
 | 
				
			||||||
 | 
					        ENTT_THROW;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return std::unique_ptr<Type, allocation_deleter<allocator_type>>{ptr, alloc};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct uses_allocator_construction {
 | 
				
			||||||
 | 
					    template<typename Allocator, typename... Params>
 | 
				
			||||||
 | 
					    static constexpr auto args([[maybe_unused]] const Allocator &allocator, Params &&...params) noexcept {
 | 
				
			||||||
 | 
					        if constexpr(!std::uses_allocator_v<Type, Allocator> && std::is_constructible_v<Type, Params...>) {
 | 
				
			||||||
 | 
					            return std::forward_as_tuple(std::forward<Params>(params)...);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            static_assert(std::uses_allocator_v<Type, Allocator>, "Ill-formed request");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if constexpr(std::is_constructible_v<Type, std::allocator_arg_t, const Allocator &, Params...>) {
 | 
				
			||||||
 | 
					                return std::tuple<std::allocator_arg_t, const Allocator &, Params &&...>{std::allocator_arg, allocator, std::forward<Params>(params)...};
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                static_assert(std::is_constructible_v<Type, Params..., const Allocator &>, "Ill-formed request");
 | 
				
			||||||
 | 
					                return std::forward_as_tuple(std::forward<Params>(params)..., allocator);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type, typename Other>
 | 
				
			||||||
 | 
					struct uses_allocator_construction<std::pair<Type, Other>> {
 | 
				
			||||||
 | 
					    using type = std::pair<Type, Other>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Allocator, typename First, typename Second>
 | 
				
			||||||
 | 
					    static constexpr auto args(const Allocator &allocator, std::piecewise_construct_t, First &&first, Second &&second) noexcept {
 | 
				
			||||||
 | 
					        return std::make_tuple(
 | 
				
			||||||
 | 
					            std::piecewise_construct,
 | 
				
			||||||
 | 
					            std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Type>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<First>(first)),
 | 
				
			||||||
 | 
					            std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Other>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<Second>(second)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Allocator>
 | 
				
			||||||
 | 
					    static constexpr auto args(const Allocator &allocator) noexcept {
 | 
				
			||||||
 | 
					        return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::tuple<>{}, std::tuple<>{});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Allocator, typename First, typename Second>
 | 
				
			||||||
 | 
					    static constexpr auto args(const Allocator &allocator, First &&first, Second &&second) noexcept {
 | 
				
			||||||
 | 
					        return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::forward<First>(first)), std::forward_as_tuple(std::forward<Second>(second)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Allocator, typename First, typename Second>
 | 
				
			||||||
 | 
					    static constexpr auto args(const Allocator &allocator, const std::pair<First, Second> &value) noexcept {
 | 
				
			||||||
 | 
					        return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(value.first), std::forward_as_tuple(value.second));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Allocator, typename First, typename Second>
 | 
				
			||||||
 | 
					    static constexpr auto args(const Allocator &allocator, std::pair<First, Second> &&value) noexcept {
 | 
				
			||||||
 | 
					        return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::move(value.first)), std::forward_as_tuple(std::move(value.second)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 * @endcond
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Uses-allocator construction utility (waiting for C++20).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Primarily intended for internal use. Prepares the argument list needed to
 | 
				
			||||||
 | 
					 * create an object of a given type by means of uses-allocator construction.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tparam Type Type to return arguments for.
 | 
				
			||||||
 | 
					 * @tparam Allocator Type of allocator used to manage memory and elements.
 | 
				
			||||||
 | 
					 * @tparam Args Types of arguments to use to construct the object.
 | 
				
			||||||
 | 
					 * @param allocator The allocator to use.
 | 
				
			||||||
 | 
					 * @param args Parameters to use to construct the object.
 | 
				
			||||||
 | 
					 * @return The arguments needed to create an object of the given type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename Allocator, typename... Args>
 | 
				
			||||||
 | 
					constexpr auto uses_allocator_construction_args(const Allocator &allocator, Args &&...args) noexcept {
 | 
				
			||||||
 | 
					    return internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Uses-allocator construction utility (waiting for C++20).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Primarily intended for internal use. Creates an object of a given type by
 | 
				
			||||||
 | 
					 * means of uses-allocator construction.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tparam Type Type of object to create.
 | 
				
			||||||
 | 
					 * @tparam Allocator Type of allocator used to manage memory and elements.
 | 
				
			||||||
 | 
					 * @tparam Args Types of arguments to use to construct the object.
 | 
				
			||||||
 | 
					 * @param allocator The allocator to use.
 | 
				
			||||||
 | 
					 * @param args Parameters to use to construct the object.
 | 
				
			||||||
 | 
					 * @return A newly created object of the given type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename Allocator, typename... Args>
 | 
				
			||||||
 | 
					constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args) {
 | 
				
			||||||
 | 
					    return std::make_from_tuple<Type>(internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Uses-allocator construction utility (waiting for C++20).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Primarily intended for internal use. Creates an object of a given type by
 | 
				
			||||||
 | 
					 * means of uses-allocator construction at an uninitialized memory location.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tparam Type Type of object to create.
 | 
				
			||||||
 | 
					 * @tparam Allocator Type of allocator used to manage memory and elements.
 | 
				
			||||||
 | 
					 * @tparam Args Types of arguments to use to construct the object.
 | 
				
			||||||
 | 
					 * @param value Memory location in which to place the object.
 | 
				
			||||||
 | 
					 * @param allocator The allocator to use.
 | 
				
			||||||
 | 
					 * @param args Parameters to use to construct the object.
 | 
				
			||||||
 | 
					 * @return A pointer to the newly created object of the given type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename Allocator, typename... Args>
 | 
				
			||||||
 | 
					constexpr Type *uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args) {
 | 
				
			||||||
 | 
					    return std::apply([value](auto &&...curr) { return new(value) Type(std::forward<decltype(curr)>(curr)...); }, internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										56
									
								
								external/entt/entt/src/entt/core/monostate.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								external/entt/entt/src/entt/core/monostate.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_MONOSTATE_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_MONOSTATE_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../config/config.h"
 | 
				
			||||||
 | 
					#include "fwd.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Minimal implementation of the monostate pattern.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * A minimal, yet complete configuration system built on top of the monostate
 | 
				
			||||||
 | 
					 * pattern. Thread safe by design, it works only with basic types like `int`s or
 | 
				
			||||||
 | 
					 * `bool`s.<br/>
 | 
				
			||||||
 | 
					 * Multiple types and therefore more than one value can be associated with a
 | 
				
			||||||
 | 
					 * single key. Because of this, users must pay attention to use the same type
 | 
				
			||||||
 | 
					 * both during an assignment and when they try to read back their data.
 | 
				
			||||||
 | 
					 * Otherwise, they can incur in unexpected results.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<id_type>
 | 
				
			||||||
 | 
					struct monostate {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Assigns a value of a specific type to a given key.
 | 
				
			||||||
 | 
					     * @tparam Type Type of the value to assign.
 | 
				
			||||||
 | 
					     * @param val User data to assign to the given key.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Type>
 | 
				
			||||||
 | 
					    void operator=(Type val) const noexcept {
 | 
				
			||||||
 | 
					        value<Type> = val;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Gets a value of a specific type for a given key.
 | 
				
			||||||
 | 
					     * @tparam Type Type of the value to get.
 | 
				
			||||||
 | 
					     * @return Stored value, if any.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Type>
 | 
				
			||||||
 | 
					    operator Type() const noexcept {
 | 
				
			||||||
 | 
					        return value<Type>;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    template<typename Type>
 | 
				
			||||||
 | 
					    inline static ENTT_MAYBE_ATOMIC(Type) value{};
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam Value Value used to differentiate between different variables.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<id_type Value>
 | 
				
			||||||
 | 
					inline monostate<Value> monostate_v = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										103
									
								
								external/entt/entt/src/entt/core/tuple.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								external/entt/entt/src/entt/core/tuple.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_TUPLE_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_TUPLE_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename>
 | 
				
			||||||
 | 
					struct is_tuple_impl: std::false_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename... Args>
 | 
				
			||||||
 | 
					struct is_tuple_impl<std::tuple<Args...>>: std::true_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 * @endcond
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides the member constant `value` to true if a given type is a
 | 
				
			||||||
 | 
					 * tuple, false otherwise.
 | 
				
			||||||
 | 
					 * @tparam Type The type to test.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct is_tuple: internal::is_tuple_impl<std::remove_cv_t<Type>> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam Type The type to test.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					inline constexpr bool is_tuple_v = is_tuple<Type>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Utility function to unwrap tuples of a single element.
 | 
				
			||||||
 | 
					 * @tparam Type Tuple type of any sizes.
 | 
				
			||||||
 | 
					 * @param value A tuple object of the given type.
 | 
				
			||||||
 | 
					 * @return The tuple itself if it contains more than one element, the first
 | 
				
			||||||
 | 
					 * element otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					constexpr decltype(auto) unwrap_tuple(Type &&value) noexcept {
 | 
				
			||||||
 | 
					    if constexpr(std::tuple_size_v<std::remove_reference_t<Type>> == 1u) {
 | 
				
			||||||
 | 
					        return std::get<0>(std::forward<Type>(value));
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return std::forward<Type>(value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Utility class to forward-and-apply tuple objects.
 | 
				
			||||||
 | 
					 * @tparam Func Type of underlying invocable object.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Func>
 | 
				
			||||||
 | 
					struct forward_apply: private Func {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a forward-and-apply object.
 | 
				
			||||||
 | 
					     * @tparam Args Types of arguments to use to construct the new instance.
 | 
				
			||||||
 | 
					     * @param args Parameters to use to construct the instance.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename... Args>
 | 
				
			||||||
 | 
					    constexpr forward_apply(Args &&...args) noexcept(std::is_nothrow_constructible_v<Func, Args...>)
 | 
				
			||||||
 | 
					        : Func{std::forward<Args>(args)...} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Forwards and applies the arguments with the underlying function.
 | 
				
			||||||
 | 
					     * @tparam Type Tuple-like type to forward to the underlying function.
 | 
				
			||||||
 | 
					     * @param args Parameters to forward to the underlying function.
 | 
				
			||||||
 | 
					     * @return Return value of the underlying function, if any.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Type>
 | 
				
			||||||
 | 
					    constexpr decltype(auto) operator()(Type &&args) noexcept(noexcept(std::apply(std::declval<Func &>(), args))) {
 | 
				
			||||||
 | 
					        return std::apply(static_cast<Func &>(*this), std::forward<Type>(args));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc operator()() */
 | 
				
			||||||
 | 
					    template<typename Type>
 | 
				
			||||||
 | 
					    constexpr decltype(auto) operator()(Type &&args) const noexcept(noexcept(std::apply(std::declval<const Func &>(), args))) {
 | 
				
			||||||
 | 
					        return std::apply(static_cast<const Func &>(*this), std::forward<Type>(args));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Deduction guide.
 | 
				
			||||||
 | 
					 * @tparam Func Type of underlying invocable object.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Func>
 | 
				
			||||||
 | 
					forward_apply(Func) -> forward_apply<std::remove_reference_t<std::remove_cv_t<Func>>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										274
									
								
								external/entt/entt/src/entt/core/type_info.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								external/entt/entt/src/entt/core/type_info.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,274 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_TYPE_INFO_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_TYPE_INFO_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string_view>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include "../config/config.h"
 | 
				
			||||||
 | 
					#include "../core/attribute.h"
 | 
				
			||||||
 | 
					#include "fwd.hpp"
 | 
				
			||||||
 | 
					#include "hashed_string.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ENTT_API type_index final {
 | 
				
			||||||
 | 
					    [[nodiscard]] static id_type next() noexcept {
 | 
				
			||||||
 | 
					        static ENTT_MAYBE_ATOMIC(id_type) value{};
 | 
				
			||||||
 | 
					        return value++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr auto stripped_type_name() noexcept {
 | 
				
			||||||
 | 
					#if defined ENTT_PRETTY_FUNCTION
 | 
				
			||||||
 | 
					    std::string_view pretty_function{ENTT_PRETTY_FUNCTION};
 | 
				
			||||||
 | 
					    auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
 | 
				
			||||||
 | 
					    auto value = pretty_function.substr(first, pretty_function.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first);
 | 
				
			||||||
 | 
					    return value;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    return std::string_view{""};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
 | 
				
			||||||
 | 
					[[nodiscard]] static constexpr std::string_view type_name(int) noexcept {
 | 
				
			||||||
 | 
					    constexpr auto value = stripped_type_name<Type>();
 | 
				
			||||||
 | 
					    return value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] static std::string_view type_name(char) noexcept {
 | 
				
			||||||
 | 
					    static const auto value = stripped_type_name<Type>();
 | 
				
			||||||
 | 
					    return value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
 | 
				
			||||||
 | 
					[[nodiscard]] static constexpr id_type type_hash(int) noexcept {
 | 
				
			||||||
 | 
					    constexpr auto stripped = stripped_type_name<Type>();
 | 
				
			||||||
 | 
					    constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
 | 
				
			||||||
 | 
					    return value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] static id_type type_hash(char) noexcept {
 | 
				
			||||||
 | 
					    static const auto value = [](const auto stripped) {
 | 
				
			||||||
 | 
					        return hashed_string::value(stripped.data(), stripped.size());
 | 
				
			||||||
 | 
					    }(stripped_type_name<Type>());
 | 
				
			||||||
 | 
					    return value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 * @endcond
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Type sequential identifier.
 | 
				
			||||||
 | 
					 * @tparam Type Type for which to generate a sequential identifier.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename = void>
 | 
				
			||||||
 | 
					struct ENTT_API type_index final {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the sequential identifier of a given type.
 | 
				
			||||||
 | 
					     * @return The sequential identifier of a given type.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] static id_type value() noexcept {
 | 
				
			||||||
 | 
					        static const id_type value = internal::type_index::next();
 | 
				
			||||||
 | 
					        return value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc value */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr operator id_type() const noexcept {
 | 
				
			||||||
 | 
					        return value();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Type hash.
 | 
				
			||||||
 | 
					 * @tparam Type Type for which to generate a hash value.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename = void>
 | 
				
			||||||
 | 
					struct type_hash final {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the numeric representation of a given type.
 | 
				
			||||||
 | 
					     * @return The numeric representation of the given type.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					#if defined ENTT_PRETTY_FUNCTION
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr id_type value() noexcept {
 | 
				
			||||||
 | 
					        return internal::type_hash<Type>(0);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr id_type value() noexcept {
 | 
				
			||||||
 | 
					        return type_index<Type>::value();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc value */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr operator id_type() const noexcept {
 | 
				
			||||||
 | 
					        return value();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Type name.
 | 
				
			||||||
 | 
					 * @tparam Type Type for which to generate a name.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename = void>
 | 
				
			||||||
 | 
					struct type_name final {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the name of a given type.
 | 
				
			||||||
 | 
					     * @return The name of the given type.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr std::string_view value() noexcept {
 | 
				
			||||||
 | 
					        return internal::type_name<Type>(0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc value */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr operator std::string_view() const noexcept {
 | 
				
			||||||
 | 
					        return value();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Implementation specific information about a type. */
 | 
				
			||||||
 | 
					struct type_info final {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a type info object for a given type.
 | 
				
			||||||
 | 
					     * @tparam Type Type for which to construct a type info object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Type>
 | 
				
			||||||
 | 
					    constexpr type_info(std::in_place_type_t<Type>) noexcept
 | 
				
			||||||
 | 
					        : seq{type_index<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
 | 
				
			||||||
 | 
					          identifier{type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
 | 
				
			||||||
 | 
					          alias{type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Type index.
 | 
				
			||||||
 | 
					     * @return Type index.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr id_type index() const noexcept {
 | 
				
			||||||
 | 
					        return seq;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Type hash.
 | 
				
			||||||
 | 
					     * @return Type hash.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr id_type hash() const noexcept {
 | 
				
			||||||
 | 
					        return identifier;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Type name.
 | 
				
			||||||
 | 
					     * @return Type name.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr std::string_view name() const noexcept {
 | 
				
			||||||
 | 
					        return alias;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    id_type seq;
 | 
				
			||||||
 | 
					    id_type identifier;
 | 
				
			||||||
 | 
					    std::string_view alias;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares the contents of two type info objects.
 | 
				
			||||||
 | 
					 * @param lhs A type info object.
 | 
				
			||||||
 | 
					 * @param rhs A type info object.
 | 
				
			||||||
 | 
					 * @return True if the two type info objects are identical, false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					[[nodiscard]] inline constexpr bool operator==(const type_info &lhs, const type_info &rhs) noexcept {
 | 
				
			||||||
 | 
					    return lhs.hash() == rhs.hash();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares the contents of two type info objects.
 | 
				
			||||||
 | 
					 * @param lhs A type info object.
 | 
				
			||||||
 | 
					 * @param rhs A type info object.
 | 
				
			||||||
 | 
					 * @return True if the two type info objects differ, false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					[[nodiscard]] inline constexpr bool operator!=(const type_info &lhs, const type_info &rhs) noexcept {
 | 
				
			||||||
 | 
					    return !(lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares two type info objects.
 | 
				
			||||||
 | 
					 * @param lhs A valid type info object.
 | 
				
			||||||
 | 
					 * @param rhs A valid type info object.
 | 
				
			||||||
 | 
					 * @return True if the first element is less than the second, false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator<(const type_info &lhs, const type_info &rhs) noexcept {
 | 
				
			||||||
 | 
					    return lhs.index() < rhs.index();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares two type info objects.
 | 
				
			||||||
 | 
					 * @param lhs A valid type info object.
 | 
				
			||||||
 | 
					 * @param rhs A valid type info object.
 | 
				
			||||||
 | 
					 * @return True if the first element is less than or equal to the second, false
 | 
				
			||||||
 | 
					 * otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator<=(const type_info &lhs, const type_info &rhs) noexcept {
 | 
				
			||||||
 | 
					    return !(rhs < lhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares two type info objects.
 | 
				
			||||||
 | 
					 * @param lhs A valid type info object.
 | 
				
			||||||
 | 
					 * @param rhs A valid type info object.
 | 
				
			||||||
 | 
					 * @return True if the first element is greater than the second, false
 | 
				
			||||||
 | 
					 * otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator>(const type_info &lhs, const type_info &rhs) noexcept {
 | 
				
			||||||
 | 
					    return rhs < lhs;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares two type info objects.
 | 
				
			||||||
 | 
					 * @param lhs A valid type info object.
 | 
				
			||||||
 | 
					 * @param rhs A valid type info object.
 | 
				
			||||||
 | 
					 * @return True if the first element is greater than or equal to the second,
 | 
				
			||||||
 | 
					 * false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator>=(const type_info &lhs, const type_info &rhs) noexcept {
 | 
				
			||||||
 | 
					    return !(lhs < rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Returns the type info object associated to a given type.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The returned element refers to an object with static storage duration.<br/>
 | 
				
			||||||
 | 
					 * The type doesn't need to be a complete type. If the type is a reference, the
 | 
				
			||||||
 | 
					 * result refers to the referenced type. In all cases, top-level cv-qualifiers
 | 
				
			||||||
 | 
					 * are ignored.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tparam Type Type for which to generate a type info object.
 | 
				
			||||||
 | 
					 * @return A reference to a properly initialized type info object.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] const type_info &type_id() noexcept {
 | 
				
			||||||
 | 
					    if constexpr(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>) {
 | 
				
			||||||
 | 
					        static type_info instance{std::in_place_type<Type>};
 | 
				
			||||||
 | 
					        return instance;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc type_id */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] const type_info &type_id(Type &&) noexcept {
 | 
				
			||||||
 | 
					    return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										920
									
								
								external/entt/entt/src/entt/core/type_traits.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										920
									
								
								external/entt/entt/src/entt/core/type_traits.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,920 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_TYPE_TRAITS_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_TYPE_TRAITS_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					#include <iterator>
 | 
				
			||||||
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include "../config/config.h"
 | 
				
			||||||
 | 
					#include "fwd.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Utility class to disambiguate overloaded functions.
 | 
				
			||||||
 | 
					 * @tparam N Number of choices available.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<std::size_t N>
 | 
				
			||||||
 | 
					struct choice_t
 | 
				
			||||||
 | 
					    // Unfortunately, doxygen cannot parse such a construct.
 | 
				
			||||||
 | 
					    : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
 | 
				
			||||||
 | 
					{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copybrief choice_t */
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct choice_t<0> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Variable template for the choice trick.
 | 
				
			||||||
 | 
					 * @tparam N Number of choices available.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<std::size_t N>
 | 
				
			||||||
 | 
					inline constexpr choice_t<N> choice{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Identity type trait.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Useful to establish non-deduced contexts in template argument deduction
 | 
				
			||||||
 | 
					 * (waiting for C++20) or to provide types through function arguments.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tparam Type A type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct type_identity {
 | 
				
			||||||
 | 
					    /*! @brief Identity type. */
 | 
				
			||||||
 | 
					    using type = Type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam Type A type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					using type_identity_t = typename type_identity<Type>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
 | 
				
			||||||
 | 
					 * @tparam Type The type of which to return the size.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename = void>
 | 
				
			||||||
 | 
					struct size_of: std::integral_constant<std::size_t, 0u> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc size_of */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
 | 
				
			||||||
 | 
					    : std::integral_constant<std::size_t, sizeof(Type)> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam Type The type of which to return the size.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					inline constexpr std::size_t size_of_v = size_of<Type>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Using declaration to be used to _repeat_ the same type a number of
 | 
				
			||||||
 | 
					 * times equal to the size of a given parameter pack.
 | 
				
			||||||
 | 
					 * @tparam Type A type to repeat.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename>
 | 
				
			||||||
 | 
					using unpack_as_type = Type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template to be used to _repeat_ the same value a
 | 
				
			||||||
 | 
					 * number of times equal to the size of a given parameter pack.
 | 
				
			||||||
 | 
					 * @tparam Value A value to repeat.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto Value, typename>
 | 
				
			||||||
 | 
					inline constexpr auto unpack_as_value = Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Wraps a static constant.
 | 
				
			||||||
 | 
					 * @tparam Value A static constant.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto Value>
 | 
				
			||||||
 | 
					using integral_constant = std::integral_constant<decltype(Value), Value>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Alias template to facilitate the creation of named values.
 | 
				
			||||||
 | 
					 * @tparam Value A constant value at least convertible to `id_type`.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<id_type Value>
 | 
				
			||||||
 | 
					using tag = integral_constant<Value>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief A class to use to push around lists of types, nothing more.
 | 
				
			||||||
 | 
					 * @tparam Type Types provided by the type list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type>
 | 
				
			||||||
 | 
					struct type_list {
 | 
				
			||||||
 | 
					    /*! @brief Type list type. */
 | 
				
			||||||
 | 
					    using type = type_list;
 | 
				
			||||||
 | 
					    /*! @brief Compile-time number of elements in the type list. */
 | 
				
			||||||
 | 
					    static constexpr auto size = sizeof...(Type);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Primary template isn't defined on purpose. */
 | 
				
			||||||
 | 
					template<std::size_t, typename>
 | 
				
			||||||
 | 
					struct type_list_element;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides compile-time indexed access to the types of a type list.
 | 
				
			||||||
 | 
					 * @tparam Index Index of the type to return.
 | 
				
			||||||
 | 
					 * @tparam First First type provided by the type list.
 | 
				
			||||||
 | 
					 * @tparam Other Other types provided by the type list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<std::size_t Index, typename First, typename... Other>
 | 
				
			||||||
 | 
					struct type_list_element<Index, type_list<First, Other...>>
 | 
				
			||||||
 | 
					    : type_list_element<Index - 1u, type_list<Other...>> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides compile-time indexed access to the types of a type list.
 | 
				
			||||||
 | 
					 * @tparam First First type provided by the type list.
 | 
				
			||||||
 | 
					 * @tparam Other Other types provided by the type list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename First, typename... Other>
 | 
				
			||||||
 | 
					struct type_list_element<0u, type_list<First, Other...>> {
 | 
				
			||||||
 | 
					    /*! @brief Searched type. */
 | 
				
			||||||
 | 
					    using type = First;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam Index Index of the type to return.
 | 
				
			||||||
 | 
					 * @tparam List Type list to search into.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<std::size_t Index, typename List>
 | 
				
			||||||
 | 
					using type_list_element_t = typename type_list_element<Index, List>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Primary template isn't defined on purpose. */
 | 
				
			||||||
 | 
					template<typename, typename>
 | 
				
			||||||
 | 
					struct type_list_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides compile-time type access to the types of a type list.
 | 
				
			||||||
 | 
					 * @tparam Type Type to look for and for which to return the index.
 | 
				
			||||||
 | 
					 * @tparam First First type provided by the type list.
 | 
				
			||||||
 | 
					 * @tparam Other Other types provided by the type list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename First, typename... Other>
 | 
				
			||||||
 | 
					struct type_list_index<Type, type_list<First, Other...>> {
 | 
				
			||||||
 | 
					    /*! @brief Unsigned integer type. */
 | 
				
			||||||
 | 
					    using value_type = std::size_t;
 | 
				
			||||||
 | 
					    /*! @brief Compile-time position of the given type in the sublist. */
 | 
				
			||||||
 | 
					    static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides compile-time type access to the types of a type list.
 | 
				
			||||||
 | 
					 * @tparam Type Type to look for and for which to return the index.
 | 
				
			||||||
 | 
					 * @tparam Other Other types provided by the type list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename... Other>
 | 
				
			||||||
 | 
					struct type_list_index<Type, type_list<Type, Other...>> {
 | 
				
			||||||
 | 
					    static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
 | 
				
			||||||
 | 
					    /*! @brief Unsigned integer type. */
 | 
				
			||||||
 | 
					    using value_type = std::size_t;
 | 
				
			||||||
 | 
					    /*! @brief Compile-time position of the given type in the sublist. */
 | 
				
			||||||
 | 
					    static constexpr value_type value = 0u;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides compile-time type access to the types of a type list.
 | 
				
			||||||
 | 
					 * @tparam Type Type to look for and for which to return the index.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct type_list_index<Type, type_list<>> {
 | 
				
			||||||
 | 
					    /*! @brief Unsigned integer type. */
 | 
				
			||||||
 | 
					    using value_type = std::size_t;
 | 
				
			||||||
 | 
					    /*! @brief Compile-time position of the given type in the sublist. */
 | 
				
			||||||
 | 
					    static constexpr value_type value = 0u;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam List Type list.
 | 
				
			||||||
 | 
					 * @tparam Type Type to look for and for which to return the index.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename List>
 | 
				
			||||||
 | 
					inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Concatenates multiple type lists.
 | 
				
			||||||
 | 
					 * @tparam Type Types provided by the first type list.
 | 
				
			||||||
 | 
					 * @tparam Other Types provided by the second type list.
 | 
				
			||||||
 | 
					 * @return A type list composed by the types of both the type lists.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type, typename... Other>
 | 
				
			||||||
 | 
					constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
 | 
				
			||||||
 | 
					    return {};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Primary template isn't defined on purpose. */
 | 
				
			||||||
 | 
					template<typename...>
 | 
				
			||||||
 | 
					struct type_list_cat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Concatenates multiple type lists. */
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct type_list_cat<> {
 | 
				
			||||||
 | 
					    /*! @brief A type list composed by the types of all the type lists. */
 | 
				
			||||||
 | 
					    using type = type_list<>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Concatenates multiple type lists.
 | 
				
			||||||
 | 
					 * @tparam Type Types provided by the first type list.
 | 
				
			||||||
 | 
					 * @tparam Other Types provided by the second type list.
 | 
				
			||||||
 | 
					 * @tparam List Other type lists, if any.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type, typename... Other, typename... List>
 | 
				
			||||||
 | 
					struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
 | 
				
			||||||
 | 
					    /*! @brief A type list composed by the types of all the type lists. */
 | 
				
			||||||
 | 
					    using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Concatenates multiple type lists.
 | 
				
			||||||
 | 
					 * @tparam Type Types provided by the type list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type>
 | 
				
			||||||
 | 
					struct type_list_cat<type_list<Type...>> {
 | 
				
			||||||
 | 
					    /*! @brief A type list composed by the types of all the type lists. */
 | 
				
			||||||
 | 
					    using type = type_list<Type...>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam List Type lists to concatenate.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... List>
 | 
				
			||||||
 | 
					using type_list_cat_t = typename type_list_cat<List...>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Primary template isn't defined on purpose. */
 | 
				
			||||||
 | 
					template<typename>
 | 
				
			||||||
 | 
					struct type_list_unique;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Removes duplicates types from a type list.
 | 
				
			||||||
 | 
					 * @tparam Type One of the types provided by the given type list.
 | 
				
			||||||
 | 
					 * @tparam Other The other types provided by the given type list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename... Other>
 | 
				
			||||||
 | 
					struct type_list_unique<type_list<Type, Other...>> {
 | 
				
			||||||
 | 
					    /*! @brief A type list without duplicate types. */
 | 
				
			||||||
 | 
					    using type = std::conditional_t<
 | 
				
			||||||
 | 
					        (std::is_same_v<Type, Other> || ...),
 | 
				
			||||||
 | 
					        typename type_list_unique<type_list<Other...>>::type,
 | 
				
			||||||
 | 
					        type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Removes duplicates types from a type list. */
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct type_list_unique<type_list<>> {
 | 
				
			||||||
 | 
					    /*! @brief A type list without duplicate types. */
 | 
				
			||||||
 | 
					    using type = type_list<>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam Type A type list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					using type_list_unique_t = typename type_list_unique<Type>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides the member constant `value` to true if a type list contains a
 | 
				
			||||||
 | 
					 * given type, false otherwise.
 | 
				
			||||||
 | 
					 * @tparam List Type list.
 | 
				
			||||||
 | 
					 * @tparam Type Type to look for.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename List, typename Type>
 | 
				
			||||||
 | 
					struct type_list_contains;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @copybrief type_list_contains
 | 
				
			||||||
 | 
					 * @tparam Type Types provided by the type list.
 | 
				
			||||||
 | 
					 * @tparam Other Type to look for.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type, typename Other>
 | 
				
			||||||
 | 
					struct type_list_contains<type_list<Type...>, Other>
 | 
				
			||||||
 | 
					    : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam List Type list.
 | 
				
			||||||
 | 
					 * @tparam Type Type to look for.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename List, typename Type>
 | 
				
			||||||
 | 
					inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Primary template isn't defined on purpose. */
 | 
				
			||||||
 | 
					template<typename...>
 | 
				
			||||||
 | 
					struct type_list_diff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Computes the difference between two type lists.
 | 
				
			||||||
 | 
					 * @tparam Type Types provided by the first type list.
 | 
				
			||||||
 | 
					 * @tparam Other Types provided by the second type list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type, typename... Other>
 | 
				
			||||||
 | 
					struct type_list_diff<type_list<Type...>, type_list<Other...>> {
 | 
				
			||||||
 | 
					    /*! @brief A type list that is the difference between the two type lists. */
 | 
				
			||||||
 | 
					    using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam List Type lists between which to compute the difference.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... List>
 | 
				
			||||||
 | 
					using type_list_diff_t = typename type_list_diff<List...>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Primary template isn't defined on purpose. */
 | 
				
			||||||
 | 
					template<typename, template<typename...> class>
 | 
				
			||||||
 | 
					struct type_list_transform;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Applies a given _function_ to a type list and generate a new list.
 | 
				
			||||||
 | 
					 * @tparam Type Types provided by the type list.
 | 
				
			||||||
 | 
					 * @tparam Op Unary operation as template class with a type member named `type`.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type, template<typename...> class Op>
 | 
				
			||||||
 | 
					struct type_list_transform<type_list<Type...>, Op> {
 | 
				
			||||||
 | 
					    /*! @brief Resulting type list after applying the transform function. */
 | 
				
			||||||
 | 
					    using type = type_list<typename Op<Type>::type...>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam List Type list.
 | 
				
			||||||
 | 
					 * @tparam Op Unary operation as template class with a type member named `type`.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename List, template<typename...> class Op>
 | 
				
			||||||
 | 
					using type_list_transform_t = typename type_list_transform<List, Op>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief A class to use to push around lists of constant values, nothing more.
 | 
				
			||||||
 | 
					 * @tparam Value Values provided by the value list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto... Value>
 | 
				
			||||||
 | 
					struct value_list {
 | 
				
			||||||
 | 
					    /*! @brief Value list type. */
 | 
				
			||||||
 | 
					    using type = value_list;
 | 
				
			||||||
 | 
					    /*! @brief Compile-time number of elements in the value list. */
 | 
				
			||||||
 | 
					    static constexpr auto size = sizeof...(Value);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Primary template isn't defined on purpose. */
 | 
				
			||||||
 | 
					template<std::size_t, typename>
 | 
				
			||||||
 | 
					struct value_list_element;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides compile-time indexed access to the values of a value list.
 | 
				
			||||||
 | 
					 * @tparam Index Index of the value to return.
 | 
				
			||||||
 | 
					 * @tparam Value First value provided by the value list.
 | 
				
			||||||
 | 
					 * @tparam Other Other values provided by the value list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<std::size_t Index, auto Value, auto... Other>
 | 
				
			||||||
 | 
					struct value_list_element<Index, value_list<Value, Other...>>
 | 
				
			||||||
 | 
					    : value_list_element<Index - 1u, value_list<Other...>> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides compile-time indexed access to the types of a type list.
 | 
				
			||||||
 | 
					 * @tparam Value First value provided by the value list.
 | 
				
			||||||
 | 
					 * @tparam Other Other values provided by the value list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto Value, auto... Other>
 | 
				
			||||||
 | 
					struct value_list_element<0u, value_list<Value, Other...>> {
 | 
				
			||||||
 | 
					    /*! @brief Searched type. */
 | 
				
			||||||
 | 
					    using type = decltype(Value);
 | 
				
			||||||
 | 
					    /*! @brief Searched value. */
 | 
				
			||||||
 | 
					    static constexpr auto value = Value;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam Index Index of the type to return.
 | 
				
			||||||
 | 
					 * @tparam List Value list to search into.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<std::size_t Index, typename List>
 | 
				
			||||||
 | 
					using value_list_element_t = typename value_list_element<Index, List>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam Index Index of the value to return.
 | 
				
			||||||
 | 
					 * @tparam List Value list to search into.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<std::size_t Index, typename List>
 | 
				
			||||||
 | 
					inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Primary template isn't defined on purpose. */
 | 
				
			||||||
 | 
					template<auto, typename>
 | 
				
			||||||
 | 
					struct value_list_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides compile-time type access to the values of a value list.
 | 
				
			||||||
 | 
					 * @tparam Value Value to look for and for which to return the index.
 | 
				
			||||||
 | 
					 * @tparam First First value provided by the value list.
 | 
				
			||||||
 | 
					 * @tparam Other Other values provided by the value list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto Value, auto First, auto... Other>
 | 
				
			||||||
 | 
					struct value_list_index<Value, value_list<First, Other...>> {
 | 
				
			||||||
 | 
					    /*! @brief Unsigned integer type. */
 | 
				
			||||||
 | 
					    using value_type = std::size_t;
 | 
				
			||||||
 | 
					    /*! @brief Compile-time position of the given value in the sublist. */
 | 
				
			||||||
 | 
					    static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides compile-time type access to the values of a value list.
 | 
				
			||||||
 | 
					 * @tparam Value Value to look for and for which to return the index.
 | 
				
			||||||
 | 
					 * @tparam Other Other values provided by the value list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto Value, auto... Other>
 | 
				
			||||||
 | 
					struct value_list_index<Value, value_list<Value, Other...>> {
 | 
				
			||||||
 | 
					    static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
 | 
				
			||||||
 | 
					    /*! @brief Unsigned integer type. */
 | 
				
			||||||
 | 
					    using value_type = std::size_t;
 | 
				
			||||||
 | 
					    /*! @brief Compile-time position of the given value in the sublist. */
 | 
				
			||||||
 | 
					    static constexpr value_type value = 0u;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides compile-time type access to the values of a value list.
 | 
				
			||||||
 | 
					 * @tparam Value Value to look for and for which to return the index.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto Value>
 | 
				
			||||||
 | 
					struct value_list_index<Value, value_list<>> {
 | 
				
			||||||
 | 
					    /*! @brief Unsigned integer type. */
 | 
				
			||||||
 | 
					    using value_type = std::size_t;
 | 
				
			||||||
 | 
					    /*! @brief Compile-time position of the given type in the sublist. */
 | 
				
			||||||
 | 
					    static constexpr value_type value = 0u;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam List Value list.
 | 
				
			||||||
 | 
					 * @tparam Value Value to look for and for which to return the index.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto Value, typename List>
 | 
				
			||||||
 | 
					inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Concatenates multiple value lists.
 | 
				
			||||||
 | 
					 * @tparam Value Values provided by the first value list.
 | 
				
			||||||
 | 
					 * @tparam Other Values provided by the second value list.
 | 
				
			||||||
 | 
					 * @return A value list composed by the values of both the value lists.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto... Value, auto... Other>
 | 
				
			||||||
 | 
					constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
 | 
				
			||||||
 | 
					    return {};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Primary template isn't defined on purpose. */
 | 
				
			||||||
 | 
					template<typename...>
 | 
				
			||||||
 | 
					struct value_list_cat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Concatenates multiple value lists. */
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct value_list_cat<> {
 | 
				
			||||||
 | 
					    /*! @brief A value list composed by the values of all the value lists. */
 | 
				
			||||||
 | 
					    using type = value_list<>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Concatenates multiple value lists.
 | 
				
			||||||
 | 
					 * @tparam Value Values provided by the first value list.
 | 
				
			||||||
 | 
					 * @tparam Other Values provided by the second value list.
 | 
				
			||||||
 | 
					 * @tparam List Other value lists, if any.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto... Value, auto... Other, typename... List>
 | 
				
			||||||
 | 
					struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
 | 
				
			||||||
 | 
					    /*! @brief A value list composed by the values of all the value lists. */
 | 
				
			||||||
 | 
					    using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Concatenates multiple value lists.
 | 
				
			||||||
 | 
					 * @tparam Value Values provided by the value list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto... Value>
 | 
				
			||||||
 | 
					struct value_list_cat<value_list<Value...>> {
 | 
				
			||||||
 | 
					    /*! @brief A value list composed by the values of all the value lists. */
 | 
				
			||||||
 | 
					    using type = value_list<Value...>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam List Value lists to concatenate.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... List>
 | 
				
			||||||
 | 
					using value_list_cat_t = typename value_list_cat<List...>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Primary template isn't defined on purpose. */
 | 
				
			||||||
 | 
					template<typename>
 | 
				
			||||||
 | 
					struct value_list_unique;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Removes duplicates values from a value list.
 | 
				
			||||||
 | 
					 * @tparam Value One of the values provided by the given value list.
 | 
				
			||||||
 | 
					 * @tparam Other The other values provided by the given value list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto Value, auto... Other>
 | 
				
			||||||
 | 
					struct value_list_unique<value_list<Value, Other...>> {
 | 
				
			||||||
 | 
					    /*! @brief A value list without duplicate types. */
 | 
				
			||||||
 | 
					    using type = std::conditional_t<
 | 
				
			||||||
 | 
					        ((Value == Other) || ...),
 | 
				
			||||||
 | 
					        typename value_list_unique<value_list<Other...>>::type,
 | 
				
			||||||
 | 
					        value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Removes duplicates values from a value list. */
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct value_list_unique<value_list<>> {
 | 
				
			||||||
 | 
					    /*! @brief A value list without duplicate types. */
 | 
				
			||||||
 | 
					    using type = value_list<>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam Type A value list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					using value_list_unique_t = typename value_list_unique<Type>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides the member constant `value` to true if a value list contains
 | 
				
			||||||
 | 
					 * a given value, false otherwise.
 | 
				
			||||||
 | 
					 * @tparam List Value list.
 | 
				
			||||||
 | 
					 * @tparam Value Value to look for.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename List, auto Value>
 | 
				
			||||||
 | 
					struct value_list_contains;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @copybrief value_list_contains
 | 
				
			||||||
 | 
					 * @tparam Value Values provided by the value list.
 | 
				
			||||||
 | 
					 * @tparam Other Value to look for.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto... Value, auto Other>
 | 
				
			||||||
 | 
					struct value_list_contains<value_list<Value...>, Other>
 | 
				
			||||||
 | 
					    : std::bool_constant<((Value == Other) || ...)> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam List Value list.
 | 
				
			||||||
 | 
					 * @tparam Value Value to look for.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename List, auto Value>
 | 
				
			||||||
 | 
					inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Primary template isn't defined on purpose. */
 | 
				
			||||||
 | 
					template<typename...>
 | 
				
			||||||
 | 
					class value_list_diff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Computes the difference between two value lists.
 | 
				
			||||||
 | 
					 * @tparam Value Values provided by the first value list.
 | 
				
			||||||
 | 
					 * @tparam Other Values provided by the second value list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto... Value, auto... Other>
 | 
				
			||||||
 | 
					class value_list_diff<value_list<Value...>, value_list<Other...>> {
 | 
				
			||||||
 | 
					    using v141_toolset_workaround = value_list<Other...>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /*! @brief A value list that is the difference between the two value lists. */
 | 
				
			||||||
 | 
					    using type = value_list_cat_t<std::conditional_t<value_list_contains_v<v141_toolset_workaround, Value>, value_list<>, value_list<Value>>...>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam List Value lists between which to compute the difference.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... List>
 | 
				
			||||||
 | 
					using value_list_diff_t = typename value_list_diff<List...>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Same as std::is_invocable, but with tuples. */
 | 
				
			||||||
 | 
					template<typename, typename>
 | 
				
			||||||
 | 
					struct is_applicable: std::false_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @copybrief is_applicable
 | 
				
			||||||
 | 
					 * @tparam Func A valid function type.
 | 
				
			||||||
 | 
					 * @tparam Tuple Tuple-like type.
 | 
				
			||||||
 | 
					 * @tparam Args The list of arguments to use to probe the function type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Func, template<typename...> class Tuple, typename... Args>
 | 
				
			||||||
 | 
					struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @copybrief is_applicable
 | 
				
			||||||
 | 
					 * @tparam Func A valid function type.
 | 
				
			||||||
 | 
					 * @tparam Tuple Tuple-like type.
 | 
				
			||||||
 | 
					 * @tparam Args The list of arguments to use to probe the function type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Func, template<typename...> class Tuple, typename... Args>
 | 
				
			||||||
 | 
					struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam Func A valid function type.
 | 
				
			||||||
 | 
					 * @tparam Args The list of arguments to use to probe the function type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Func, typename Args>
 | 
				
			||||||
 | 
					inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
 | 
				
			||||||
 | 
					template<typename, typename, typename>
 | 
				
			||||||
 | 
					struct is_applicable_r: std::false_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @copybrief is_applicable_r
 | 
				
			||||||
 | 
					 * @tparam Ret The type to which the return type of the function should be
 | 
				
			||||||
 | 
					 * convertible.
 | 
				
			||||||
 | 
					 * @tparam Func A valid function type.
 | 
				
			||||||
 | 
					 * @tparam Args The list of arguments to use to probe the function type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Ret, typename Func, typename... Args>
 | 
				
			||||||
 | 
					struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam Ret The type to which the return type of the function should be
 | 
				
			||||||
 | 
					 * convertible.
 | 
				
			||||||
 | 
					 * @tparam Func A valid function type.
 | 
				
			||||||
 | 
					 * @tparam Args The list of arguments to use to probe the function type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Ret, typename Func, typename Args>
 | 
				
			||||||
 | 
					inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides the member constant `value` to true if a given type is
 | 
				
			||||||
 | 
					 * complete, false otherwise.
 | 
				
			||||||
 | 
					 * @tparam Type The type to test.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename = void>
 | 
				
			||||||
 | 
					struct is_complete: std::false_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc is_complete */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam Type The type to test.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					inline constexpr bool is_complete_v = is_complete<Type>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides the member constant `value` to true if a given type is an
 | 
				
			||||||
 | 
					 * iterator, false otherwise.
 | 
				
			||||||
 | 
					 * @tparam Type The type to test.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename = void>
 | 
				
			||||||
 | 
					struct is_iterator: std::false_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename, typename = void>
 | 
				
			||||||
 | 
					struct has_iterator_category: std::false_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 * @endcond
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc is_iterator */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_pointer_t<Type>>, void>>>
 | 
				
			||||||
 | 
					    : internal::has_iterator_category<Type> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam Type The type to test.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					inline constexpr bool is_iterator_v = is_iterator<Type>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides the member constant `value` to true if a given type is both
 | 
				
			||||||
 | 
					 * an empty and non-final class, false otherwise.
 | 
				
			||||||
 | 
					 * @tparam Type The type to test
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct is_ebco_eligible
 | 
				
			||||||
 | 
					    : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam Type The type to test.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides the member constant `value` to true if `Type::is_transparent`
 | 
				
			||||||
 | 
					 * is valid and denotes a type, false otherwise.
 | 
				
			||||||
 | 
					 * @tparam Type The type to test.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename = void>
 | 
				
			||||||
 | 
					struct is_transparent: std::false_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc is_transparent */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam Type The type to test.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					inline constexpr bool is_transparent_v = is_transparent<Type>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides the member constant `value` to true if a given type is
 | 
				
			||||||
 | 
					 * equality comparable, false otherwise.
 | 
				
			||||||
 | 
					 * @tparam Type The type to test.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename = void>
 | 
				
			||||||
 | 
					struct is_equality_comparable: std::false_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename, typename = void>
 | 
				
			||||||
 | 
					struct has_tuple_size_value: std::false_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type, std::size_t... Index>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
 | 
				
			||||||
 | 
					    return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
 | 
				
			||||||
 | 
					    if constexpr(is_iterator_v<Type>) {
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
 | 
				
			||||||
 | 
					        return maybe_equality_comparable<Type>(choice<0>);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return is_equality_comparable<typename Type::value_type>::value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_cv_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
 | 
				
			||||||
 | 
					    if constexpr(has_tuple_size_value<Type>::value) {
 | 
				
			||||||
 | 
					        return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return maybe_equality_comparable<Type>(choice<1>);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 * @endcond
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc is_equality_comparable */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
 | 
				
			||||||
 | 
					    : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc is_equality_comparable */
 | 
				
			||||||
 | 
					template<typename Type, auto N>
 | 
				
			||||||
 | 
					struct is_equality_comparable<Type[N]>: std::false_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper variable template.
 | 
				
			||||||
 | 
					 * @tparam Type The type to test.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Transcribes the constness of a type to another type.
 | 
				
			||||||
 | 
					 * @tparam To The type to which to transcribe the constness.
 | 
				
			||||||
 | 
					 * @tparam From The type from which to transcribe the constness.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename To, typename From>
 | 
				
			||||||
 | 
					struct constness_as {
 | 
				
			||||||
 | 
					    /*! @brief The type resulting from the transcription of the constness. */
 | 
				
			||||||
 | 
					    using type = std::remove_const_t<To>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @copydoc constness_as */
 | 
				
			||||||
 | 
					template<typename To, typename From>
 | 
				
			||||||
 | 
					struct constness_as<To, const From> {
 | 
				
			||||||
 | 
					    /*! @brief The type resulting from the transcription of the constness. */
 | 
				
			||||||
 | 
					    using type = const To;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Alias template to facilitate the transcription of the constness.
 | 
				
			||||||
 | 
					 * @tparam To The type to which to transcribe the constness.
 | 
				
			||||||
 | 
					 * @tparam From The type from which to transcribe the constness.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename To, typename From>
 | 
				
			||||||
 | 
					using constness_as_t = typename constness_as<To, From>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Extracts the class of a non-static member object or function.
 | 
				
			||||||
 | 
					 * @tparam Member A pointer to a non-static member object or function.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Member>
 | 
				
			||||||
 | 
					class member_class {
 | 
				
			||||||
 | 
					    static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Class, typename Ret, typename... Args>
 | 
				
			||||||
 | 
					    static Class *clazz(Ret (Class::*)(Args...));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Class, typename Ret, typename... Args>
 | 
				
			||||||
 | 
					    static Class *clazz(Ret (Class::*)(Args...) const);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Class, typename Type>
 | 
				
			||||||
 | 
					    static Class *clazz(Type Class::*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /*! @brief The class of the given non-static member object or function. */
 | 
				
			||||||
 | 
					    using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam Member A pointer to a non-static member object or function.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Member>
 | 
				
			||||||
 | 
					using member_class_t = typename member_class<Member>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Extracts the n-th argument of a given function or member function.
 | 
				
			||||||
 | 
					 * @tparam Index The index of the argument to extract.
 | 
				
			||||||
 | 
					 * @tparam Candidate A valid function, member function or data member.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<std::size_t Index, auto Candidate>
 | 
				
			||||||
 | 
					class nth_argument {
 | 
				
			||||||
 | 
					    template<typename Ret, typename... Args>
 | 
				
			||||||
 | 
					    static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Ret, typename Class, typename... Args>
 | 
				
			||||||
 | 
					    static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Ret, typename Class, typename... Args>
 | 
				
			||||||
 | 
					    static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Type, typename Class>
 | 
				
			||||||
 | 
					    static constexpr type_list<Type> pick_up(Type Class ::*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /*! @brief N-th argument of the given function or member function. */
 | 
				
			||||||
 | 
					    using type = type_list_element_t<Index, decltype(pick_up(Candidate))>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam Index The index of the argument to extract.
 | 
				
			||||||
 | 
					 * @tparam Candidate A valid function, member function or data member.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<std::size_t Index, auto Candidate>
 | 
				
			||||||
 | 
					using nth_argument_t = typename nth_argument<Index, Candidate>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename... Type>
 | 
				
			||||||
 | 
					struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<std::size_t Index, typename... Type>
 | 
				
			||||||
 | 
					struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<auto... Value>
 | 
				
			||||||
 | 
					struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<std::size_t Index, auto... Value>
 | 
				
			||||||
 | 
					struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										101
									
								
								external/entt/entt/src/entt/core/utility.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								external/entt/entt/src/entt/core/utility.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,101 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_CORE_UTILITY_HPP
 | 
				
			||||||
 | 
					#define ENTT_CORE_UTILITY_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Identity function object (waiting for C++20). */
 | 
				
			||||||
 | 
					struct identity {
 | 
				
			||||||
 | 
					    /*! @brief Indicates that this is a transparent function object. */
 | 
				
			||||||
 | 
					    using is_transparent = void;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns its argument unchanged.
 | 
				
			||||||
 | 
					     * @tparam Type Type of the argument.
 | 
				
			||||||
 | 
					     * @param value The actual argument.
 | 
				
			||||||
 | 
					     * @return The submitted value as-is.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Type>
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept {
 | 
				
			||||||
 | 
					        return std::forward<Type>(value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Constant utility to disambiguate overloaded members of a class.
 | 
				
			||||||
 | 
					 * @tparam Type Type of the desired overload.
 | 
				
			||||||
 | 
					 * @tparam Class Type of class to which the member belongs.
 | 
				
			||||||
 | 
					 * @param member A valid pointer to a member.
 | 
				
			||||||
 | 
					 * @return Pointer to the member.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename Class>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr auto overload(Type Class::*member) noexcept {
 | 
				
			||||||
 | 
					    return member;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Constant utility to disambiguate overloaded functions.
 | 
				
			||||||
 | 
					 * @tparam Func Function type of the desired overload.
 | 
				
			||||||
 | 
					 * @param func A valid pointer to a function.
 | 
				
			||||||
 | 
					 * @return Pointer to the function.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Func>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr auto overload(Func *func) noexcept {
 | 
				
			||||||
 | 
					    return func;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type for visitors.
 | 
				
			||||||
 | 
					 * @tparam Func Types of function objects.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Func>
 | 
				
			||||||
 | 
					struct overloaded: Func... {
 | 
				
			||||||
 | 
					    using Func::operator()...;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Deduction guide.
 | 
				
			||||||
 | 
					 * @tparam Func Types of function objects.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Func>
 | 
				
			||||||
 | 
					overloaded(Func...) -> overloaded<Func...>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Basic implementation of a y-combinator.
 | 
				
			||||||
 | 
					 * @tparam Func Type of a potentially recursive function.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Func>
 | 
				
			||||||
 | 
					struct y_combinator {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a y-combinator from a given function.
 | 
				
			||||||
 | 
					     * @param recursive A potentially recursive function.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v<Func>)
 | 
				
			||||||
 | 
					        : func{std::move(recursive)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Invokes a y-combinator and therefore its underlying function.
 | 
				
			||||||
 | 
					     * @tparam Args Types of arguments to use to invoke the underlying function.
 | 
				
			||||||
 | 
					     * @param args Parameters to use to invoke the underlying function.
 | 
				
			||||||
 | 
					     * @return Return value of the underlying function, if any.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename... Args>
 | 
				
			||||||
 | 
					    constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v<Func, const y_combinator &, Args...>) {
 | 
				
			||||||
 | 
					        return func(*this, std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @copydoc operator()() */
 | 
				
			||||||
 | 
					    template<typename... Args>
 | 
				
			||||||
 | 
					    constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v<Func, y_combinator &, Args...>) {
 | 
				
			||||||
 | 
					        return func(*this, std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    Func func;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										64
									
								
								external/entt/entt/src/entt/entity/component.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								external/entt/entt/src/entt/entity/component.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_ENTITY_COMPONENT_HPP
 | 
				
			||||||
 | 
					#define ENTT_ENTITY_COMPONENT_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include "../config/config.h"
 | 
				
			||||||
 | 
					#include "fwd.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type, typename = void>
 | 
				
			||||||
 | 
					struct in_place_delete: std::bool_constant<!(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>)> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct in_place_delete<void>: std::false_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct in_place_delete<Type, std::enable_if_t<Type::in_place_delete>>
 | 
				
			||||||
 | 
					    : std::true_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type, typename = void>
 | 
				
			||||||
 | 
					struct page_size: std::integral_constant<std::size_t, !std::is_empty_v<ENTT_ETO_TYPE(Type)> * ENTT_PACKED_PAGE> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct page_size<void>: std::integral_constant<std::size_t, 0u> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct page_size<Type, std::enable_if_t<std::is_convertible_v<decltype(Type::page_size), std::size_t>>>
 | 
				
			||||||
 | 
					    : std::integral_constant<std::size_t, Type::page_size> {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 * @endcond
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Common way to access various properties of components.
 | 
				
			||||||
 | 
					 * @tparam Type Type of component.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename = void>
 | 
				
			||||||
 | 
					struct component_traits {
 | 
				
			||||||
 | 
					    static_assert(std::is_same_v<std::decay_t<Type>, Type>, "Unsupported type");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Component type. */
 | 
				
			||||||
 | 
					    using type = Type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Pointer stability, default is `false`. */
 | 
				
			||||||
 | 
					    static constexpr bool in_place_delete = internal::in_place_delete<Type>::value;
 | 
				
			||||||
 | 
					    /*! @brief Page size, default is `ENTT_PACKED_PAGE` for non-empty types. */
 | 
				
			||||||
 | 
					    static constexpr std::size_t page_size = internal::page_size<Type>::value;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										379
									
								
								external/entt/entt/src/entt/entity/entity.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										379
									
								
								external/entt/entt/src/entt/entity/entity.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,379 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_ENTITY_ENTITY_HPP
 | 
				
			||||||
 | 
					#define ENTT_ENTITY_ENTITY_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include "../config/config.h"
 | 
				
			||||||
 | 
					#include "fwd.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// waiting for C++20 (and std::popcount)
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					static constexpr int popcount(Type value) noexcept {
 | 
				
			||||||
 | 
					    return value ? (int(value & 1) + popcount(value >> 1)) : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename, typename = void>
 | 
				
			||||||
 | 
					struct entt_traits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct entt_traits<Type, std::enable_if_t<std::is_enum_v<Type>>>
 | 
				
			||||||
 | 
					    : entt_traits<std::underlying_type_t<Type>> {
 | 
				
			||||||
 | 
					    using value_type = Type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct entt_traits<Type, std::enable_if_t<std::is_class_v<Type>>>
 | 
				
			||||||
 | 
					    : entt_traits<typename Type::entity_type> {
 | 
				
			||||||
 | 
					    using value_type = Type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct entt_traits<std::uint32_t> {
 | 
				
			||||||
 | 
					    using value_type = std::uint32_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using entity_type = std::uint32_t;
 | 
				
			||||||
 | 
					    using version_type = std::uint16_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static constexpr entity_type entity_mask = 0xFFFFF;
 | 
				
			||||||
 | 
					    static constexpr entity_type version_mask = 0xFFF;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct entt_traits<std::uint64_t> {
 | 
				
			||||||
 | 
					    using value_type = std::uint64_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using entity_type = std::uint64_t;
 | 
				
			||||||
 | 
					    using version_type = std::uint32_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static constexpr entity_type entity_mask = 0xFFFFFFFF;
 | 
				
			||||||
 | 
					    static constexpr entity_type version_mask = 0xFFFFFFFF;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 * @endcond
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Common basic entity traits implementation.
 | 
				
			||||||
 | 
					 * @tparam Traits Actual entity traits to use.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Traits>
 | 
				
			||||||
 | 
					class basic_entt_traits {
 | 
				
			||||||
 | 
					    static constexpr auto length = internal::popcount(Traits::entity_mask);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static_assert(Traits::entity_mask && ((typename Traits::entity_type{1} << length) == (Traits::entity_mask + 1)), "Invalid entity mask");
 | 
				
			||||||
 | 
					    static_assert((typename Traits::entity_type{1} << internal::popcount(Traits::version_mask)) == (Traits::version_mask + 1), "Invalid version mask");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /*! @brief Value type. */
 | 
				
			||||||
 | 
					    using value_type = typename Traits::value_type;
 | 
				
			||||||
 | 
					    /*! @brief Underlying entity type. */
 | 
				
			||||||
 | 
					    using entity_type = typename Traits::entity_type;
 | 
				
			||||||
 | 
					    /*! @brief Underlying version type. */
 | 
				
			||||||
 | 
					    using version_type = typename Traits::version_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Entity mask size. */
 | 
				
			||||||
 | 
					    static constexpr entity_type entity_mask = Traits::entity_mask;
 | 
				
			||||||
 | 
					    /*! @brief Version mask size */
 | 
				
			||||||
 | 
					    static constexpr entity_type version_mask = Traits::version_mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Converts an entity to its underlying type.
 | 
				
			||||||
 | 
					     * @param value The value to convert.
 | 
				
			||||||
 | 
					     * @return The integral representation of the given value.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr entity_type to_integral(const value_type value) noexcept {
 | 
				
			||||||
 | 
					        return static_cast<entity_type>(value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the entity part once converted to the underlying type.
 | 
				
			||||||
 | 
					     * @param value The value to convert.
 | 
				
			||||||
 | 
					     * @return The integral representation of the entity part.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr entity_type to_entity(const value_type value) noexcept {
 | 
				
			||||||
 | 
					        return (to_integral(value) & entity_mask);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the version part once converted to the underlying type.
 | 
				
			||||||
 | 
					     * @param value The value to convert.
 | 
				
			||||||
 | 
					     * @return The integral representation of the version part.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr version_type to_version(const value_type value) noexcept {
 | 
				
			||||||
 | 
					        return static_cast<version_type>(to_integral(value) >> length);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the successor of a given identifier.
 | 
				
			||||||
 | 
					     * @param value The identifier of which to return the successor.
 | 
				
			||||||
 | 
					     * @return The successor of the given identifier.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr value_type next(const value_type value) noexcept {
 | 
				
			||||||
 | 
					        const auto vers = to_version(value) + 1;
 | 
				
			||||||
 | 
					        return construct(to_entity(value), static_cast<version_type>(vers + (vers == version_mask)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs an identifier from its parts.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * If the version part is not provided, a tombstone is returned.<br/>
 | 
				
			||||||
 | 
					     * If the entity part is not provided, a null identifier is returned.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param entity The entity part of the identifier.
 | 
				
			||||||
 | 
					     * @param version The version part of the identifier.
 | 
				
			||||||
 | 
					     * @return A properly constructed identifier.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr value_type construct(const entity_type entity, const version_type version) noexcept {
 | 
				
			||||||
 | 
					        return value_type{(entity & entity_mask) | (static_cast<entity_type>(version) << length)};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Combines two identifiers in a single one.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * The returned identifier is a copy of the first element except for its
 | 
				
			||||||
 | 
					     * version, which is taken from the second element.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param lhs The identifier from which to take the entity part.
 | 
				
			||||||
 | 
					     * @param rhs The identifier from which to take the version part.
 | 
				
			||||||
 | 
					     * @return A properly constructed identifier.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] static constexpr value_type combine(const entity_type lhs, const entity_type rhs) noexcept {
 | 
				
			||||||
 | 
					        constexpr auto mask = (version_mask << length);
 | 
				
			||||||
 | 
					        return value_type{(lhs & entity_mask) | (rhs & mask)};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Entity traits.
 | 
				
			||||||
 | 
					 * @tparam Type Type of identifier.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					struct entt_traits: basic_entt_traits<internal::entt_traits<Type>> {
 | 
				
			||||||
 | 
					    /*! @brief Base type. */
 | 
				
			||||||
 | 
					    using base_type = basic_entt_traits<internal::entt_traits<Type>>;
 | 
				
			||||||
 | 
					    /*! @brief Page size, default is `ENTT_SPARSE_PAGE`. */
 | 
				
			||||||
 | 
					    static constexpr std::size_t page_size = ENTT_SPARSE_PAGE;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @copydoc entt_traits<Entity>::to_integral
 | 
				
			||||||
 | 
					 * @tparam Entity The value type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Entity>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr typename entt_traits<Entity>::entity_type to_integral(const Entity value) noexcept {
 | 
				
			||||||
 | 
					    return entt_traits<Entity>::to_integral(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @copydoc entt_traits<Entity>::to_entity
 | 
				
			||||||
 | 
					 * @tparam Entity The value type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Entity>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr typename entt_traits<Entity>::entity_type to_entity(const Entity value) noexcept {
 | 
				
			||||||
 | 
					    return entt_traits<Entity>::to_entity(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @copydoc entt_traits<Entity>::to_version
 | 
				
			||||||
 | 
					 * @tparam Entity The value type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Entity>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr typename entt_traits<Entity>::version_type to_version(const Entity value) noexcept {
 | 
				
			||||||
 | 
					    return entt_traits<Entity>::to_version(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Null object for all identifiers.  */
 | 
				
			||||||
 | 
					struct null_t {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Converts the null object to identifiers of any type.
 | 
				
			||||||
 | 
					     * @tparam Entity Type of identifier.
 | 
				
			||||||
 | 
					     * @return The null representation for the given type.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Entity>
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr operator Entity() const noexcept {
 | 
				
			||||||
 | 
					        using traits_type = entt_traits<Entity>;
 | 
				
			||||||
 | 
					        constexpr auto value = traits_type::construct(traits_type::entity_mask, traits_type::version_mask);
 | 
				
			||||||
 | 
					        return value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Compares two null objects.
 | 
				
			||||||
 | 
					     * @param other A null object.
 | 
				
			||||||
 | 
					     * @return True in all cases.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr bool operator==([[maybe_unused]] const null_t other) const noexcept {
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Compares two null objects.
 | 
				
			||||||
 | 
					     * @param other A null object.
 | 
				
			||||||
 | 
					     * @return False in all cases.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr bool operator!=([[maybe_unused]] const null_t other) const noexcept {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Compares a null object and an identifier of any type.
 | 
				
			||||||
 | 
					     * @tparam Entity Type of identifier.
 | 
				
			||||||
 | 
					     * @param entity Identifier with which to compare.
 | 
				
			||||||
 | 
					     * @return False if the two elements differ, true otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Entity>
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr bool operator==(const Entity entity) const noexcept {
 | 
				
			||||||
 | 
					        using traits_type = entt_traits<Entity>;
 | 
				
			||||||
 | 
					        return traits_type::to_entity(entity) == traits_type::to_entity(*this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Compares a null object and an identifier of any type.
 | 
				
			||||||
 | 
					     * @tparam Entity Type of identifier.
 | 
				
			||||||
 | 
					     * @param entity Identifier with which to compare.
 | 
				
			||||||
 | 
					     * @return True if the two elements differ, false otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Entity>
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr bool operator!=(const Entity entity) const noexcept {
 | 
				
			||||||
 | 
					        return !(entity == *this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares a null object and an identifier of any type.
 | 
				
			||||||
 | 
					 * @tparam Entity Type of identifier.
 | 
				
			||||||
 | 
					 * @param entity Identifier with which to compare.
 | 
				
			||||||
 | 
					 * @param other A null object yet to be converted.
 | 
				
			||||||
 | 
					 * @return False if the two elements differ, true otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Entity>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator==(const Entity entity, const null_t other) noexcept {
 | 
				
			||||||
 | 
					    return other.operator==(entity);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares a null object and an identifier of any type.
 | 
				
			||||||
 | 
					 * @tparam Entity Type of identifier.
 | 
				
			||||||
 | 
					 * @param entity Identifier with which to compare.
 | 
				
			||||||
 | 
					 * @param other A null object yet to be converted.
 | 
				
			||||||
 | 
					 * @return True if the two elements differ, false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Entity>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator!=(const Entity entity, const null_t other) noexcept {
 | 
				
			||||||
 | 
					    return !(other == entity);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Tombstone object for all identifiers.  */
 | 
				
			||||||
 | 
					struct tombstone_t {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Converts the tombstone object to identifiers of any type.
 | 
				
			||||||
 | 
					     * @tparam Entity Type of identifier.
 | 
				
			||||||
 | 
					     * @return The tombstone representation for the given type.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Entity>
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr operator Entity() const noexcept {
 | 
				
			||||||
 | 
					        using traits_type = entt_traits<Entity>;
 | 
				
			||||||
 | 
					        constexpr auto value = traits_type::construct(traits_type::entity_mask, traits_type::version_mask);
 | 
				
			||||||
 | 
					        return value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Compares two tombstone objects.
 | 
				
			||||||
 | 
					     * @param other A tombstone object.
 | 
				
			||||||
 | 
					     * @return True in all cases.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr bool operator==([[maybe_unused]] const tombstone_t other) const noexcept {
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Compares two tombstone objects.
 | 
				
			||||||
 | 
					     * @param other A tombstone object.
 | 
				
			||||||
 | 
					     * @return False in all cases.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr bool operator!=([[maybe_unused]] const tombstone_t other) const noexcept {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Compares a tombstone object and an identifier of any type.
 | 
				
			||||||
 | 
					     * @tparam Entity Type of identifier.
 | 
				
			||||||
 | 
					     * @param entity Identifier with which to compare.
 | 
				
			||||||
 | 
					     * @return False if the two elements differ, true otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Entity>
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr bool operator==(const Entity entity) const noexcept {
 | 
				
			||||||
 | 
					        using traits_type = entt_traits<Entity>;
 | 
				
			||||||
 | 
					        return traits_type::to_version(entity) == traits_type::to_version(*this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Compares a tombstone object and an identifier of any type.
 | 
				
			||||||
 | 
					     * @tparam Entity Type of identifier.
 | 
				
			||||||
 | 
					     * @param entity Identifier with which to compare.
 | 
				
			||||||
 | 
					     * @return True if the two elements differ, false otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Entity>
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr bool operator!=(const Entity entity) const noexcept {
 | 
				
			||||||
 | 
					        return !(entity == *this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares a tombstone object and an identifier of any type.
 | 
				
			||||||
 | 
					 * @tparam Entity Type of identifier.
 | 
				
			||||||
 | 
					 * @param entity Identifier with which to compare.
 | 
				
			||||||
 | 
					 * @param other A tombstone object yet to be converted.
 | 
				
			||||||
 | 
					 * @return False if the two elements differ, true otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Entity>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator==(const Entity entity, const tombstone_t other) noexcept {
 | 
				
			||||||
 | 
					    return other.operator==(entity);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares a tombstone object and an identifier of any type.
 | 
				
			||||||
 | 
					 * @tparam Entity Type of identifier.
 | 
				
			||||||
 | 
					 * @param entity Identifier with which to compare.
 | 
				
			||||||
 | 
					 * @param other A tombstone object yet to be converted.
 | 
				
			||||||
 | 
					 * @return True if the two elements differ, false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Entity>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator!=(const Entity entity, const tombstone_t other) noexcept {
 | 
				
			||||||
 | 
					    return !(other == entity);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compile-time constant for null entities.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * There exist implicit conversions from this variable to identifiers of any
 | 
				
			||||||
 | 
					 * allowed type. Similarly, there exist comparison operators between the null
 | 
				
			||||||
 | 
					 * entity and any other identifier.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					inline constexpr null_t null{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compile-time constant for tombstone entities.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * There exist implicit conversions from this variable to identifiers of any
 | 
				
			||||||
 | 
					 * allowed type. Similarly, there exist comparison operators between the
 | 
				
			||||||
 | 
					 * tombstone entity and any other identifier.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					inline constexpr tombstone_t tombstone{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										257
									
								
								external/entt/entt/src/entt/entity/fwd.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								external/entt/entt/src/entt/entity/fwd.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,257 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_ENTITY_FWD_HPP
 | 
				
			||||||
 | 
					#define ENTT_ENTITY_FWD_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include "../core/fwd.hpp"
 | 
				
			||||||
 | 
					#include "../core/type_traits.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Default entity identifier. */
 | 
				
			||||||
 | 
					enum class entity : id_type {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Storage deletion policy. */
 | 
				
			||||||
 | 
					enum class deletion_policy : std::uint8_t {
 | 
				
			||||||
 | 
					    /*! @brief Swap-and-pop deletion policy. */
 | 
				
			||||||
 | 
					    swap_and_pop = 0u,
 | 
				
			||||||
 | 
					    /*! @brief In-place deletion policy. */
 | 
				
			||||||
 | 
					    in_place = 1u
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Entity = entity, typename = std::allocator<Entity>>
 | 
				
			||||||
 | 
					class basic_sparse_set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type, typename = entity, typename = std::allocator<Type>, typename = void>
 | 
				
			||||||
 | 
					class basic_storage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					class sigh_mixin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Provides a common way to define storage types.
 | 
				
			||||||
 | 
					 * @tparam Type Storage value type.
 | 
				
			||||||
 | 
					 * @tparam Entity A valid entity type.
 | 
				
			||||||
 | 
					 * @tparam Allocator Type of allocator used to manage memory and elements.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename Entity = entity, typename Allocator = std::allocator<Type>, typename = void>
 | 
				
			||||||
 | 
					struct storage_type {
 | 
				
			||||||
 | 
					    /*! @brief Type-to-storage conversion result. */
 | 
				
			||||||
 | 
					    using type = sigh_mixin<basic_storage<Type, Entity, Allocator>>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam Args Arguments to forward.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Args>
 | 
				
			||||||
 | 
					using storage_type_t = typename storage_type<Args...>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Type-to-storage conversion utility that preserves constness.
 | 
				
			||||||
 | 
					 * @tparam Type Storage value type, eventually const.
 | 
				
			||||||
 | 
					 * @tparam Entity A valid entity type.
 | 
				
			||||||
 | 
					 * @tparam Allocator Type of allocator used to manage memory and elements.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type, typename Entity = entity, typename Allocator = std::allocator<std::remove_const_t<Type>>>
 | 
				
			||||||
 | 
					struct storage_for {
 | 
				
			||||||
 | 
					    /*! @brief Type-to-storage conversion result. */
 | 
				
			||||||
 | 
					    using type = constness_as_t<storage_type_t<std::remove_const_t<Type>, Entity, Allocator>, Type>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper type.
 | 
				
			||||||
 | 
					 * @tparam Args Arguments to forward.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Args>
 | 
				
			||||||
 | 
					using storage_for_t = typename storage_for<Args...>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Entity = entity, typename = std::allocator<Entity>>
 | 
				
			||||||
 | 
					class basic_registry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename, typename, typename = void>
 | 
				
			||||||
 | 
					class basic_view;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Type, typename = std::allocator<Type *>>
 | 
				
			||||||
 | 
					class basic_runtime_view;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename, typename, typename>
 | 
				
			||||||
 | 
					class basic_group;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename, typename Mask = std::uint32_t, typename = std::allocator<Mask>>
 | 
				
			||||||
 | 
					class basic_observer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename>
 | 
				
			||||||
 | 
					class basic_organizer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename, typename...>
 | 
				
			||||||
 | 
					struct basic_handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename>
 | 
				
			||||||
 | 
					class basic_snapshot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename>
 | 
				
			||||||
 | 
					class basic_snapshot_loader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename>
 | 
				
			||||||
 | 
					class basic_continuous_loader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Alias for exclusion lists.
 | 
				
			||||||
 | 
					 * @tparam Type List of types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type>
 | 
				
			||||||
 | 
					struct exclude_t final: type_list<Type...> {
 | 
				
			||||||
 | 
					    /*! @brief Default constructor. */
 | 
				
			||||||
 | 
					    explicit constexpr exclude_t() {}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Variable template for exclusion lists.
 | 
				
			||||||
 | 
					 * @tparam Type List of types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type>
 | 
				
			||||||
 | 
					inline constexpr exclude_t<Type...> exclude{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Alias for lists of observed components.
 | 
				
			||||||
 | 
					 * @tparam Type List of types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type>
 | 
				
			||||||
 | 
					struct get_t final: type_list<Type...> {
 | 
				
			||||||
 | 
					    /*! @brief Default constructor. */
 | 
				
			||||||
 | 
					    explicit constexpr get_t() {}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Variable template for lists of observed components.
 | 
				
			||||||
 | 
					 * @tparam Type List of types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type>
 | 
				
			||||||
 | 
					inline constexpr get_t<Type...> get{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Alias for lists of owned components.
 | 
				
			||||||
 | 
					 * @tparam Type List of types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type>
 | 
				
			||||||
 | 
					struct owned_t final: type_list<Type...> {
 | 
				
			||||||
 | 
					    /*! @brief Default constructor. */
 | 
				
			||||||
 | 
					    explicit constexpr owned_t() {}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Variable template for lists of owned components.
 | 
				
			||||||
 | 
					 * @tparam Type List of types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type>
 | 
				
			||||||
 | 
					inline constexpr owned_t<Type...> owned{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Applies a given _function_ to a get list and generate a new list.
 | 
				
			||||||
 | 
					 * @tparam Type Types provided by the get list.
 | 
				
			||||||
 | 
					 * @tparam Op Unary operation as template class with a type member named `type`.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type, template<typename...> class Op>
 | 
				
			||||||
 | 
					struct type_list_transform<get_t<Type...>, Op> {
 | 
				
			||||||
 | 
					    /*! @brief Resulting get list after applying the transform function. */
 | 
				
			||||||
 | 
					    using type = get_t<typename Op<Type>::type...>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Applies a given _function_ to an exclude list and generate a new list.
 | 
				
			||||||
 | 
					 * @tparam Type Types provided by the exclude list.
 | 
				
			||||||
 | 
					 * @tparam Op Unary operation as template class with a type member named `type`.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type, template<typename...> class Op>
 | 
				
			||||||
 | 
					struct type_list_transform<exclude_t<Type...>, Op> {
 | 
				
			||||||
 | 
					    /*! @brief Resulting exclude list after applying the transform function. */
 | 
				
			||||||
 | 
					    using type = exclude_t<typename Op<Type>::type...>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Applies a given _function_ to an owned list and generate a new list.
 | 
				
			||||||
 | 
					 * @tparam Type Types provided by the owned list.
 | 
				
			||||||
 | 
					 * @tparam Op Unary operation as template class with a type member named `type`.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Type, template<typename...> class Op>
 | 
				
			||||||
 | 
					struct type_list_transform<owned_t<Type...>, Op> {
 | 
				
			||||||
 | 
					    /*! @brief Resulting owned list after applying the transform function. */
 | 
				
			||||||
 | 
					    using type = owned_t<typename Op<Type>::type...>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Alias declaration for the most common use case. */
 | 
				
			||||||
 | 
					using sparse_set = basic_sparse_set<>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Alias declaration for the most common use case.
 | 
				
			||||||
 | 
					 * @tparam Type Type of objects assigned to the entities.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					using storage = basic_storage<Type>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Alias declaration for the most common use case. */
 | 
				
			||||||
 | 
					using registry = basic_registry<>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Alias declaration for the most common use case. */
 | 
				
			||||||
 | 
					using observer = basic_observer<registry>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Alias declaration for the most common use case. */
 | 
				
			||||||
 | 
					using organizer = basic_organizer<registry>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Alias declaration for the most common use case. */
 | 
				
			||||||
 | 
					using handle = basic_handle<registry>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Alias declaration for the most common use case. */
 | 
				
			||||||
 | 
					using const_handle = basic_handle<const registry>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Alias declaration for the most common use case.
 | 
				
			||||||
 | 
					 * @tparam Args Other template parameters.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Args>
 | 
				
			||||||
 | 
					using handle_view = basic_handle<registry, Args...>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Alias declaration for the most common use case.
 | 
				
			||||||
 | 
					 * @tparam Args Other template parameters.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Args>
 | 
				
			||||||
 | 
					using const_handle_view = basic_handle<const registry, Args...>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Alias declaration for the most common use case. */
 | 
				
			||||||
 | 
					using snapshot = basic_snapshot<registry>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Alias declaration for the most common use case. */
 | 
				
			||||||
 | 
					using snapshot_loader = basic_snapshot_loader<registry>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Alias declaration for the most common use case. */
 | 
				
			||||||
 | 
					using continuous_loader = basic_continuous_loader<registry>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Alias declaration for the most common use case.
 | 
				
			||||||
 | 
					 * @tparam Get Types of storage iterated by the view.
 | 
				
			||||||
 | 
					 * @tparam Exclude Types of storage used to filter the view.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Get, typename Exclude = exclude_t<>>
 | 
				
			||||||
 | 
					using view = basic_view<type_list_transform_t<Get, storage_for>, type_list_transform_t<Exclude, storage_for>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Alias declaration for the most common use case. */
 | 
				
			||||||
 | 
					using runtime_view = basic_runtime_view<sparse_set>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Alias declaration for the most common use case. */
 | 
				
			||||||
 | 
					using const_runtime_view = basic_runtime_view<const sparse_set>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Alias declaration for the most common use case.
 | 
				
			||||||
 | 
					 * @tparam Owned Types of storage _owned_ by the group.
 | 
				
			||||||
 | 
					 * @tparam Get Types of storage _observed_ by the group.
 | 
				
			||||||
 | 
					 * @tparam Exclude Types of storage used to filter the group.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Owned, typename Get, typename Exclude>
 | 
				
			||||||
 | 
					using group = basic_group<type_list_transform_t<Owned, storage_for>, type_list_transform_t<Get, storage_for>, type_list_transform_t<Exclude, storage_for>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										1084
									
								
								external/entt/entt/src/entt/entity/group.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1084
									
								
								external/entt/entt/src/entt/entity/group.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										384
									
								
								external/entt/entt/src/entt/entity/handle.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										384
									
								
								external/entt/entt/src/entt/entity/handle.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,384 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_ENTITY_HANDLE_HPP
 | 
				
			||||||
 | 
					#define ENTT_ENTITY_HANDLE_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iterator>
 | 
				
			||||||
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include "../core/iterator.hpp"
 | 
				
			||||||
 | 
					#include "../core/type_traits.hpp"
 | 
				
			||||||
 | 
					#include "entity.hpp"
 | 
				
			||||||
 | 
					#include "fwd.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @cond TURN_OFF_DOXYGEN
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename It>
 | 
				
			||||||
 | 
					class handle_storage_iterator final {
 | 
				
			||||||
 | 
					    template<typename Other>
 | 
				
			||||||
 | 
					    friend class handle_storage_iterator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using underlying_type = std::remove_reference_t<typename It::value_type::second_type>;
 | 
				
			||||||
 | 
					    using entity_type = typename underlying_type::entity_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    using value_type = typename std::iterator_traits<It>::value_type;
 | 
				
			||||||
 | 
					    using pointer = input_iterator_pointer<value_type>;
 | 
				
			||||||
 | 
					    using reference = value_type;
 | 
				
			||||||
 | 
					    using difference_type = std::ptrdiff_t;
 | 
				
			||||||
 | 
					    using iterator_category = std::input_iterator_tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr handle_storage_iterator() noexcept
 | 
				
			||||||
 | 
					        : entt{null},
 | 
				
			||||||
 | 
					          it{},
 | 
				
			||||||
 | 
					          last{} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr handle_storage_iterator(entity_type value, It from, It to) noexcept
 | 
				
			||||||
 | 
					        : entt{value},
 | 
				
			||||||
 | 
					          it{from},
 | 
				
			||||||
 | 
					          last{to} {
 | 
				
			||||||
 | 
					        while(it != last && !it->second.contains(entt)) {
 | 
				
			||||||
 | 
					            ++it;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr handle_storage_iterator &operator++() noexcept {
 | 
				
			||||||
 | 
					        while(++it != last && !it->second.contains(entt)) {}
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr handle_storage_iterator operator++(int) noexcept {
 | 
				
			||||||
 | 
					        handle_storage_iterator orig = *this;
 | 
				
			||||||
 | 
					        return ++(*this), orig;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr reference operator*() const noexcept {
 | 
				
			||||||
 | 
					        return *it;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [[nodiscard]] constexpr pointer operator->() const noexcept {
 | 
				
			||||||
 | 
					        return operator*();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename ILhs, typename IRhs>
 | 
				
			||||||
 | 
					    friend constexpr bool operator==(const handle_storage_iterator<ILhs> &, const handle_storage_iterator<IRhs> &) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    entity_type entt;
 | 
				
			||||||
 | 
					    It it;
 | 
				
			||||||
 | 
					    It last;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename ILhs, typename IRhs>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator==(const handle_storage_iterator<ILhs> &lhs, const handle_storage_iterator<IRhs> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return lhs.it == rhs.it;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename ILhs, typename IRhs>
 | 
				
			||||||
 | 
					[[nodiscard]] constexpr bool operator!=(const handle_storage_iterator<ILhs> &lhs, const handle_storage_iterator<IRhs> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return !(lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Internal details not to be documented.
 | 
				
			||||||
 | 
					 * @endcond
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Non-owning handle to an entity.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Tiny wrapper around a registry and an entity.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tparam Registry Basic registry type.
 | 
				
			||||||
 | 
					 * @tparam Scope Types to which to restrict the scope of a handle.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Registry, typename... Scope>
 | 
				
			||||||
 | 
					struct basic_handle {
 | 
				
			||||||
 | 
					    /*! @brief Type of registry accepted by the handle. */
 | 
				
			||||||
 | 
					    using registry_type = Registry;
 | 
				
			||||||
 | 
					    /*! @brief Underlying entity identifier. */
 | 
				
			||||||
 | 
					    using entity_type = typename registry_type::entity_type;
 | 
				
			||||||
 | 
					    /*! @brief Underlying version type. */
 | 
				
			||||||
 | 
					    using version_type = typename registry_type::version_type;
 | 
				
			||||||
 | 
					    /*! @brief Unsigned integer type. */
 | 
				
			||||||
 | 
					    using size_type = typename registry_type::size_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Constructs an invalid handle. */
 | 
				
			||||||
 | 
					    basic_handle() noexcept
 | 
				
			||||||
 | 
					        : reg{},
 | 
				
			||||||
 | 
					          entt{null} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a handle from a given registry and entity.
 | 
				
			||||||
 | 
					     * @param ref An instance of the registry class.
 | 
				
			||||||
 | 
					     * @param value A valid identifier.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    basic_handle(registry_type &ref, entity_type value) noexcept
 | 
				
			||||||
 | 
					        : reg{&ref},
 | 
				
			||||||
 | 
					          entt{value} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns an iterable object to use to _visit_ a handle.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * The iterable object returns a pair that contains the name and a reference
 | 
				
			||||||
 | 
					     * to the current storage.<br/>
 | 
				
			||||||
 | 
					     * Returned storage are those that contain the entity associated with the
 | 
				
			||||||
 | 
					     * handle.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return An iterable object to use to _visit_ the handle.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] auto storage() const noexcept {
 | 
				
			||||||
 | 
					        auto iterable = reg->storage();
 | 
				
			||||||
 | 
					        using iterator_type = internal::handle_storage_iterator<typename decltype(iterable)::iterator>;
 | 
				
			||||||
 | 
					        return iterable_adaptor{iterator_type{entt, iterable.begin(), iterable.end()}, iterator_type{entt, iterable.end(), iterable.end()}};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a const handle from a non-const one.
 | 
				
			||||||
 | 
					     * @tparam Other A valid entity type.
 | 
				
			||||||
 | 
					     * @tparam Args Scope of the handle to construct.
 | 
				
			||||||
 | 
					     * @return A const handle referring to the same registry and the same
 | 
				
			||||||
 | 
					     * entity.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Other, typename... Args>
 | 
				
			||||||
 | 
					    operator basic_handle<Other, Args...>() const noexcept {
 | 
				
			||||||
 | 
					        static_assert(std::is_same_v<Other, Registry> || std::is_same_v<std::remove_const_t<Other>, Registry>, "Invalid conversion between different handles");
 | 
				
			||||||
 | 
					        static_assert((sizeof...(Scope) == 0 || ((sizeof...(Args) != 0 && sizeof...(Args) <= sizeof...(Scope)) && ... && (type_list_contains_v<type_list<Scope...>, Args>))), "Invalid conversion between different handles");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return reg ? basic_handle<Other, Args...>{*reg, entt} : basic_handle<Other, Args...>{};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Converts a handle to its underlying entity.
 | 
				
			||||||
 | 
					     * @return The contained identifier.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] operator entity_type() const noexcept {
 | 
				
			||||||
 | 
					        return entity();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Checks if a handle refers to non-null registry pointer and entity.
 | 
				
			||||||
 | 
					     * @return True if the handle refers to non-null registry and entity, false otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] explicit operator bool() const noexcept {
 | 
				
			||||||
 | 
					        return reg && reg->valid(entt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Checks if a handle refers to a valid entity or not.
 | 
				
			||||||
 | 
					     * @return True if the handle refers to a valid entity, false otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] bool valid() const {
 | 
				
			||||||
 | 
					        return reg->valid(entt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns a pointer to the underlying registry, if any.
 | 
				
			||||||
 | 
					     * @return A pointer to the underlying registry, if any.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] registry_type *registry() const noexcept {
 | 
				
			||||||
 | 
					        return reg;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns the entity associated with a handle.
 | 
				
			||||||
 | 
					     * @return The entity associated with the handle.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] entity_type entity() const noexcept {
 | 
				
			||||||
 | 
					        return entt;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Destroys the entity associated with a handle. */
 | 
				
			||||||
 | 
					    void destroy() {
 | 
				
			||||||
 | 
					        reg->destroy(std::exchange(entt, null));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Destroys the entity associated with a handle.
 | 
				
			||||||
 | 
					     * @param version A desired version upon destruction.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void destroy(const version_type version) {
 | 
				
			||||||
 | 
					        reg->destroy(std::exchange(entt, null), version);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Assigns the given component to a handle.
 | 
				
			||||||
 | 
					     * @tparam Component Type of component to create.
 | 
				
			||||||
 | 
					     * @tparam Args Types of arguments to use to construct the component.
 | 
				
			||||||
 | 
					     * @param args Parameters to use to initialize the component.
 | 
				
			||||||
 | 
					     * @return A reference to the newly created component.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Component, typename... Args>
 | 
				
			||||||
 | 
					    decltype(auto) emplace(Args &&...args) const {
 | 
				
			||||||
 | 
					        static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Component, Scope>), "Invalid type");
 | 
				
			||||||
 | 
					        return reg->template emplace<Component>(entt, std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Assigns or replaces the given component for a handle.
 | 
				
			||||||
 | 
					     * @tparam Component Type of component to assign or replace.
 | 
				
			||||||
 | 
					     * @tparam Args Types of arguments to use to construct the component.
 | 
				
			||||||
 | 
					     * @param args Parameters to use to initialize the component.
 | 
				
			||||||
 | 
					     * @return A reference to the newly created component.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Component, typename... Args>
 | 
				
			||||||
 | 
					    decltype(auto) emplace_or_replace(Args &&...args) const {
 | 
				
			||||||
 | 
					        static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Component, Scope>), "Invalid type");
 | 
				
			||||||
 | 
					        return reg->template emplace_or_replace<Component>(entt, std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Patches the given component for a handle.
 | 
				
			||||||
 | 
					     * @tparam Component Type of component to patch.
 | 
				
			||||||
 | 
					     * @tparam Func Types of the function objects to invoke.
 | 
				
			||||||
 | 
					     * @param func Valid function objects.
 | 
				
			||||||
 | 
					     * @return A reference to the patched component.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Component, typename... Func>
 | 
				
			||||||
 | 
					    decltype(auto) patch(Func &&...func) const {
 | 
				
			||||||
 | 
					        static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Component, Scope>), "Invalid type");
 | 
				
			||||||
 | 
					        return reg->template patch<Component>(entt, std::forward<Func>(func)...);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Replaces the given component for a handle.
 | 
				
			||||||
 | 
					     * @tparam Component Type of component to replace.
 | 
				
			||||||
 | 
					     * @tparam Args Types of arguments to use to construct the component.
 | 
				
			||||||
 | 
					     * @param args Parameters to use to initialize the component.
 | 
				
			||||||
 | 
					     * @return A reference to the component being replaced.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Component, typename... Args>
 | 
				
			||||||
 | 
					    decltype(auto) replace(Args &&...args) const {
 | 
				
			||||||
 | 
					        static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Component, Scope>), "Invalid type");
 | 
				
			||||||
 | 
					        return reg->template replace<Component>(entt, std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Removes the given components from a handle.
 | 
				
			||||||
 | 
					     * @tparam Component Types of components to remove.
 | 
				
			||||||
 | 
					     * @return The number of components actually removed.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename... Component>
 | 
				
			||||||
 | 
					    size_type remove() const {
 | 
				
			||||||
 | 
					        static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Component> && ...), "Invalid type");
 | 
				
			||||||
 | 
					        return reg->template remove<Component...>(entt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Erases the given components from a handle.
 | 
				
			||||||
 | 
					     * @tparam Component Types of components to erase.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename... Component>
 | 
				
			||||||
 | 
					    void erase() const {
 | 
				
			||||||
 | 
					        static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Component> && ...), "Invalid type");
 | 
				
			||||||
 | 
					        reg->template erase<Component...>(entt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Checks if a handle has all the given components.
 | 
				
			||||||
 | 
					     * @tparam Component Components for which to perform the check.
 | 
				
			||||||
 | 
					     * @return True if the handle has all the components, false otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename... Component>
 | 
				
			||||||
 | 
					    [[nodiscard]] decltype(auto) all_of() const {
 | 
				
			||||||
 | 
					        return reg->template all_of<Component...>(entt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Checks if a handle has at least one of the given components.
 | 
				
			||||||
 | 
					     * @tparam Component Components for which to perform the check.
 | 
				
			||||||
 | 
					     * @return True if the handle has at least one of the given components,
 | 
				
			||||||
 | 
					     * false otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename... Component>
 | 
				
			||||||
 | 
					    [[nodiscard]] decltype(auto) any_of() const {
 | 
				
			||||||
 | 
					        return reg->template any_of<Component...>(entt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns references to the given components for a handle.
 | 
				
			||||||
 | 
					     * @tparam Component Types of components to get.
 | 
				
			||||||
 | 
					     * @return References to the components owned by the handle.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename... Component>
 | 
				
			||||||
 | 
					    [[nodiscard]] decltype(auto) get() const {
 | 
				
			||||||
 | 
					        static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Component> && ...), "Invalid type");
 | 
				
			||||||
 | 
					        return reg->template get<Component...>(entt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns a reference to the given component for a handle.
 | 
				
			||||||
 | 
					     * @tparam Component Type of component to get.
 | 
				
			||||||
 | 
					     * @tparam Args Types of arguments to use to construct the component.
 | 
				
			||||||
 | 
					     * @param args Parameters to use to initialize the component.
 | 
				
			||||||
 | 
					     * @return Reference to the component owned by the handle.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Component, typename... Args>
 | 
				
			||||||
 | 
					    [[nodiscard]] decltype(auto) get_or_emplace(Args &&...args) const {
 | 
				
			||||||
 | 
					        static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Component, Scope>), "Invalid type");
 | 
				
			||||||
 | 
					        return reg->template get_or_emplace<Component>(entt, std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns pointers to the given components for a handle.
 | 
				
			||||||
 | 
					     * @tparam Component Types of components to get.
 | 
				
			||||||
 | 
					     * @return Pointers to the components owned by the handle.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename... Component>
 | 
				
			||||||
 | 
					    [[nodiscard]] auto try_get() const {
 | 
				
			||||||
 | 
					        static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Component> && ...), "Invalid type");
 | 
				
			||||||
 | 
					        return reg->template try_get<Component...>(entt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Checks if a handle has components assigned.
 | 
				
			||||||
 | 
					     * @return True if the handle has no components assigned, false otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] bool orphan() const {
 | 
				
			||||||
 | 
					        return reg->orphan(entt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    registry_type *reg;
 | 
				
			||||||
 | 
					    entity_type entt;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares two handles.
 | 
				
			||||||
 | 
					 * @tparam Args Scope of the first handle.
 | 
				
			||||||
 | 
					 * @tparam Other Scope of the second handle.
 | 
				
			||||||
 | 
					 * @param lhs A valid handle.
 | 
				
			||||||
 | 
					 * @param rhs A valid handle.
 | 
				
			||||||
 | 
					 * @return True if both handles refer to the same registry and the same
 | 
				
			||||||
 | 
					 * entity, false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Args, typename... Other>
 | 
				
			||||||
 | 
					[[nodiscard]] bool operator==(const basic_handle<Args...> &lhs, const basic_handle<Other...> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return lhs.registry() == rhs.registry() && lhs.entity() == rhs.entity();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Compares two handles.
 | 
				
			||||||
 | 
					 * @tparam Args Scope of the first handle.
 | 
				
			||||||
 | 
					 * @tparam Other Scope of the second handle.
 | 
				
			||||||
 | 
					 * @param lhs A valid handle.
 | 
				
			||||||
 | 
					 * @param rhs A valid handle.
 | 
				
			||||||
 | 
					 * @return False if both handles refer to the same registry and the same
 | 
				
			||||||
 | 
					 * entity, true otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename... Args, typename... Other>
 | 
				
			||||||
 | 
					[[nodiscard]] bool operator!=(const basic_handle<Args...> &lhs, const basic_handle<Other...> &rhs) noexcept {
 | 
				
			||||||
 | 
					    return !(lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										258
									
								
								external/entt/entt/src/entt/entity/helper.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								external/entt/entt/src/entt/entity/helper.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,258 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_ENTITY_HELPER_HPP
 | 
				
			||||||
 | 
					#define ENTT_ENTITY_HELPER_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include "../core/fwd.hpp"
 | 
				
			||||||
 | 
					#include "../core/type_traits.hpp"
 | 
				
			||||||
 | 
					#include "../signal/delegate.hpp"
 | 
				
			||||||
 | 
					#include "fwd.hpp"
 | 
				
			||||||
 | 
					#include "group.hpp"
 | 
				
			||||||
 | 
					#include "view.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Converts a registry to a view.
 | 
				
			||||||
 | 
					 * @tparam Registry Basic registry type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Registry>
 | 
				
			||||||
 | 
					class as_view {
 | 
				
			||||||
 | 
					    template<typename... Get, typename... Exclude>
 | 
				
			||||||
 | 
					    auto dispatch(get_t<Get...>, exclude_t<Exclude...>) const {
 | 
				
			||||||
 | 
					        return reg.template view<constness_as_t<typename Get::value_type, Get>...>(exclude_t<constness_as_t<typename Exclude::value_type, Exclude>...>{});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /*! @brief Type of registry to convert. */
 | 
				
			||||||
 | 
					    using registry_type = Registry;
 | 
				
			||||||
 | 
					    /*! @brief Underlying entity identifier. */
 | 
				
			||||||
 | 
					    using entity_type = typename registry_type::entity_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a converter for a given registry.
 | 
				
			||||||
 | 
					     * @param source A valid reference to a registry.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    as_view(registry_type &source) noexcept
 | 
				
			||||||
 | 
					        : reg{source} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Conversion function from a registry to a view.
 | 
				
			||||||
 | 
					     * @tparam Get Type of storage used to construct the view.
 | 
				
			||||||
 | 
					     * @tparam Exclude Types of storage used to filter the view.
 | 
				
			||||||
 | 
					     * @return A newly created view.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Get, typename Exclude>
 | 
				
			||||||
 | 
					    operator basic_view<Get, Exclude>() const {
 | 
				
			||||||
 | 
					        return dispatch(Get{}, Exclude{});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    registry_type ®
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Converts a registry to a group.
 | 
				
			||||||
 | 
					 * @tparam Registry Basic registry type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Registry>
 | 
				
			||||||
 | 
					class as_group {
 | 
				
			||||||
 | 
					    template<typename... Owned, typename... Get, typename... Exclude>
 | 
				
			||||||
 | 
					    auto dispatch(owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>) const {
 | 
				
			||||||
 | 
					        if constexpr(std::is_const_v<registry_type>) {
 | 
				
			||||||
 | 
					            return reg.template group_if_exists<typename Owned::value_type...>(get_t<typename Get::value_type...>{}, exclude_t<typename Exclude::value_type...>{});
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return reg.template group<constness_as_t<typename Owned::value_type, Owned>...>(get_t<constness_as_t<typename Get::value_type, Get>...>{}, exclude_t<constness_as_t<typename Exclude::value_type, Exclude>...>{});
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /*! @brief Type of registry to convert. */
 | 
				
			||||||
 | 
					    using registry_type = Registry;
 | 
				
			||||||
 | 
					    /*! @brief Underlying entity identifier. */
 | 
				
			||||||
 | 
					    using entity_type = typename registry_type::entity_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a converter for a given registry.
 | 
				
			||||||
 | 
					     * @param source A valid reference to a registry.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    as_group(registry_type &source) noexcept
 | 
				
			||||||
 | 
					        : reg{source} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Conversion function from a registry to a group.
 | 
				
			||||||
 | 
					     * @tparam Owned Types of _owned_ by the group.
 | 
				
			||||||
 | 
					     * @tparam Get Types of storage _observed_ by the group.
 | 
				
			||||||
 | 
					     * @tparam Exclude Types of storage used to filter the group.
 | 
				
			||||||
 | 
					     * @return A newly created group.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Owned, typename Get, typename Exclude>
 | 
				
			||||||
 | 
					    operator basic_group<Owned, Get, Exclude>() const {
 | 
				
			||||||
 | 
					        return dispatch(Owned{}, Get{}, Exclude{});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    registry_type ®
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Helper to create a listener that directly invokes a member function.
 | 
				
			||||||
 | 
					 * @tparam Member Member function to invoke on a component of the given type.
 | 
				
			||||||
 | 
					 * @tparam Registry Basic registry type.
 | 
				
			||||||
 | 
					 * @param reg A registry that contains the given entity and its components.
 | 
				
			||||||
 | 
					 * @param entt Entity from which to get the component.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<auto Member, typename Registry = std::decay_t<nth_argument_t<0u, Member>>>
 | 
				
			||||||
 | 
					void invoke(Registry ®, const typename Registry::entity_type entt) {
 | 
				
			||||||
 | 
					    static_assert(std::is_member_function_pointer_v<decltype(Member)>, "Invalid pointer to non-static member function");
 | 
				
			||||||
 | 
					    delegate<void(Registry &, const typename Registry::entity_type)> func;
 | 
				
			||||||
 | 
					    func.template connect<Member>(reg.template get<member_class_t<decltype(Member)>>(entt));
 | 
				
			||||||
 | 
					    func(reg, entt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Returns the entity associated with a given component.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @warning
 | 
				
			||||||
 | 
					 * Currently, this function only works correctly with the default pool as it
 | 
				
			||||||
 | 
					 * makes assumptions about how the components are laid out.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tparam Registry Basic registry type.
 | 
				
			||||||
 | 
					 * @tparam Component Type of component.
 | 
				
			||||||
 | 
					 * @param reg A registry that contains the given entity and its components.
 | 
				
			||||||
 | 
					 * @param instance A valid component instance.
 | 
				
			||||||
 | 
					 * @return The entity associated with the given component.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Registry, typename Component>
 | 
				
			||||||
 | 
					typename Registry::entity_type to_entity(const Registry ®, const Component &instance) {
 | 
				
			||||||
 | 
					    if(const auto *storage = reg.template storage<Component>(); storage) {
 | 
				
			||||||
 | 
					        constexpr auto page_size = std::remove_const_t<std::remove_pointer_t<decltype(storage)>>::traits_type::page_size;
 | 
				
			||||||
 | 
					        const typename Registry::common_type &base = *storage;
 | 
				
			||||||
 | 
					        const auto *addr = std::addressof(instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for(auto it = base.rbegin(), last = base.rend(); it < last; it += page_size) {
 | 
				
			||||||
 | 
					            if(const auto dist = (addr - std::addressof(storage->get(*it))); dist >= 0 && dist < static_cast<decltype(dist)>(page_size)) {
 | 
				
			||||||
 | 
					                return *(it + dist);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Primary template isn't defined on purpose. */
 | 
				
			||||||
 | 
					template<typename...>
 | 
				
			||||||
 | 
					struct sigh_helper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Signal connection helper for registries.
 | 
				
			||||||
 | 
					 * @tparam Registry Basic registry type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Registry>
 | 
				
			||||||
 | 
					struct sigh_helper<Registry> {
 | 
				
			||||||
 | 
					    /*! @brief Registry type. */
 | 
				
			||||||
 | 
					    using registry_type = Registry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a helper for a given registry.
 | 
				
			||||||
 | 
					     * @param ref A valid reference to a registry.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    sigh_helper(registry_type &ref)
 | 
				
			||||||
 | 
					        : bucket{&ref} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Binds a properly initialized helper to a given signal type.
 | 
				
			||||||
 | 
					     * @tparam Type Type of signal to bind the helper to.
 | 
				
			||||||
 | 
					     * @param id Optional name for the underlying storage to use.
 | 
				
			||||||
 | 
					     * @return A helper for a given registry and signal type.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename Type>
 | 
				
			||||||
 | 
					    auto with(const id_type id = type_hash<Type>::value()) noexcept {
 | 
				
			||||||
 | 
					        return sigh_helper<registry_type, Type>{*bucket, id};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns a reference to the underlying registry.
 | 
				
			||||||
 | 
					     * @return A reference to the underlying registry.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] registry_type ®istry() noexcept {
 | 
				
			||||||
 | 
					        return *bucket;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    registry_type *bucket;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Signal connection helper for registries.
 | 
				
			||||||
 | 
					 * @tparam Registry Basic registry type.
 | 
				
			||||||
 | 
					 * @tparam Type Type of signal to connect listeners to.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Registry, typename Type>
 | 
				
			||||||
 | 
					struct sigh_helper<Registry, Type> final: sigh_helper<Registry> {
 | 
				
			||||||
 | 
					    /*! @brief Registry type. */
 | 
				
			||||||
 | 
					    using registry_type = Registry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs a helper for a given registry.
 | 
				
			||||||
 | 
					     * @param ref A valid reference to a registry.
 | 
				
			||||||
 | 
					     * @param id Optional name for the underlying storage to use.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    sigh_helper(registry_type &ref, const id_type id = type_hash<Type>::value())
 | 
				
			||||||
 | 
					        : sigh_helper<Registry>{ref},
 | 
				
			||||||
 | 
					          name{id} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Forwards the call to `on_construct` on the underlying storage.
 | 
				
			||||||
 | 
					     * @tparam Candidate Function or member to connect.
 | 
				
			||||||
 | 
					     * @tparam Args Type of class or type of payload, if any.
 | 
				
			||||||
 | 
					     * @param args A valid object that fits the purpose, if any.
 | 
				
			||||||
 | 
					     * @return This helper.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<auto Candidate, typename... Args>
 | 
				
			||||||
 | 
					    auto on_construct(Args &&...args) {
 | 
				
			||||||
 | 
					        this->registry().template on_construct<Type>(name).template connect<Candidate>(std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Forwards the call to `on_update` on the underlying storage.
 | 
				
			||||||
 | 
					     * @tparam Candidate Function or member to connect.
 | 
				
			||||||
 | 
					     * @tparam Args Type of class or type of payload, if any.
 | 
				
			||||||
 | 
					     * @param args A valid object that fits the purpose, if any.
 | 
				
			||||||
 | 
					     * @return This helper.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<auto Candidate, typename... Args>
 | 
				
			||||||
 | 
					    auto on_update(Args &&...args) {
 | 
				
			||||||
 | 
					        this->registry().template on_update<Type>(name).template connect<Candidate>(std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Forwards the call to `on_destroy` on the underlying storage.
 | 
				
			||||||
 | 
					     * @tparam Candidate Function or member to connect.
 | 
				
			||||||
 | 
					     * @tparam Args Type of class or type of payload, if any.
 | 
				
			||||||
 | 
					     * @param args A valid object that fits the purpose, if any.
 | 
				
			||||||
 | 
					     * @return This helper.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<auto Candidate, typename... Args>
 | 
				
			||||||
 | 
					    auto on_destroy(Args &&...args) {
 | 
				
			||||||
 | 
					        this->registry().template on_destroy<Type>(name).template connect<Candidate>(std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    id_type name;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Deduction guide.
 | 
				
			||||||
 | 
					 * @tparam Registry Basic registry type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Registry>
 | 
				
			||||||
 | 
					sigh_helper(Registry &) -> sigh_helper<Registry>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										293
									
								
								external/entt/entt/src/entt/entity/mixin.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								external/entt/entt/src/entt/entity/mixin.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,293 @@
 | 
				
			|||||||
 | 
					#ifndef ENTT_ENTITY_MIXIN_HPP
 | 
				
			||||||
 | 
					#define ENTT_ENTITY_MIXIN_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include "../config/config.h"
 | 
				
			||||||
 | 
					#include "../core/any.hpp"
 | 
				
			||||||
 | 
					#include "../signal/sigh.hpp"
 | 
				
			||||||
 | 
					#include "entity.hpp"
 | 
				
			||||||
 | 
					#include "fwd.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace entt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Mixin type used to add signal support to storage types.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The function type of a listener is equivalent to:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @code{.cpp}
 | 
				
			||||||
 | 
					 * void(basic_registry<entity_type> &, entity_type);
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This applies to all signals made available.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tparam Type The type of the underlying storage.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename Type>
 | 
				
			||||||
 | 
					class sigh_mixin final: public Type {
 | 
				
			||||||
 | 
					    using underlying_type = Type;
 | 
				
			||||||
 | 
					    using basic_registry_type = basic_registry<typename underlying_type::entity_type, typename underlying_type::base_type::allocator_type>;
 | 
				
			||||||
 | 
					    using sigh_type = sigh<void(basic_registry_type &, const typename underlying_type::entity_type), typename underlying_type::allocator_type>;
 | 
				
			||||||
 | 
					    using underlying_iterator = typename underlying_type::base_type::basic_iterator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    basic_registry_type &owner_or_assert() const noexcept {
 | 
				
			||||||
 | 
					        ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
 | 
				
			||||||
 | 
					        return *owner;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void pop(underlying_iterator first, underlying_iterator last) final {
 | 
				
			||||||
 | 
					        if(auto ® = owner_or_assert(); destruction.empty()) {
 | 
				
			||||||
 | 
					            underlying_type::pop(first, last);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            for(; first != last; ++first) {
 | 
				
			||||||
 | 
					                const auto entt = *first;
 | 
				
			||||||
 | 
					                destruction.publish(reg, entt);
 | 
				
			||||||
 | 
					                const auto it = underlying_type::find(entt);
 | 
				
			||||||
 | 
					                underlying_type::pop(it, it + 1u);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void pop_all() final {
 | 
				
			||||||
 | 
					        if(auto ® = owner_or_assert(); !destruction.empty()) {
 | 
				
			||||||
 | 
					            for(auto pos = underlying_type::each().begin().base().index(); !(pos < 0); --pos) {
 | 
				
			||||||
 | 
					                if constexpr(underlying_type::traits_type::in_place_delete) {
 | 
				
			||||||
 | 
					                    if(const auto entt = underlying_type::operator[](static_cast<typename underlying_type::size_type>(pos)); entt != tombstone) {
 | 
				
			||||||
 | 
					                        destruction.publish(reg, entt);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    destruction.publish(reg, underlying_type::operator[](static_cast<typename underlying_type::size_type>(pos)));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        underlying_type::pop_all();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    underlying_iterator try_emplace(const typename underlying_type::entity_type entt, const bool force_back, const void *value) final {
 | 
				
			||||||
 | 
					        const auto it = underlying_type::try_emplace(entt, force_back, value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(auto ® = owner_or_assert(); it != underlying_type::base_type::end()) {
 | 
				
			||||||
 | 
					            construction.publish(reg, *it);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return it;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /*! @brief Allocator type. */
 | 
				
			||||||
 | 
					    using allocator_type = typename underlying_type::allocator_type;
 | 
				
			||||||
 | 
					    /*! @brief Underlying entity identifier. */
 | 
				
			||||||
 | 
					    using entity_type = typename underlying_type::entity_type;
 | 
				
			||||||
 | 
					    /*! @brief Expected registry type. */
 | 
				
			||||||
 | 
					    using registry_type = basic_registry_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*! @brief Default constructor. */
 | 
				
			||||||
 | 
					    sigh_mixin()
 | 
				
			||||||
 | 
					        : sigh_mixin{allocator_type{}} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Constructs an empty storage with a given allocator.
 | 
				
			||||||
 | 
					     * @param allocator The allocator to use.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    explicit sigh_mixin(const allocator_type &allocator)
 | 
				
			||||||
 | 
					        : underlying_type{allocator},
 | 
				
			||||||
 | 
					          owner{},
 | 
				
			||||||
 | 
					          construction{allocator},
 | 
				
			||||||
 | 
					          destruction{allocator},
 | 
				
			||||||
 | 
					          update{allocator} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Move constructor.
 | 
				
			||||||
 | 
					     * @param other The instance to move from.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    sigh_mixin(sigh_mixin &&other) noexcept
 | 
				
			||||||
 | 
					        : underlying_type{std::move(other)},
 | 
				
			||||||
 | 
					          owner{other.owner},
 | 
				
			||||||
 | 
					          construction{std::move(other.construction)},
 | 
				
			||||||
 | 
					          destruction{std::move(other.destruction)},
 | 
				
			||||||
 | 
					          update{std::move(other.update)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Allocator-extended move constructor.
 | 
				
			||||||
 | 
					     * @param other The instance to move from.
 | 
				
			||||||
 | 
					     * @param allocator The allocator to use.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    sigh_mixin(sigh_mixin &&other, const allocator_type &allocator) noexcept
 | 
				
			||||||
 | 
					        : underlying_type{std::move(other), allocator},
 | 
				
			||||||
 | 
					          owner{other.owner},
 | 
				
			||||||
 | 
					          construction{std::move(other.construction), allocator},
 | 
				
			||||||
 | 
					          destruction{std::move(other.destruction), allocator},
 | 
				
			||||||
 | 
					          update{std::move(other.update), allocator} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Move assignment operator.
 | 
				
			||||||
 | 
					     * @param other The instance to move from.
 | 
				
			||||||
 | 
					     * @return This storage.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    sigh_mixin &operator=(sigh_mixin &&other) noexcept {
 | 
				
			||||||
 | 
					        underlying_type::operator=(std::move(other));
 | 
				
			||||||
 | 
					        owner = other.owner;
 | 
				
			||||||
 | 
					        construction = std::move(other.construction);
 | 
				
			||||||
 | 
					        destruction = std::move(other.destruction);
 | 
				
			||||||
 | 
					        update = std::move(other.update);
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Exchanges the contents with those of a given storage.
 | 
				
			||||||
 | 
					     * @param other Storage to exchange the content with.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void swap(sigh_mixin &other) {
 | 
				
			||||||
 | 
					        using std::swap;
 | 
				
			||||||
 | 
					        underlying_type::swap(other);
 | 
				
			||||||
 | 
					        swap(owner, other.owner);
 | 
				
			||||||
 | 
					        swap(construction, other.construction);
 | 
				
			||||||
 | 
					        swap(destruction, other.destruction);
 | 
				
			||||||
 | 
					        swap(update, other.update);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns a sink object.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * The sink returned by this function can be used to receive notifications
 | 
				
			||||||
 | 
					     * whenever a new instance is created and assigned to an entity.<br/>
 | 
				
			||||||
 | 
					     * Listeners are invoked after the object has been assigned to the entity.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @sa sink
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return A temporary sink object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] auto on_construct() noexcept {
 | 
				
			||||||
 | 
					        return sink{construction};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns a sink object.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * The sink returned by this function can be used to receive notifications
 | 
				
			||||||
 | 
					     * whenever an instance is explicitly updated.<br/>
 | 
				
			||||||
 | 
					     * Listeners are invoked after the object has been updated.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @sa sink
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return A temporary sink object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] auto on_update() noexcept {
 | 
				
			||||||
 | 
					        return sink{update};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Returns a sink object.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * The sink returned by this function can be used to receive notifications
 | 
				
			||||||
 | 
					     * whenever an instance is removed from an entity and thus destroyed.<br/>
 | 
				
			||||||
 | 
					     * Listeners are invoked before the object has been removed from the entity.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @sa sink
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return A temporary sink object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    [[nodiscard]] auto on_destroy() noexcept {
 | 
				
			||||||
 | 
					        return sink{destruction};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Emplace elements into a storage.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * The behavior of this operation depends on the underlying storage type
 | 
				
			||||||
 | 
					     * (for example, components vs entities).<br/>
 | 
				
			||||||
 | 
					     * Refer to the specific documentation for more details.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return A return value as returned by the underlying storage.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    auto emplace() {
 | 
				
			||||||
 | 
					        const auto entt = underlying_type::emplace();
 | 
				
			||||||
 | 
					        construction.publish(owner_or_assert(), entt);
 | 
				
			||||||
 | 
					        return entt;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Emplace elements into a storage.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * The behavior of this operation depends on the underlying storage type
 | 
				
			||||||
 | 
					     * (for example, components vs entities).<br/>
 | 
				
			||||||
 | 
					     * Refer to the specific documentation for more details.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @tparam Args Types of arguments to forward to the underlying storage.
 | 
				
			||||||
 | 
					     * @param hint A valid identifier.
 | 
				
			||||||
 | 
					     * @param args Parameters to forward to the underlying storage.
 | 
				
			||||||
 | 
					     * @return A return value as returned by the underlying storage.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename... Args>
 | 
				
			||||||
 | 
					    decltype(auto) emplace(const entity_type hint, Args &&...args) {
 | 
				
			||||||
 | 
					        if constexpr(std::is_same_v<typename underlying_type::value_type, typename underlying_type::entity_type>) {
 | 
				
			||||||
 | 
					            const auto entt = underlying_type::emplace(hint, std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					            construction.publish(owner_or_assert(), entt);
 | 
				
			||||||
 | 
					            return entt;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            underlying_type::emplace(hint, std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					            construction.publish(owner_or_assert(), hint);
 | 
				
			||||||
 | 
					            return this->get(hint);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Patches the given instance for an entity.
 | 
				
			||||||
 | 
					     * @tparam Func Types of the function objects to invoke.
 | 
				
			||||||
 | 
					     * @param entt A valid identifier.
 | 
				
			||||||
 | 
					     * @param func Valid function objects.
 | 
				
			||||||
 | 
					     * @return A reference to the patched instance.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename... Func>
 | 
				
			||||||
 | 
					    decltype(auto) patch(const entity_type entt, Func &&...func) {
 | 
				
			||||||
 | 
					        underlying_type::patch(entt, std::forward<Func>(func)...);
 | 
				
			||||||
 | 
					        update.publish(owner_or_assert(), entt);
 | 
				
			||||||
 | 
					        return this->get(entt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Emplace elements into a storage.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * The behavior of this operation depends on the underlying storage type
 | 
				
			||||||
 | 
					     * (for example, components vs entities).<br/>
 | 
				
			||||||
 | 
					     * Refer to the specific documentation for more details.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @tparam It Iterator type (as required by the underlying storage type).
 | 
				
			||||||
 | 
					     * @tparam Args Types of arguments to forward to the underlying storage.
 | 
				
			||||||
 | 
					     * @param first An iterator to the first element of the range.
 | 
				
			||||||
 | 
					     * @param last An iterator past the last element of the range.
 | 
				
			||||||
 | 
					     * @param args Parameters to use to forward to the underlying storage.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    template<typename It, typename... Args>
 | 
				
			||||||
 | 
					    void insert(It first, It last, Args &&...args) {
 | 
				
			||||||
 | 
					        underlying_type::insert(first, last, std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(auto ® = owner_or_assert(); !construction.empty()) {
 | 
				
			||||||
 | 
					            for(; first != last; ++first) {
 | 
				
			||||||
 | 
					                construction.publish(reg, *first);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief Forwards variables to derived classes, if any.
 | 
				
			||||||
 | 
					     * @param value A variable wrapped in an opaque container.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void bind(any value) noexcept final {
 | 
				
			||||||
 | 
					        auto *reg = any_cast<basic_registry_type>(&value);
 | 
				
			||||||
 | 
					        owner = reg ? reg : owner;
 | 
				
			||||||
 | 
					        underlying_type::bind(std::move(value));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    basic_registry_type *owner;
 | 
				
			||||||
 | 
					    sigh_type construction;
 | 
				
			||||||
 | 
					    sigh_type destruction;
 | 
				
			||||||
 | 
					    sigh_type update;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace entt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user