Merge branch 'development' into feature/add-time-date-classes

# Conflicts:
#	.gitignore
#	include/etl/platform.h
#	include/etl/ratio.h
#	test/CMakeLists.txt
#	test/test_ratio.cpp
#	test/vs2022/etl.vcxproj
#	test/vs2022/etl.vcxproj.filters
This commit is contained in:
John Wellbelove 2025-04-19 12:30:36 +01:00
commit fedf429d02
265 changed files with 38540 additions and 12825 deletions

View File

@ -15,7 +15,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
@ -37,7 +37,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |

View File

@ -15,7 +15,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
@ -37,7 +37,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |

View File

@ -15,7 +15,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
@ -37,7 +37,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |

View File

@ -15,7 +15,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
# Temporary fix. See https://github.com/actions/runner-images/issues/8659
- name: Install newer Clang
@ -44,7 +44,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
# Temporary fix. See https://github.com/actions/runner-images/issues/8659
- name: Install newer Clang
@ -73,7 +73,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
# Temporary fix. See https://github.com/actions/runner-images/issues/8659
- name: Install newer Clang
@ -99,10 +99,10 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-12]
os: [macos-13]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
@ -121,10 +121,10 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-12]
os: [macos-13]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
@ -143,10 +143,10 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-12]
os: [macos-13]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
@ -165,10 +165,10 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-12]
os: [macos-13]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |

View File

@ -14,13 +14,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++03
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -32,13 +32,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++03
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -50,13 +50,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++11
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -68,13 +68,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++11
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -86,13 +86,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++11
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -104,13 +104,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++11
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -122,13 +122,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++14
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -140,13 +140,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++14
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -158,13 +158,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++14
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -176,13 +176,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++14
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -194,13 +194,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++17
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -212,13 +212,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++17
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -230,13 +230,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++17
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -248,13 +248,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++17
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -266,13 +266,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++20
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -284,13 +284,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++20
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -302,13 +302,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++20
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -320,12 +320,12 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=clang
export CXX=clang++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++20
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
clang --version
make -j $(getconf _NPROCESSORS_ONLN)

View File

@ -15,7 +15,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
@ -38,7 +38,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |

View File

@ -15,7 +15,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
@ -37,7 +37,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |

View File

@ -15,7 +15,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
@ -37,7 +37,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |

View File

@ -15,7 +15,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
@ -37,7 +37,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
@ -59,7 +59,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
@ -81,7 +81,7 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |

View File

@ -14,13 +14,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++03
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -32,13 +32,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++03
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -50,13 +50,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++11
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -68,13 +68,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++11
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -86,13 +86,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++11
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -104,13 +104,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++11
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -122,13 +122,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++14
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -140,13 +140,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++14
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -158,13 +158,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++14
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -176,13 +176,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++14
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -194,13 +194,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++17
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -212,13 +212,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++17
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -230,13 +230,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++17
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -248,13 +248,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++17
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -266,13 +266,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++20
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -284,13 +284,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check/c++20
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -302,13 +302,13 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++20
cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -320,12 +320,12 @@ jobs:
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build
run: |
export CC=gcc
export CXX=g++
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check/c++20
cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON ./test/syntax_check
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)

View File

@ -12,7 +12,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
@ -33,7 +33,7 @@ jobs:
runs-on: [windows-2022]
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
@ -55,7 +55,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
@ -77,7 +77,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive

9
.gitignore vendored
View File

@ -388,6 +388,15 @@ support/time remaining test.xlsx
test/vs2022/Debug MSVC C++20 - Force C++03
test/vs2022/Release MSVC C++20 - No STL - Optimised -O2 - Sanitiser
test/test_file_list.txt
examples/QueuedMessageRouter/vs2022/.vs/QueuedMessageRouter/CopilotIndices
examples/QueuedMessageRouter/vs2022/.vs/QueuedMessageRouter/FileContentIndex
examples/QueuedMessageRouter/vs2022/.vs/QueuedMessageRouter/v17
test/etl_error_handler/assert_errors/build-make
test/etl_error_handler/assert_function/build-make
test/syntax_check/bgcc
test/syntax_check/bclang
test/vs2022/Debug Clang C++20
test/vs2022/Debug MSVC C++20 - Forve C++03 - No virtual messages
test/reflog.txt
test/etl_error_handler/assert_function/build-make
test/syntax_check/bgcc

13
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,13 @@
# How to contribute
If your are considering creating a pull request, please observe the following:
- If you are adding or modifying a feature, add *new* unit tests that test that feature.
- If you are fixing a bug, add a unit test that *fails* before the bug fix is implemented.
- Do not initiate a pull request until all of the units tests pass.
- Branches should be based on the branch `master`.
There is a project file for VS2022 for C++14, 17, 20, and bash scripts that run the tests for C++11, 14, 17, 20 under Linux with GCC and Clang.
If you are thinking of adding a new feature then raise this on the GitHub Issues page for disccussion as the maintainers and user of the ETL may have questions or suggestions.
It is possible that the maintainer of the ETL or another contributor is already working on the same or related feature.

View File

@ -69,7 +69,7 @@ The library is intended for any compiler that supports C++98/03/11/14/17/20.
- Checksums & hash functions
- Variants (a type that can store many types in a type-safe interface)
- Choice of asserts, exceptions, error handler or no checks on errors
- Unit tested (currently over 6480 tests), using VS2019, GCC 8.1.0, , GCC 9.3.0, Clang 9.0.0 & 10.0.0
- Unit tested (currently over 9400 tests), using VS2022, GCC 12, Clang 14.
- Many utilities for template support.
- Easy to read and documented source.
- Free support via email, GitHub and Slack

View File

@ -16,11 +16,5 @@ install:
build:
project: test/vs2022/etl.vcxproj
verbosity: minimal
notifications:
- provider: Webhook
url: https://hooks.slack.com/services/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
method: POST
on_build_success: true
on_build_failure: true
on_build_status_changed: true

View File

@ -1,6 +1,6 @@
{
"name": "Embedded Template Library ETL",
"version": "20.39.0",
"version": "20.40.0",
"authors": {
"name": "John Wellbelove",
"email": "john.wellbelove@etlcpp.com"

View File

@ -1,5 +1,5 @@
name=Embedded Template Library ETL
version=20.39.0
version=20.40.0
author= John Wellbelove <john.wellbelove@etlcpp.com>
maintainer=John Wellbelove <john.wellbelove@etlcpp.com>
license=MIT

View File

@ -13,7 +13,7 @@ function(determine_version_with_git)
git_describe(VERSION ${ARGN})
string(FIND ${VERSION} "." VALID_VERSION)
if(VALID_VERSION EQUAL -1)
if(PROJECT_IS_TOP_LEVEL)
if(CMAKE_CURRENT_LIST_DIR STREQUAL PROJECT_SOURCE_DIR)
# only warn if this is the top-level project, since we may be
# building from a tarball as a subproject
message(WARNING "Version string ${VERSION} retrieved with git describe is invalid")

View File

@ -52,8 +52,6 @@ public:
typedef etl::message_router<Router, Message1, Message2, Message3> Base_t;
using Base_t::receive;
//***************************************************************************
Router()
: message_router(1)

View File

@ -29,26 +29,26 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>

View File

@ -1449,16 +1449,20 @@ namespace etl
TCompare compare)
{
TIterator minimum = begin;
++begin;
while (begin != end)
if (begin != end)
{
if (compare(*begin, *minimum))
{
minimum = begin;
}
++begin;
while (begin != end)
{
if (compare(*begin, *minimum))
{
minimum = begin;
}
++begin;
}
}
return minimum;
@ -1493,16 +1497,20 @@ namespace etl
TCompare compare)
{
TIterator maximum = begin;
++begin;
while (begin != end)
if (begin != end)
{
if (!compare(*begin, *maximum))
{
maximum = begin;
}
++begin;
while (begin != end)
{
if (!compare(*begin, *maximum))
{
maximum = begin;
}
++begin;
}
}
return maximum;
@ -1538,21 +1546,25 @@ namespace etl
{
TIterator minimum = begin;
TIterator maximum = begin;
++begin;
while (begin != end)
if (begin != end)
{
if (compare(*begin, *minimum))
{
minimum = begin;
}
if (compare(*maximum, *begin))
{
maximum = begin;
}
++begin;
while (begin != end)
{
if (compare(*begin, *minimum))
{
minimum = begin;
}
if (compare(*maximum, *begin))
{
maximum = begin;
}
++begin;
}
}
return ETL_OR_STD::pair<TIterator, TIterator>(minimum, maximum);

View File

@ -36,6 +36,7 @@ SOFTWARE.
#include "static_assert.h"
#include "error_handler.h"
#include "exception.h"
#include "utility.h"
#include <stdint.h>
@ -71,6 +72,19 @@ namespace etl
}
};
//***************************************************************************
/// Typed storage exception.
//***************************************************************************
class typed_storage_error : public alignment_exception
{
public:
typed_storage_error(string_type file_name_, numeric_type line_number_)
: alignment_exception(ETL_ERROR_TEXT("typed_storage:error", ETL_ALIGNMENT_FILE_ID"B"), file_name_, line_number_)
{
}
};
//*****************************************************************************
/// Check that 'p' has 'required_alignment'.
//*****************************************************************************
@ -334,6 +348,167 @@ namespace etl
template <size_t Length, typename T>
using aligned_storage_as_t = typename aligned_storage_as<Length, T>::type;
#endif
//***************************************************************************
/// Wrapper class that provides a memory area and lets the user create an
/// instance of T in this memory at runtime. This class also erases the
/// destructor call of T, i.e. if typed_storage goes out of scope, the
/// destructor if the wrapped type will not be called. This can be done
/// explicitly by calling destroy().
/// \tparam T Type of element stored in this instance of typed_storage.
//***************************************************************************
template <typename T>
class typed_storage
{
public:
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef T* pointer;
typedef const T* const_pointer;
// Constructor
typed_storage()
: valid(false)
{
}
//***************************************************************************
/// Default destructor which will NOT call the destructor of the object which
/// was created by calling create().
//***************************************************************************
~typed_storage() = default;
//***************************************************************************
/// Calls the destructor of the wrapped object and asserts if has_value() is false.
//***************************************************************************
void destroy()
{
ETL_ASSERT(has_value(), ETL_ERROR(etl::typed_storage_error));
data.template get_reference<T>().~T();
valid = false;
}
//***************************************************************************
/// \returns <b>true</b> if object has been constructed using create().
/// \returns <b>false</b> otherwise.
//***************************************************************************
bool has_value() const
{
return valid;
}
#if ETL_USING_CPP11
//***************************************************************************
/// Constructs the instance of T forwarding the given \p args to its constructor and
/// asserts if has_value() is false.
///
/// \returns the instance of T which has been constructed in the internal byte array.
//***************************************************************************
template<typename... Args>
reference create(Args&&... args)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
valid = true;
return *::new (data.template get_address<char>()) value_type(etl::forward<Args>(args)...);
}
#else
//***************************************************************************
/// Constructs the instance of T with type T1
/// asserts if has_value() is false.
///
/// \returns the instance of T which has been constructed in the internal byte array.
//***************************************************************************
template<typename T1>
reference create(const T1& t1)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
valid = true;
return *::new (data.template get_address<char>()) value_type(t1);
}
//***************************************************************************
/// Constructs the instance of T with types T1, T2
/// asserts if has_value() is false.
///
/// \returns the instance of T which has been constructed in the internal byte array.
//***************************************************************************
template<typename T1, typename T2>
reference create(const T1& t1, const T2& t2)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
valid = true;
return *::new (data.template get_address<char>()) value_type(t1, t2);
}
//***************************************************************************
/// Constructs the instance of T with types T1, T2, T3
/// asserts if has_value() is false.
///
/// \returns the instance of T which has been constructed in the internal byte array.
//***************************************************************************
template<typename T1, typename T2, typename T3>
reference create(const T1& t1, const T2& t2, const T3& t3)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
valid = true;
return *::new (data.template get_address<char>()) value_type(t1, t2, t3);
}
//***************************************************************************
/// Constructs the instance of T with types T1, T2, T3, T4
/// asserts if has_value() is false.
///
/// \returns the instance of T which has been constructed in the internal byte array.
//***************************************************************************
template<typename T1, typename T2, typename T3, typename T4>
reference create(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
valid = true;
return *::new (data.template get_address<char>()) value_type(t1, t2, t3, t4);
}
#endif
//***************************************************************************
/// \returns a pointer of type T and asserts if has_value() is false.
//***************************************************************************
pointer operator->()
{
ETL_ASSERT(has_value(), ETL_ERROR(etl::typed_storage_error));
return data.template get_address<value_type>();
}
//***************************************************************************
/// \returns a const pointer of type T and asserts if has_value() is false.
//***************************************************************************
const_pointer operator->() const
{
return operator->();
}
//***************************************************************************
/// \returns reference of type T and asserts if has_value() is false.
//***************************************************************************
reference operator*()
{
return *operator->();
}
//***************************************************************************
/// \returns const reference of type T and asserts if has_value() is false.
//***************************************************************************
const_reference operator*() const
{
return *operator->();
}
private:
typename aligned_storage_as<sizeof(value_type), value_type>::type data;
bool valid;
};
}
#endif

View File

@ -239,19 +239,19 @@ namespace etl
//*************************************************************************
template <typename TIterator>
ETL_CONSTEXPR array_view(const TIterator begin_, const TIterator end_)
: mbegin(etl::addressof(*begin_)),
mend(etl::addressof(*begin_) + etl::distance(begin_, end_))
: mbegin(etl::to_address(begin_)),
mend(etl::to_address(begin_) + etl::distance(begin_, end_))
{
}
//*************************************************************************
/// Construct from C array
/// Construct from iterator and size
//*************************************************************************
template <typename TIterator,
typename TSize>
ETL_CONSTEXPR array_view(const TIterator begin_, const TSize size_)
: mbegin(etl::addressof(*begin_)),
mend(etl::addressof(*begin_) + size_)
: mbegin(etl::to_address(begin_)),
mend(etl::to_address(begin_) + size_)
{
}
@ -458,8 +458,8 @@ namespace etl
template <typename TIterator>
void assign(const TIterator begin_, const TIterator end_)
{
mbegin = etl::addressof(*begin_);
mend = etl::addressof(*begin_) + etl::distance(begin_, end_);
mbegin = etl::to_address(begin_);
mend = etl::to_address(begin_) + etl::distance(begin_, end_);
}
//*************************************************************************
@ -469,8 +469,8 @@ namespace etl
typename TSize>
void assign(const TIterator begin_, const TSize size_)
{
mbegin = etl::addressof(*begin_);
mend = etl::addressof(*begin_) + size_;
mbegin = etl::to_address(begin_);
mend = etl::to_address(begin_) + size_;
}
#if defined(ETL_ARRAY_VIEW_IS_MUTABLE)

View File

@ -83,7 +83,7 @@ namespace etl
// Only integral and pointer types are supported.
//***************************************************************************
enum memory_order
typedef enum memory_order
{
memory_order_relaxed = __ATOMIC_RELAXED,
memory_order_consume = __ATOMIC_CONSUME,
@ -91,13 +91,22 @@ namespace etl
memory_order_release = __ATOMIC_RELEASE,
memory_order_acq_rel = __ATOMIC_ACQ_REL,
memory_order_seq_cst = __ATOMIC_SEQ_CST
} memory_order;
template <bool Is_Always_Lock_Free>
struct atomic_traits
{
static ETL_CONSTANT bool is_always_lock_free = Is_Always_Lock_Free;
};
template <bool Is_Always_Lock_Free>
ETL_CONSTANT bool atomic_traits<Is_Always_Lock_Free>::is_always_lock_free;
//***************************************************************************
/// For all types except bool, pointers and types that are always lock free.
//***************************************************************************
template <typename T, bool integral_type = etl::is_integral<T>::value>
class atomic
class atomic : public atomic_traits<integral_type>
{
public:
@ -389,7 +398,7 @@ namespace etl
/// Specialisation for pointers
//***************************************************************************
template <typename T>
class atomic<T*, false>
class atomic<T*, false> : public atomic_traits<true>
{
public:
@ -631,7 +640,7 @@ namespace etl
/// Specialisation for bool
//***************************************************************************
template <>
class atomic<bool, true>
class atomic<bool, true> : public atomic_traits<true>
{
public:
@ -794,7 +803,7 @@ namespace etl
/// Uses a mutex to control access.
//***************************************************************************
template <typename T>
class atomic<T, false>
class atomic<T, false> : public atomic_traits<false>
{
public:
@ -1030,11 +1039,20 @@ namespace etl
memory_order_seq_cst
} memory_order;
template <bool Is_Always_Lock_Free>
struct atomic_traits
{
static ETL_CONSTANT bool is_always_lock_free = Is_Always_Lock_Free;
};
template <bool Is_Always_Lock_Free>
ETL_CONSTANT bool atomic_traits<Is_Always_Lock_Free>::is_always_lock_free;
//***************************************************************************
/// For all types except bool and pointers
//***************************************************************************
template <typename T, bool integral_type = etl::is_integral<T>::value>
class atomic
class atomic : public atomic_traits<integral_type>
{
public:
@ -1440,7 +1458,7 @@ namespace etl
/// Specialisation for pointers
//***************************************************************************
template <typename T>
class atomic<T*, false>
class atomic<T*, false> : public atomic_traits<true>
{
public:
@ -1750,7 +1768,7 @@ namespace etl
/// Specialisation for bool
//***************************************************************************
template <>
class atomic<bool, true>
class atomic<bool, true> : public atomic_traits<true>
{
public:
@ -1973,7 +1991,7 @@ namespace etl
/// Uses a mutex to control access.
//***************************************************************************
template <typename T>
class atomic<T, false>
class atomic<T, false> : public atomic_traits<false>
{
public:
@ -2234,3 +2252,4 @@ namespace etl
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -86,13 +86,13 @@ namespace etl
//***************************************************************************
/// The common base for a bip_buffer_spsc_atomic_base.
//***************************************************************************
template <size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
template <size_t Memory_Model = etl::memory_model::MEMORY_MODEL_LARGE>
class bip_buffer_spsc_atomic_base
{
public:
/// The type used for determining the size of buffer.
typedef typename etl::size_type_lookup<MEMORY_MODEL>::type size_type;
typedef typename etl::size_type_lookup<Memory_Model>::type size_type;
//*************************************************************************
/// Returns true if the buffer is empty.
@ -168,7 +168,7 @@ namespace etl
//*************************************************************************
size_type capacity() const
{
return RESERVED;
return Reserved;
}
//*************************************************************************
@ -176,7 +176,7 @@ namespace etl
//*************************************************************************
size_type max_size() const
{
return RESERVED;
return Reserved;
}
protected:
@ -188,7 +188,7 @@ namespace etl
: read(0)
, write(0)
, last(0)
, RESERVED(reserved_)
, Reserved(reserved_)
{
}
@ -341,7 +341,7 @@ namespace etl
etl::atomic<size_type> read;
etl::atomic<size_type> write;
etl::atomic<size_type> last;
const size_type RESERVED;
const size_type Reserved;
#if defined(ETL_POLYMORPHIC_SPSC_BIP_BUFFER_ATOMIC) || defined(ETL_POLYMORPHIC_CONTAINERS)
public:
@ -361,12 +361,12 @@ namespace etl
//***************************************************************************
/// A fixed capacity bipartite buffer.
//***************************************************************************
template <typename T, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
class ibip_buffer_spsc_atomic : public bip_buffer_spsc_atomic_base<MEMORY_MODEL>
template <typename T, const size_t Memory_Model = etl::memory_model::MEMORY_MODEL_LARGE>
class ibip_buffer_spsc_atomic : public bip_buffer_spsc_atomic_base<Memory_Model>
{
private:
typedef typename etl::bip_buffer_spsc_atomic_base<MEMORY_MODEL> base_t;
typedef typename etl::bip_buffer_spsc_atomic_base<Memory_Model> base_t;
using base_t::reset;
using base_t::get_read_reserve;
using base_t::apply_read_reserve;
@ -486,15 +486,15 @@ namespace etl
/// A fixed capacity bipartite buffer.
/// This buffer supports concurrent access by one producer and one consumer.
/// \tparam T The type this buffer should support.
/// \tparam SIZE The maximum capacity of the buffer.
/// \tparam MEMORY_MODEL The memory model for the buffer. Determines the type of the internal counter variables.
/// \tparam Size The maximum capacity of the buffer.
/// \tparam Memory_Model The memory model for the buffer. Determines the type of the internal counter variables.
//***************************************************************************
template <typename T, const size_t SIZE, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
class bip_buffer_spsc_atomic : public ibip_buffer_spsc_atomic<T, MEMORY_MODEL>
template <typename T, const size_t Size, const size_t Memory_Model = etl::memory_model::MEMORY_MODEL_LARGE>
class bip_buffer_spsc_atomic : public ibip_buffer_spsc_atomic<T, Memory_Model>
{
private:
typedef typename etl::ibip_buffer_spsc_atomic<T, MEMORY_MODEL> base_t;
typedef typename etl::ibip_buffer_spsc_atomic<T, Memory_Model> base_t;
public:
@ -502,19 +502,19 @@ namespace etl
private:
static ETL_CONSTANT size_type RESERVED_SIZE = size_type(SIZE);
static ETL_CONSTANT size_type Reserved_Size = size_type(Size);
public:
ETL_STATIC_ASSERT((SIZE <= (etl::integral_limits<size_type>::max)), "Size too large for memory model");
ETL_STATIC_ASSERT((Size <= (etl::integral_limits<size_type>::max)), "Size too large for memory model");
static ETL_CONSTANT size_type MAX_SIZE = size_type(SIZE);
static ETL_CONSTANT size_type MAX_SIZE = size_type(Size);
//*************************************************************************
/// Default constructor.
//*************************************************************************
bip_buffer_spsc_atomic()
: base_t(reinterpret_cast<T*>(buffer.raw), RESERVED_SIZE)
: base_t(reinterpret_cast<T*>(buffer.raw), Reserved_Size)
{
}
@ -529,11 +529,11 @@ namespace etl
private:
/// The uninitialised buffer of T used in the bip_buffer_spsc.
etl::uninitialized_buffer_of<T, RESERVED_SIZE> buffer;
etl::uninitialized_buffer_of<T, Reserved_Size> buffer;
};
template <typename T, const size_t SIZE, const size_t MEMORY_MODEL>
ETL_CONSTANT typename bip_buffer_spsc_atomic<T, SIZE, MEMORY_MODEL>::size_type bip_buffer_spsc_atomic<T, SIZE, MEMORY_MODEL>::RESERVED_SIZE;
template <typename T, const size_t Size, const size_t Memory_Model>
ETL_CONSTANT typename bip_buffer_spsc_atomic<T, Size, Memory_Model>::size_type bip_buffer_spsc_atomic<T, Size, Memory_Model>::Reserved_Size;
}
#endif /* ETL_HAS_ATOMIC && ETL_USING_CPP11 */

View File

@ -236,8 +236,8 @@ namespace etl
while (nbits != 0)
{
unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
typedef typename etl::make_unsigned<T>::type chunk_t;
typedef typename etl::make_unsigned<T>::type chunk_t;
chunk_t chunk = get_chunk(mask_width);
nbits -= mask_width;
@ -529,7 +529,7 @@ namespace etl
typedef char value_type;
typedef value_type* iterator;
typedef const value_type* const_iterator;
typedef const value_type* const_iterator;
typedef etl::span<value_type> callback_parameter_type;
typedef etl::delegate<void(callback_parameter_type)> callback_type;

View File

@ -251,7 +251,7 @@ namespace etl
//*************************************************************************
reference operator [](size_t index)
{
return pbuffer[(current + index) % picb->buffer_size];
return picb->pbuffer[(current + index) % picb->buffer_size];
}
//*************************************************************************
@ -259,7 +259,7 @@ namespace etl
//*************************************************************************
const_reference operator [](size_t index) const
{
return pbuffer[(current + index) % picb->buffer_size];
return picb->pbuffer[(current + index) % picb->buffer_size];
}
//*************************************************************************
@ -438,7 +438,7 @@ namespace etl
//***************************************************
pointer get_buffer() const
{
return pbuffer;
return picb->pbuffer;
}
protected:
@ -550,7 +550,7 @@ namespace etl
//*************************************************************************
const_reference operator [](size_t index) const
{
return pbuffer[(current + index) % picb->buffer_size];
return picb->pbuffer[(current + index) % picb->buffer_size];
}
//*************************************************************************
@ -717,7 +717,7 @@ namespace etl
//***************************************************
pointer get_buffer() const
{
return pbuffer;
return picb->pbuffer;
}
protected:

View File

@ -52,19 +52,19 @@ namespace etl
};
//*********************************
value_type initial() const
ETL_CONSTEXPR14 value_type initial() const
{
return even_parity;
}
//*********************************
uint8_t add(int parity, uint8_t value) const
ETL_CONSTEXPR14 uint8_t add(int parity, uint8_t value) const
{
return parity ^ etl::parity(value);
}
//*********************************
uint8_t final(uint8_t parity) const
ETL_CONSTEXPR14 uint8_t final(uint8_t parity) const
{
return parity;
}
@ -83,7 +83,7 @@ namespace etl
//*************************************************************************
/// Default constructor.
//*************************************************************************
crc1()
ETL_CONSTEXPR14 crc1()
{
this->reset();
}
@ -94,7 +94,7 @@ namespace etl
/// \param end End of the range.
//*************************************************************************
template<typename TIterator>
crc1(TIterator begin, const TIterator end)
ETL_CONSTEXPR14 crc1(TIterator begin, const TIterator end)
{
this->reset();
this->add(begin, end);

View File

@ -158,23 +158,16 @@ inline void swap(etl::debug_count& lhs, etl::debug_count& rhs)
}
#else
#define ETL_DECLARE_DEBUG_COUNT etl::debug_count etl_debug_count
#define ETL_SET_DEBUG_COUNT(n) ETL_DO_NOTHING
#define ETL_GET_DEBUG_COUNT ETL_DO_NOTHING
#define ETL_INCREMENT_DEBUG_COUNT ETL_DO_NOTHING
#define ETL_DECREMENT_DEBUG_COUNT ETL_DO_NOTHING
#define ETL_ADD_DEBUG_COUNT(n) ETL_DO_NOTHING
#define ETL_SUBTRACT_DEBUG_COUNT(n) ETL_DO_NOTHING
#define ETL_RESET_DEBUG_COUNT ETL_DO_NOTHING
#define ETL_OBJECT_RESET_DEBUG_COUNT(object) ETL_DO_NOTHING
#define ETL_OBJECT_GET_DEBUG_COUNT(object) ETL_DO_NOTHING
namespace etl
{
class debug_count
{
};
}
#define ETL_DECLARE_DEBUG_COUNT
#define ETL_SET_DEBUG_COUNT(n)
#define ETL_GET_DEBUG_COUNT
#define ETL_INCREMENT_DEBUG_COUNT
#define ETL_DECREMENT_DEBUG_COUNT
#define ETL_ADD_DEBUG_COUNT(n)
#define ETL_SUBTRACT_DEBUG_COUNT(n)
#define ETL_RESET_DEBUG_COUNT
#define ETL_OBJECT_RESET_DEBUG_COUNT(object)
#define ETL_OBJECT_GET_DEBUG_COUNT(object)
#endif // ETL_DEBUG_COUNT
#endif

View File

@ -255,6 +255,38 @@ namespace etl
}
};
}
#elif defined(ETL_USE_ASSERT_FUNCTION)
namespace etl
{
namespace private_error_handler
{
typedef void(*assert_function_ptr_t)(const etl::exception&);
// Stores the assert function pointer and default assert function.
template <size_t N>
struct assert_handler
{
static assert_function_ptr_t assert_function_ptr;
static void default_assert(const etl::exception&)
{
assert(false);
}
};
template <size_t N>
assert_function_ptr_t assert_handler<N>::assert_function_ptr = assert_handler<N>::default_assert;
}
//***************************************************************************
/// Sets the assert function.
/// The argument function signature is void(*)(const etl::exception&)
//***************************************************************************
void set_assert_function(etl::private_error_handler::assert_function_ptr_t afptr)
{
etl::private_error_handler::assert_handler<0>::assert_function_ptr = afptr;
}
}
#endif
//***************************************************************************
@ -264,6 +296,7 @@ namespace etl
/// If ETL_NO_CHECKS is defined then no runtime checks are executed at all.
/// If asserts or exceptions are enabled then the error is thrown if the assert fails. The return value is always 'true'.
/// If ETL_LOG_ERRORS is defined then the error is logged if the assert fails. The return value is the value of the boolean test.
/// If ETL_USE_ASSERT_FUNCTION is defined then the error is sent to the assert function.
/// Otherwise 'assert' is called. The return value is always 'true'.
///\ingroup error_handler
//***************************************************************************
@ -275,6 +308,14 @@ namespace etl
#define ETL_ASSERT_FAIL(e) ETL_DO_NOTHING // Does nothing.
#define ETL_ASSERT_FAIL_AND_RETURN(e) ETL_DO_NOTHING // Does nothing.
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) ETL_DO_NOTHING // Does nothing.
#elif defined(ETL_USE_ASSERT_FUNCTION)
#define ETL_ASSERT(b, e) {if(!(b)) {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e));}} // If the condition fails, calls the assert function
#define ETL_ASSERT_OR_RETURN(b, e) {if(!(b)) {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return;}} // If the condition fails, calls the assert function and return
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) {if(!(b)) {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return (v);}} // If the condition fails, calls the assert function and return a value
#define ETL_ASSERT_FAIL(e) {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e));} // Calls the assert function
#define ETL_ASSERT_FAIL_AND_RETURN(e) {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return;} // Calls the assert function and return
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return (v);} // Calls the assert function and return a value
#elif ETL_USING_EXCEPTIONS
#if defined(ETL_LOG_ERRORS)
#define ETL_ASSERT(b, e) {if (!(b)) {etl::error_handler::error((e)); throw((e));}} // If the condition fails, calls the error handler then throws an exception.
@ -292,7 +333,6 @@ namespace etl
#define ETL_ASSERT_FAIL(e) {throw((e));} // Throws an exception.
#define ETL_ASSERT_FAIL_AND_RETURN(e) {throw((e));} // Throws an exception.
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {throw((e));} // Throws an exception.
#endif
#else
#if defined(ETL_LOG_ERRORS)
@ -314,8 +354,8 @@ namespace etl
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {assert(false); return(v);} // Asserts.
#else
#define ETL_ASSERT(b, e) // Does nothing.
#define ETL_ASSERT_OR_RETURN(b, e) {if (!(b)) return;} // Returns.
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) return(v);} // Returns a value.
#define ETL_ASSERT_OR_RETURN(b, e) {if (!(b)) return;} // Returns.
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) return(v);} // Returns a value.
#define ETL_ASSERT_FAIL(e) // Does nothing.
#define ETL_ASSERT_FAIL_AND_RETURN(e) {return;} // Returns.

View File

@ -188,7 +188,7 @@ namespace etl
//*******************************************
/// Get the error.
//*******************************************
//*******************************************
ETL_CONSTEXPR14 TError&& error() const&& ETL_NOEXCEPT
{
return etl::move(error_value);
@ -350,7 +350,7 @@ namespace etl
//*******************************************
template <typename... Args>
ETL_CONSTEXPR14 explicit expected(etl::in_place_t, Args&&... args)
: storage(etl::forward<Args>(args)...)
: storage(etl::in_place_index_t<Value_Type>(), etl::forward<Args>(args)...)
{
}
@ -360,7 +360,7 @@ namespace etl
//*******************************************
template <typename U, typename... Args>
ETL_CONSTEXPR14 explicit expected(etl::in_place_t, std::initializer_list<U> il, Args&&... args)
: storage(il, etl::forward<Args>(args)...)
: storage(etl::in_place_index_t<Value_Type>(), il, etl::forward<Args>(args)...)
{
}
#endif
@ -500,7 +500,7 @@ namespace etl
//*******************************************
/// Get the value.
//*******************************************
value_type& value() const
const value_type& value() const
{
return etl::get<Value_Type>(storage);
}
@ -511,7 +511,7 @@ namespace etl
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
bool has_value() const
bool has_value() const ETL_NOEXCEPT
{
return (storage.index() == Value_Type);
}
@ -521,7 +521,8 @@ namespace etl
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
operator bool() const
ETL_EXPLICIT
operator bool() const ETL_NOEXCEPT
{
return has_value();
}
@ -659,7 +660,7 @@ namespace etl
//*******************************************
///
//*******************************************
error_type& error() const
const error_type& error() const
{
return etl::get<Error_Type>(storage);
}
@ -865,8 +866,8 @@ namespace etl
/// Returns true if expected has a value
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
bool has_value() const
ETL_CONSTEXPR14
bool has_value() const ETL_NOEXCEPT
{
return (storage.index() != Error_Type);
}
@ -875,8 +876,9 @@ namespace etl
/// Returns true if expected has a value
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
operator bool() const
ETL_CONSTEXPR14
ETL_EXPLICIT
operator bool() const ETL_NOEXCEPT
{
return has_value();
}
@ -887,8 +889,8 @@ namespace etl
/// Undefined behaviour if an error has not been set.
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
error_type& error()& ETL_NOEXCEPT
ETL_CONSTEXPR14
error_type& error()& ETL_NOEXCEPT
{
return etl::get<Error_Type>(storage);
}
@ -898,8 +900,8 @@ namespace etl
/// Undefined behaviour if an error has not been set.
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
const error_type& error() const& ETL_NOEXCEPT
ETL_CONSTEXPR14
const error_type& error() const& ETL_NOEXCEPT
{
return etl::get<Error_Type>(storage);
}
@ -909,8 +911,8 @@ namespace etl
/// Undefined behaviour if an error has not been set.
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
error_type&& error() && ETL_NOEXCEPT
ETL_CONSTEXPR14
error_type&& error() && ETL_NOEXCEPT
{
return etl::move(etl::get<Error_Type>(storage));
}
@ -920,8 +922,8 @@ namespace etl
/// Undefined behaviour if an error has not been set.
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
const error_type&& error() const&& ETL_NOEXCEPT
ETL_CONSTEXPR14
const error_type&& error() const&& ETL_NOEXCEPT
{
return etl::move(etl::get<Error_Type>(storage));
}
@ -930,7 +932,7 @@ namespace etl
/// Returns the error
/// Undefined behaviour if an error has not been set.
//*******************************************
error_type& error() const
const error_type& error() const
{
return etl::get<Error_Type>(storage);
}
@ -1105,4 +1107,3 @@ void swap(etl::unexpected<TError>& lhs, etl::unexpected<TError>& rhs)
}
#endif

View File

@ -103,5 +103,8 @@ SOFTWARE.
#define ETL_EXPECTED_FILE_ID "70"
#define ETL_ALIGNMENT_FILE_ID "71"
#define ETL_BASE64_FILE_ID "72"
#define ETL_SINGLETON_BASE_FILE_ID "73"
#define ETL_UNALIGNED_TYPE_FILE_ID "74"
#define ETL_SPAN_FILE_ID "75"
#endif

View File

@ -107,7 +107,8 @@ namespace etl
//*************************************************************************
/// Default constructor.
//*************************************************************************
frame_check_sequence()
ETL_CONSTEXPR14 frame_check_sequence()
: frame_check()
{
reset();
}
@ -118,7 +119,7 @@ namespace etl
/// \param end End of the range.
//*************************************************************************
template<typename TIterator>
frame_check_sequence(TIterator begin, const TIterator end)
ETL_CONSTEXPR14 frame_check_sequence(TIterator begin, const TIterator end) : frame_check()
{
ETL_STATIC_ASSERT(sizeof(typename etl::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
@ -129,7 +130,7 @@ namespace etl
//*************************************************************************
/// Resets the FCS to the initial state.
//*************************************************************************
void reset()
ETL_CONSTEXPR14 void reset()
{
frame_check = policy.initial();
}
@ -140,7 +141,7 @@ namespace etl
/// \param end
//*************************************************************************
template<typename TIterator>
void add(TIterator begin, const TIterator end)
ETL_CONSTEXPR14 void add(TIterator begin, const TIterator end)
{
ETL_STATIC_ASSERT(sizeof(typename etl::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
@ -154,7 +155,7 @@ namespace etl
//*************************************************************************
/// \param value The uint8_t to add to the FCS.
//*************************************************************************
void add(uint8_t value_)
ETL_CONSTEXPR14 void add(uint8_t value_)
{
frame_check = policy.add(frame_check, value_);
}
@ -162,7 +163,7 @@ namespace etl
//*************************************************************************
/// Gets the FCS value.
//*************************************************************************
value_type value() const
ETL_CONSTEXPR14 value_type value() const
{
return policy.final(frame_check);
}
@ -170,7 +171,7 @@ namespace etl
//*************************************************************************
/// Conversion operator to value_type.
//*************************************************************************
operator value_type () const
ETL_CONSTEXPR14 operator value_type () const
{
return policy.final(frame_check);
}
@ -178,7 +179,7 @@ namespace etl
//*************************************************************************
/// Gets an add_insert_iterator for input.
//*************************************************************************
add_insert_iterator input()
ETL_CONSTEXPR14 add_insert_iterator input()
{
return add_insert_iterator(*this);
}

View File

@ -0,0 +1,136 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2025 John Wellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies 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.
******************************************************************************/
#ifndef ETL_FUNCTION_TRAITS_INCLUDED
#define ETL_FUNCTION_TRAITS_INCLUDED
#include "platform.h"
#include "type_list.h"
#include "type_traits.h"
#if ETL_USING_CPP11
namespace etl
{
//***************************************************************************
/// A template to extract the function type traits.
//***************************************************************************
template <typename T>
struct function_traits;
//***************************************************************************
/// Specialisation for function pointers
//***************************************************************************
template <typename TReturn, typename... TArgs>
struct function_traits<TReturn(*)(TArgs...)>
{
using function_type = TReturn(TArgs...); ///< The signature of the function.
using return_type = TReturn; ///< The return type.
using object_type = void; ///< The object type, if a member function.
using argument_types = etl::type_list<TArgs...>; ///< An etl::type_list containing the function argument types.
static constexpr bool is_function = true; ///< <b>true</b> if the type is a free, static or global function, otherwise <b>false</b>.
static constexpr bool is_member_function = false; ///< <b>true</b> if the type is a member function, otherwise <b>false</b>.
static constexpr bool is_const = false; ///< <b>true</b> if the type is a const member function, otherwise <b>false</b>.
static constexpr size_t argument_count = sizeof...(TArgs); ///< The number of arguments that the function takes.
};
template <typename TReturn, typename... TArgs>
constexpr bool function_traits<TReturn(*)(TArgs...)>::is_function;
template <typename TReturn, typename... TArgs>
constexpr bool function_traits<TReturn(*)(TArgs...)>::is_member_function;
template <typename TReturn, typename... TArgs>
constexpr bool function_traits<TReturn(*)(TArgs...)>::is_const;
template <typename TReturn, typename... TArgs>
constexpr size_t function_traits<TReturn(*)(TArgs...)>::argument_count;
//***************************************************************************
/// Specialisation for member function pointers
//***************************************************************************
template <typename TReturn, typename TObject, typename... TArgs>
struct function_traits<TReturn(TObject::*)(TArgs...)>
{
using function_type = TReturn(TArgs...); ///< The signature of the function.
using return_type = TReturn; ///< The return type.
using object_type = TObject; ///< The object type, if a member function.
using argument_types = etl::type_list<TArgs...>; ///< An etl::type_list containing the function argument types.
static constexpr bool is_function = false; ///< <b>true</b> if the type is a free, static or global function, otherwise <b>false</b>.
static constexpr bool is_member_function = true; ///< <b>true</b> if the type is a member function, otherwise <b>false</b>.
static constexpr bool is_const = false; ///< <b>true</b> if the type is a const member function, otherwise <b>false</b>.
static constexpr size_t argument_count = sizeof...(TArgs); ///< The number of arguments that the function takes.
};
template <typename TReturn, typename TObject, typename... TArgs>
constexpr bool function_traits<TReturn(TObject::*)(TArgs...)>::is_function;
template <typename TReturn, typename TObject, typename... TArgs>
constexpr bool function_traits<TReturn(TObject::*)(TArgs...)>::is_member_function;
template <typename TReturn, typename TObject, typename... TArgs>
constexpr bool function_traits<TReturn(TObject::*)(TArgs...)>::is_const;
template <typename TReturn, typename TObject, typename... TArgs>
constexpr size_t function_traits<TReturn(TObject::*)(TArgs...)>::argument_count;
//***************************************************************************
/// Specialisation for const member function pointers
//***************************************************************************
template <typename TReturn, typename TObject, typename... TArgs>
struct function_traits<TReturn(TObject::*)(TArgs...) const>
{
using function_type = TReturn(TArgs...); ///< The signature of the function.
using return_type = TReturn; ///< The return type.
using object_type = TObject; ///< The object type, if a member function.
using argument_types = etl::type_list<TArgs...>; ///< An etl::type_list containing the function argument types.
static constexpr bool is_function = false; ///< <b>true</b> if the type is a free, static or global function, otherwise <b>false</b>.
static constexpr bool is_member_function = true; ///< <b>true</b> if the type is a member function, otherwise <b>false</b>.
static constexpr bool is_const = true; ///< <b>true</b> if the type is a const member function, otherwise <b>false</b>.
static constexpr size_t argument_count = sizeof...(TArgs); ///< The number of arguments that the function takes.
};
template <typename TReturn, typename TObject, typename... TArgs>
constexpr bool function_traits<TReturn(TObject::*)(TArgs...) const>::is_function;
template <typename TReturn, typename TObject, typename... TArgs>
constexpr bool function_traits<TReturn(TObject::*)(TArgs...) const>::is_member_function;
template <typename TReturn, typename TObject, typename... TArgs>
constexpr bool function_traits<TReturn(TObject::*)(TArgs...) const>::is_const;
template <typename TReturn, typename TObject, typename... TArgs>
constexpr size_t function_traits<TReturn(TObject::*)(TArgs...) const>::argument_count;
}
#endif
#endif

View File

@ -112,6 +112,39 @@ namespace etl
return reference_wrapper<const T>(t.get());
}
//***************************************************************************
/// unwrap_reference.
//***************************************************************************
template <class T>
struct unwrap_reference
{
typedef T type;
};
template <typename T>
struct unwrap_reference<etl::reference_wrapper<T> >
{
typedef T& type;
};
#if ETL_USING_CPP11
template <typename T>
using unwrap_reference_t = typename unwrap_reference<T>::type;
#endif
//***************************************************************************
/// unwrap_ref_decay.
//***************************************************************************
template <typename T>
struct unwrap_ref_decay : etl::unwrap_reference<typename etl::decay<T>::type> {};
#if ETL_USING_CPP11
template <typename T>
using unwrap_ref_decay_t = typename unwrap_ref_decay<T>::type;
#endif
//***************************************************************************
/// unary_function
//***************************************************************************
template <typename TArgumentType, typename TResultType>
struct unary_function
@ -120,6 +153,8 @@ namespace etl
typedef TResultType result_type;
};
//***************************************************************************
/// binary_function
//***************************************************************************
template <typename TFirstArgumentType, typename TSecondArgumentType, typename TResultType>
struct binary_function

View File

@ -65,8 +65,6 @@ cog.outl("//********************************************************************
#include "platform.h"
#if ETL_HAS_VIRTUAL_MESSAGES
#include "message.h"
#include "error_handler.h"
#include "static_assert.h"
@ -298,11 +296,39 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
#if !ETL_HAS_VIRTUAL_MESSAGES
//********************************************
void delete_message(etl::imessage* pmsg)
{
(delete_message_type<TMessageTypes>(pmsg) || ...);
}
//********************************************
template <typename TType>
bool delete_message_type(etl::imessage* pmsg)
{
if (TType::ID == pmsg->get_message_id())
{
TType* p = static_cast<TType*>(pmsg);
p->~TType();
return true;
}
else
{
return false;
}
}
#endif
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -671,12 +697,28 @@ namespace etl
cog.outl(" {")
cog.outl(" etl::imessage* pmsg = static_cast<etl::imessage*>(data);")
cog.outl("")
cog.outl("#if ETL_HAS_VIRTUAL_MESSAGES")
cog.outl(" pmsg->~imessage();")
cog.outl("#else")
cog.outl(" delete_message(pmsg);")
cog.outl("#endif")
cog.outl(" }")
cog.outl(" }")
cog.outl(" #include \"private/diagnostic_pop.h\"")
cog.outl("")
cog.outl(" //********************************************")
cog.outl(" void delete_message(etl::imessage* pmsg)")
cog.outl(" {")
cog.outl(" switch (pmsg->get_message_id())")
cog.outl(" {")
for n in range(1, int(Handlers) + 1):
cog.out(" case T%d::ID: static_cast<const T%d" %(n, n))
cog.outl("*>(pmsg)->~T%d(); break;" % n)
cog.outl(" default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;")
cog.outl(" }")
cog.outl(" }")
cog.outl("")
cog.outl(" //********************************************")
cog.outl(" void add_new_message(const etl::imessage& msg)")
cog.outl(" {")
cog.outl(" const size_t id = msg.get_message_id();")
@ -686,7 +728,7 @@ namespace etl
cog.outl(" {")
for n in range(1, int(Handlers) + 1):
cog.outl(" case T%d::ID: ::new (p) T%d(static_cast<const T%d&>(msg)); break;" %(n, n, n))
cog.outl(" default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;")
cog.outl(" default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;")
cog.outl(" }")
cog.outl(" }")
cog.outl("")
@ -701,7 +743,7 @@ namespace etl
cog.outl(" {")
for n in range(1, int(Handlers) + 1):
cog.outl(" case T%d::ID: ::new (p) T%d(static_cast<T%d&&>(msg)); break;" %(n, n, n))
cog.outl(" default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;")
cog.outl(" default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;")
cog.outl(" }")
cog.outl(" }")
cog.outl("#endif")
@ -959,12 +1001,29 @@ namespace etl
cog.outl(" {")
cog.outl(" etl::imessage* pmsg = static_cast<etl::imessage*>(data);")
cog.outl("")
cog.outl("")
cog.outl("#if ETL_HAS_VIRTUAL_MESSAGES")
cog.outl(" pmsg->~imessage();")
cog.outl("#else")
cog.outl(" delete_message(pmsg);")
cog.outl("#endif")
cog.outl(" }")
cog.outl(" }")
cog.outl(" #include \"private/diagnostic_pop.h\"")
cog.outl("")
cog.outl(" //********************************************")
cog.outl(" void delete_message(etl::imessage* pmsg)")
cog.outl(" {")
cog.outl(" switch (pmsg->get_message_id())")
cog.outl(" {")
for t in range(1, n + 1):
cog.out(" case T%d::ID: static_cast<const T%d" %(t, t))
cog.outl("*>(pmsg)->~T%d(); break;" % t)
cog.outl(" default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;")
cog.outl(" }")
cog.outl(" }")
cog.outl("")
cog.outl(" //********************************************")
cog.outl(" void add_new_message(const etl::imessage& msg)")
cog.outl(" {")
cog.outl(" const size_t id = msg.get_message_id();")
@ -974,7 +1033,7 @@ namespace etl
cog.outl(" {")
for t in range(1, n + 1):
cog.outl(" case T%d::ID: ::new (p) T%d(static_cast<const T%d&>(msg)); break;" %(t, t, t))
cog.outl(" default: break;")
cog.outl(" default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;")
cog.outl(" }")
cog.outl(" }")
cog.outl("")
@ -1001,8 +1060,5 @@ namespace etl
/*[[[end]]]*/
#endif
}
#else
#error "etl::message_packet is not compatible with non-virtual etl::imessage"
#endif
#endif

View File

@ -66,9 +66,7 @@ cog.outl("//********************************************************************
#include "platform.h"
#include "message.h"
#include "shared_message.h"
#if ETL_HAS_VIRTUAL_MESSAGES
#include "message_packet.h"
#endif
#include "message_packet.h"
#include "message_types.h"
#include "alignment.h"
#include "error_handler.h"
@ -424,9 +422,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<TMessageTypes...> message_packet;
#endif
//**********************************************
message_router()
@ -584,12 +580,10 @@ namespace etl
cog.outl("{")
cog.outl("public:")
cog.outl("")
cog.outl("#if ETL_HAS_VIRTUAL_MESSAGES")
cog.out(" typedef etl::message_packet<")
for n in range(1, int(Handlers)):
cog.out("T%s, " % n)
cog.outl(" T%s> message_packet;" % int(Handlers))
cog.outl("#endif")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" message_router(etl::message_router_id_t id_)")
@ -754,12 +748,10 @@ namespace etl
cog.outl("{")
cog.outl("public:")
cog.outl("")
cog.outl("#if ETL_HAS_VIRTUAL_MESSAGES")
cog.out(" typedef etl::message_packet<")
for t in range(1, n):
cog.out("T%s, " % t)
cog.outl(" T%s> message_packet;" % n)
cog.outl("#endif")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" message_router(etl::message_router_id_t id_)")

View File

@ -640,17 +640,12 @@ namespace etl
{
private:
template<typename T> struct dummy {};
struct internal: TDerived, dummy<int>{};
static TBase* check(TBase*) { return (TBase*)0; }
template<typename T>
static char check(dummy<T>*) { return 0; }
static char check(...) { return 0; }
public:
static const bool value = (sizeof(check((internal*)0)) == sizeof(TBase*));
static const bool value = (sizeof(check((TDerived*)0)) == sizeof(TBase*));
};
// For when TBase or TDerived is a fundamental type.
@ -1339,6 +1334,79 @@ typedef integral_constant<bool, true> true_type;
// ETL extended type traits.
//***************************************************************************
#if ETL_USING_CPP11
//***************************************************************************
/// conjunction
#if ETL_USING_CPP11
template <typename...>
struct conjunction : public etl::true_type
{
};
template <typename T1, typename... Tn>
struct conjunction<T1, Tn...> : public etl::conditional_t<bool(T1::value), etl::conjunction<Tn...>, T1>
{
};
template <typename T>
struct conjunction<T> : public T
{
};
#endif
#if ETL_USING_CPP17
template <typename... T>
inline constexpr bool conjunction_v = conjunction<T...>::value;
#endif
//***************************************************************************
/// disjunction
#if ETL_USING_CPP11
template <typename...>
struct disjunction : public etl::false_type
{
};
template <typename T1, typename... Tn>
struct disjunction<T1, Tn...> : public etl::conditional_t<bool(T1::value), T1, disjunction<Tn...>>
{
};
template <typename T1> struct disjunction<T1> : public T1
{
};
#endif
#if ETL_USING_CPP17
template <typename... T>
inline constexpr bool disjunction_v = etl::disjunction<T...>::value;
#endif
#endif
//***************************************************************************
/// exclusive_disjunction
#if ETL_USING_CPP11
template <typename... TTypes>
struct exclusive_disjunction;
template <typename T>
struct exclusive_disjunction<T> : public etl::bool_constant<T::value>
{
};
// Recursive case: XOR the first two values and recurse
template <typename T1, typename T2, typename... TRest>
struct exclusive_disjunction<T1, T2, TRest...> : public etl::exclusive_disjunction<etl::integral_constant<bool, etl::disjunction<T1, T2>::value && !etl::conjunction<T1, T2>::value>, TRest...>
{
};
#endif
#if ETL_USING_CPP17
template <typename... T>
inline constexpr bool exclusive_disjunction_v = etl::exclusive_disjunction<T...>::value;
#endif
//***************************************************************************
/// conditional_integral_constant
// /\ingroup type_traits
@ -1361,19 +1429,11 @@ typedef integral_constant<bool, true> true_type;
#if ETL_USING_CPP11
//***************************************************************************
/// Template to determine if a type is one of a specified list.
/// Template to determine if a type is a base of all types in a specified list.
///\ingroup types
template <typename T, typename T1, typename... TRest>
struct is_one_of
template <typename T, typename... TRest>
struct is_one_of : etl::disjunction<etl::is_same<T, TRest>...>
{
static const bool value = etl::is_same<T, T1>::value ||
etl::is_one_of<T, TRest...>::value;
};
template <typename T, typename T1>
struct is_one_of<T, T1>
{
static const bool value = etl::is_same<T, T1>::value;
};
#else
/*[[[cog
@ -1406,21 +1466,46 @@ typedef integral_constant<bool, true> true_type;
inline constexpr bool is_one_of_v = etl::is_one_of<T, TRest...>::value;
#endif
#if ETL_USING_CPP11
namespace private_type_traits
{
//***************************************************************************
// Helper to count occurrences of a type in a list of types
template<typename T, typename... TTypes>
struct count_type;
// Base case: zero occurrences
template<typename T>
struct count_type<T> : etl::integral_constant<size_t, 0>
{
};
// Recursive case: increment count if head is the same as T, otherwise continue with tail
template<typename T, typename THead, typename... TTail>
struct count_type<T, THead, TTail...> : etl::integral_constant<size_t, (etl::is_same<T, THead>::value ? 1 : 0) + count_type<T, TTail...>::value>
{
};
}
template<typename T, typename... TTypes>
struct has_duplicates_of
: etl::integral_constant<bool, (private_type_traits::count_type<T, TTypes...>::value > 1)>
{
};
#endif
#if ETL_USING_CPP17
template <typename T, typename... TRest>
inline constexpr bool has_duplicates_of_v = etl::has_duplicates_of<T, TRest...>::value;
#endif
#if ETL_USING_CPP11
//***************************************************************************
/// Template to determine if a type is a base of all types in a specified list.
///\ingroup types
template <typename T, typename T1, typename... TRest>
struct is_base_of_all
template <typename TBase, typename... TDerived>
struct is_base_of_all : etl::conjunction<etl::is_base_of<TBase, TDerived>...>
{
static const bool value = etl::is_base_of<T, T1>::value &&
etl::is_base_of_all<T, TRest...>::value;
};
template <typename T, typename T1>
struct is_base_of_all<T, T1>
{
static const bool value = etl::is_base_of<T, T1>::value;
};
#endif
@ -1433,18 +1518,11 @@ typedef integral_constant<bool, true> true_type;
//***************************************************************************
/// Template to determine if a type is a base of any type in a specified list.
///\ingroup types
template <typename T, typename T1, typename... TRest>
struct is_base_of_any
template <typename TBase, typename... TDerived>
struct is_base_of_any : etl::disjunction<etl::is_base_of<TBase, TDerived>...>
{
static const bool value = etl::is_base_of<T, T1>::value ||
etl::is_base_of_any<T, TRest...>::value;
};
template <typename T, typename T1>
struct is_base_of_any<T, T1>
{
static const bool value = etl::is_base_of<T, T1>::value;
};
#endif
#if ETL_USING_CPP17
@ -1452,6 +1530,28 @@ typedef integral_constant<bool, true> true_type;
inline constexpr bool is_base_of_any_v = etl::is_base_of_any<T, TRest...>::value;
#endif
//***************************************************************************
/// Get the Nth base of a recursively inherited type.
/// Requires that the class has defined 'base_type'.
//***************************************************************************
// Recursive definition of the type.
template <size_t N, typename TType>
struct nth_base
{
typedef typename nth_base<N - 1U, typename TType::base_type>::type type;
};
template <typename TType>
struct nth_base<0, TType>
{
typedef TType type;
};
#if ETL_USING_CPP11
template <size_t N, typename TType>
using nth_base_t = typename nth_base<N, TType>::type;
#endif
//***************************************************************************
/// A set of templates to allow related types to be derived.
///\ingroup types
@ -1605,70 +1705,15 @@ typedef integral_constant<bool, true> true_type;
#if ETL_USING_CPP11
//***************************************************************************
/// are_all_same
template <typename T, typename T1, typename... TRest>
struct are_all_same
{
static const bool value = etl::is_same<T, T1>::value &&
etl::are_all_same<T, TRest...>::value;
};
template <typename T, typename T1>
struct are_all_same<T, T1>
{
static const bool value = etl::is_same<T, T1>::value;
};
#endif
#if ETL_USING_CPP17
template <typename T, typename T1, typename... TRest>
inline constexpr bool are_all_same_v = are_all_same<T, T1, TRest...>::value;
#endif
//***************************************************************************
/// conjunction
#if ETL_USING_CPP11
template <typename...>
struct conjunction : public etl::true_type
{
};
template <typename T1, typename... Tn>
struct conjunction<T1, Tn...> : public etl::conditional_t<bool(T1::value), etl::conjunction<Tn...>, T1>
{
};
template <typename T>
struct conjunction<T> : public T
template <typename T, typename... TRest>
struct are_all_same : etl::conjunction<etl::is_same<T, TRest>...>
{
};
#endif
#if ETL_USING_CPP17
template <typename... T>
inline constexpr bool conjunction_v = conjunction<T...>::value;
#endif
//***************************************************************************
/// disjunction
#if ETL_USING_CPP11
template <typename...>
struct disjunction : public etl::false_type
{
};
template <typename T1, typename... Tn>
struct disjunction<T1, Tn...> : public etl::conditional_t<bool(T1::value), T1, disjunction<Tn...>>
{
};
template <typename T1> struct disjunction<T1> : public T1
{
};
#endif
#if ETL_USING_CPP17
template <typename... T>
inline constexpr bool disjunction_v = etl::disjunction<T...>::value;
template <typename T, typename... TRest>
inline constexpr bool are_all_same_v = are_all_same<T, TRest...>::value;
#endif
//***************************************************************************
@ -2318,6 +2363,9 @@ typedef integral_constant<bool, true> true_type;
etl::true_type,
has_duplicates<TRest...>> {};
template <typename T>
struct has_duplicates<T> : etl::false_type {};
template <>
struct has_duplicates<> : etl::false_type {};
#endif
@ -2346,18 +2394,6 @@ typedef integral_constant<bool, true> true_type;
template <typename T, typename... TTypes>
inline constexpr size_t count_of_v = etl::count_of<T, TTypes...>::value;
#endif
#if ETL_USING_CPP11
//*********************************************
// has_duplicates_of
template <typename T, typename... TTypes>
struct has_duplicates_of : etl::bool_constant<(etl::count_of<T, TTypes...>::value > 1U)> {};
#endif
#if ETL_USING_CPP17
template <typename T, typename... TTypes>
inline constexpr bool has_duplicates_of_v = etl::has_duplicates_of<T, TTypes...>::value;
#endif
}
// Helper macros

View File

@ -0,0 +1,80 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2025 John Wellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies 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.
******************************************************************************/
#ifndef ETL_INDEX_OF_TYPE_INCLUDED
#define ETL_INDEX_OF_TYPE_INCLUDED
#include "platform.h"
#include "static_assert.h"
#include "integral_limits.h"
namespace etl
{
#if ETL_USING_CPP11
//***************************************************************************
/// Defines a no-position constant.
//***************************************************************************
static ETL_CONSTANT size_t index_of_type_npos = etl::integral_limits<size_t>::max;
//***************************************************************************
/// Finds the index of a type in a variadic type parameter.
//***************************************************************************
template <typename T, typename... TTypes>
struct index_of_type;
//***************************************************************************
/// Finds the index of a type in a variadic type parameter.
//***************************************************************************
template <typename T, typename T1, typename... TRest>
struct index_of_type<T, T1, TRest...> : public etl::integral_constant<size_t, etl::is_same<T, T1>::value ? 0 :
(etl::index_of_type<T, TRest...>::value == etl::index_of_type_npos ? etl::index_of_type_npos :
etl::index_of_type<T, TRest...>::value + 1)>
{
};
//***************************************************************************
/// Finds the index of a type in a variadic type parameter.
/// No types left.
//***************************************************************************
template <typename T>
struct index_of_type<T> : public etl::integral_constant<size_t, etl::index_of_type_npos>
{
};
#if ETL_USING_CPP17
//***************************************************************************
/// Finds the index of a type in a variadic type parameter.
//***************************************************************************
template <typename T, typename... TTypes>
inline constexpr size_t index_of_type_v = etl::index_of_type<T, TTypes...>::value;
#endif
#endif
}
#endif

View File

@ -253,6 +253,24 @@ namespace etl
return current_size;
}
//*************************************************************************
/// Detects existence of specified node in list.
///\param search_link The node to find in list
//*************************************************************************
bool contains_node(const link_type& search_link) const
{
return is_link_in_list(&search_link);
}
//*************************************************************************
/// Detects existence of specified node in list.
///\param search_link The node to find in list
//*************************************************************************
bool contains_node(const link_type* search_link) const
{
return is_link_in_list(search_link);
}
protected:
link_type start; ///< The link pointer that acts as the intrusive_forward_list start.
@ -304,7 +322,10 @@ namespace etl
if (p_next != &this->terminator)
{
link_type* p_unlinked = etl::unlink_after<link_type>(link);
p_unlinked->clear();
if (p_unlinked != ETL_NULLPTR)
{
p_unlinked->clear();
}
--current_size;
}
}
@ -338,24 +359,20 @@ namespace etl
/// Tests if the link is in this list.
/// Returns the previous link to it, if found, otherwise ETL_NULLPTR.
//*************************************************************************
link_type* is_link_in_list(link_type& search_link)
link_type* is_link_in_list(const link_type* search_link) const
{
link_type* p_link = start.etl_next;
link_type* p_previous = &start;
link_type* p_previous = const_cast<link_type*>(&start);
while (p_link != ETL_NULLPTR)
{
if (&search_link == p_link)
if (search_link == p_link)
{
return p_previous;
}
p_previous = p_link;
if (p_link != ETL_NULLPTR)
{
p_link = p_link->link_type::etl_next;
}
p_link = p_link->link_type::etl_next;
}
return ETL_NULLPTR;
@ -366,7 +383,7 @@ namespace etl
/// Returns ETL_NULLPTR if the link was not in this list.
/// Returns the next
//*************************************************************************
link_type* remove_link(link_type& link)
link_type* remove_link(link_type* link)
{
link_type* result = ETL_NULLPTR;
@ -374,7 +391,7 @@ namespace etl
if (p_previous != ETL_NULLPTR)
{
link_type* p_next = link.etl_next;
link_type* p_next = link->etl_next;
disconnect_link_after(*p_previous);
@ -629,6 +646,22 @@ namespace etl
this->assign(first, last);
}
#if ETL_USING_CPP11
//*************************************************************************
/// Constructor from variadic list of nodes.
//*************************************************************************
template <typename... TLinks>
intrusive_forward_list(link_type& first, TLinks&... links)
{
ETL_STATIC_ASSERT((etl::is_base_of_all<link_type, TLinks...>::value), "Mixed link types");
this->current_size = 0;
this->start.etl_next = &first;
link_type* last = make_linked_list(this->current_size, first, static_cast<link_type&>(links)...);
last->etl_next = &this->terminator;
}
#endif
//*************************************************************************
/// Gets the beginning of the intrusive_forward_list.
//*************************************************************************
@ -787,9 +820,17 @@ namespace etl
//*************************************************************************
/// Erases the specified node.
//*************************************************************************
node_type* erase(node_type& node)
node_type* erase(const node_type& node)
{
return static_cast<node_type*>(this->remove_link(node));
return static_cast<node_type*>(this->remove_link(const_cast<node_type*>(&node)));
}
//*************************************************************************
/// Erases the specified node.
//*************************************************************************
node_type* erase(const node_type* p_node)
{
return static_cast<node_type*>(this->remove_link(const_cast<node_type*>(p_node)));
}
//*************************************************************************
@ -991,6 +1032,29 @@ namespace etl
}
}
//*************************************************************************
// Removes the element specified by pointer.
//*************************************************************************
void remove(const_pointer element)
{
iterator i_item = begin();
iterator i_last_item = before_begin();
while (i_item != end())
{
if (&i_item == element)
{
i_item = erase_after(i_last_item);
return;
}
else
{
++i_item;
++i_last_item;
}
}
}
//*************************************************************************
/// Removes according to a predicate.
//*************************************************************************
@ -1167,8 +1231,64 @@ namespace etl
}
}
//*************************************************************************
/// Detects existence of specified value in list.
///\param value The value to find in list
//*************************************************************************
bool contains(const_reference value) const
{
const_iterator i_item = begin();
while (i_item != end())
{
if (*i_item == value)
{
return true;
}
++i_item;
}
return false;
}
private:
#if ETL_USING_CPP17
//***************************************************************************
/// Create a linked list from a number of forward_link nodes.
//***************************************************************************
template <typename... TLinks>
link_type* make_linked_list(size_t& count, link_type& first, TLinks&... links)
{
link_type* current = &first;
++count;
((current->etl_next = &links, current = &links, ++count), ...);
return current;
}
#elif ETL_USING_CPP11
//***************************************************************************
/// Create a counted linked list from a number of forward_link nodes.
//***************************************************************************
link_type* make_linked_list(size_t& count, link_type& first)
{
++count;
return &first;
}
//***************************************************************************
/// Create a counted linked list from a number of forward_link nodes.
//***************************************************************************
template <typename... TLinks>
link_type* make_linked_list(size_t& count, link_type& first, link_type& next, TLinks&... links)
{
++count;
first.etl_next = &next;
return make_linked_list(count, next, static_cast<link_type&>(links)...);
}
#endif
//*************************************************************************
/// Get the next value.
//*************************************************************************

View File

@ -375,7 +375,7 @@ namespace etl
}
//***************************************************************************
// link_clear
// link_clear range
//***************************************************************************
// Reference
template <typename TLink>
@ -404,6 +404,112 @@ namespace etl
}
}
#if ETL_USING_CPP17
//***************************************************************************
/// Create a linked list from a number of forward_link nodes.
//***************************************************************************
template <typename TLink, typename... TLinks>
typename etl::enable_if<etl::is_forward_link<TLink>::value, TLink*>::type
create_linked_list(TLink& first, TLinks&... links)
{
TLink* current = &first;
((current->etl_next = &links, current = &links), ...);
return current;
}
//***************************************************************************
/// Create a linked list from a number of forward_link nodes.
//***************************************************************************
template <typename TLink, typename... TLinks>
typename etl::enable_if<etl::is_forward_link<TLink>::value, TLink*>::type
create_linked_list(TLink* first, TLinks*... links)
{
if (first != ETL_NULLPTR)
{
return create_linked_list(*first, (*links)...);
}
else
{
return nullptr;
}
}
#elif ETL_USING_CPP11
//***************************************************************************
/// Create a linked list from a number of forward_link nodes.
//***************************************************************************
template <typename TLink>
typename etl::enable_if<etl::is_forward_link<TLink>::value, TLink*>::type
create_linked_list(TLink& first)
{
return &first;
}
//***************************************************************************
/// Create a linked list from a number of forward_link nodes.
//***************************************************************************
template <typename TLink, typename... TLinks>
typename etl::enable_if<etl::is_forward_link<TLink>::value, TLink*>::type
create_linked_list(TLink& first, TLink& next, TLinks&... links)
{
first.etl_next = &next;
return create_linked_list(next, static_cast<TLink&>(links)...);
}
//***************************************************************************
/// Create a linked list from a number of forward_link nodes.
//***************************************************************************
template <typename TLink>
typename etl::enable_if<etl::is_forward_link<TLink>::value, TLink*>::type
create_linked_list(TLink* first)
{
if (first != ETL_NULLPTR)
{
return create_linked_list(*first);
}
else
{
return ETL_NULLPTR;
}
}
//***************************************************************************
/// Create a linked list from a number of forward_link nodes.
//***************************************************************************
template <typename TLink, typename... TLinks>
typename etl::enable_if<etl::is_forward_link<TLink>::value, TLink*>::type
create_linked_list(TLink* first, TLink* next, TLinks*... links)
{
if (first != ETL_NULLPTR)
{
return create_linked_list(*first, *next, static_cast<TLink&>(*links)...);
}
else
{
return ETL_NULLPTR;
}
}
#endif
//***************************************************************************
template <typename TLink>
typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
detach_linked_list(TLink& first)
{
link_clear_range(first);
}
//***************************************************************************
template <typename TLink>
typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
detach_linked_list(TLink* first)
{
if (first != ETL_NULLPTR)
{
detach_linked_list(*first);
}
}
//***************************************************************************
/// A bidirectional link.
//***************************************************************************
@ -829,6 +935,93 @@ namespace etl
etl::link_clear_range(*start);
}
#if ETL_USING_CPP17
//***************************************************************************
/// Create a linked list from a number of bidirectional_link nodes.
//***************************************************************************
template <typename TLink, typename... TLinks>
typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type
create_linked_list(TLink& first, TLinks&... links)
{
TLink* current = &first;
((current->etl_next = &links, static_cast<TLink&>(links).etl_previous = current, current = &links), ...);
return current;
}
//***************************************************************************
/// Create a linked list from a number of bidirectional_link nodes.
//***************************************************************************
template <typename TLink, typename... TLinks>
typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type
create_linked_list(TLink* first, TLinks*... links)
{
TLink* current = first;
((current->etl_next = links, static_cast<TLink*>(links)->etl_previous = current, current = links), ...);
return current;
}
#elif ETL_USING_CPP11
//***************************************************************************
/// Create a linked list from a number of bidirectional_link nodes.
//***************************************************************************
template <typename TLink>
typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type
create_linked_list(TLink& first)
{
return &first;
}
//***************************************************************************
/// Create a linked list from a number of bidirectional_link nodes.
//***************************************************************************
template <typename TLink, typename... TLinks>
typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type
create_linked_list(TLink& first, TLink& next, TLinks&... links)
{
first.etl_next = &next;
next.etl_previous = &first;
return create_linked_list(next, static_cast<TLink&>(links)...);
}
//***************************************************************************
/// Create a linked list from a number of bidirectional_link nodes.
//***************************************************************************
template <typename TLink, typename... TLinks>
typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type
create_linked_list(TLink* first, TLink* next, TLinks*... links)
{
if (first != ETL_NULLPTR)
{
return create_linked_list(*first, *next, static_cast<TLink&>(*links)...);
}
else
{
return ETL_NULLPTR;
}
}
#endif
//***************************************************************************
template <typename TLink>
typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, void>::type
detach_linked_list(TLink& first)
{
link_clear_range(first);
}
//***************************************************************************
template <typename TLink>
typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, void>::type
detach_linked_list(TLink* first)
{
if (first != ETL_NULLPTR)
{
detach_linked_list(*first);
}
}
//***************************************************************************
/// A binary tree link.
//***************************************************************************

View File

@ -255,6 +255,24 @@ namespace etl
return current_size;
}
//*************************************************************************
/// Detects existence of specified node in list.
///\param search_link The node to find in list
//*************************************************************************
bool contains_node(const link_type& search_link) const
{
return is_link_in_list(&search_link);;
}
//*************************************************************************
/// Detects existence of specified node in list.
///\param search_link The node to find in list
//*************************************************************************
bool contains_node(const link_type* search_link) const
{
return is_link_in_list(search_link);;
}
protected:
/// The link that acts as the intrusive_list start & end.
@ -379,13 +397,13 @@ namespace etl
//*************************************************************************
/// Tests if the link is in this list.
//*************************************************************************
bool is_link_in_list(link_type& search_link) const
bool is_link_in_list(const link_type* search_link) const
{
link_type* p_link = terminal_link.link_type::etl_next;
while (p_link != &terminal_link)
{
if (&search_link == p_link)
if (search_link == p_link)
{
return true;
}
@ -400,13 +418,13 @@ namespace etl
/// Remove the specified node from the list.
/// Returns ETL_NULLPTR if the link was not in this list or was the last in the list.
//*************************************************************************
link_type* remove_link(link_type& link)
link_type* remove_link(link_type* link)
{
link_type* result = ETL_NULLPTR;
if (is_link_in_list(link))
{
link_type* p_next = link.etl_next;
link_type* p_next = link->etl_next;
disconnect_link(link);
@ -685,6 +703,24 @@ namespace etl
this->assign(first, last);
}
#if ETL_USING_CPP11
//*************************************************************************
/// Constructor from variadic list of nodes.
//*************************************************************************
template <typename... TLinks>
intrusive_list(link_type& first, TLinks&... links)
{
ETL_STATIC_ASSERT((etl::is_base_of_all<link_type, TLinks...>::value), "Mixed link types");
this->current_size = 0;
this->terminal_link.etl_next = &first;
link_type* last = make_linked_list(this->current_size, first, static_cast<link_type&>(links)...);
first.etl_previous = &this->terminal_link;
last->etl_next = &this->terminal_link;
this->terminal_link.etl_previous = last;
}
#endif
//*************************************************************************
/// Gets the beginning of the intrusive_list.
//*************************************************************************
@ -843,9 +879,17 @@ namespace etl
//*************************************************************************
/// Erases the specified node.
//*************************************************************************
node_type* erase(node_type& node)
node_type* erase(const node_type& node)
{
return static_cast<node_type*>(this->remove_link(node));
return static_cast<node_type*>(this->remove_link(const_cast<node_type*>(&node)));
}
//*************************************************************************
/// Erases the specified node.
//*************************************************************************
node_type* erase(const node_type* p_node)
{
return static_cast<node_type*>(this->remove_link(const_cast<node_type*>(p_node)));
}
//*************************************************************************
@ -1192,8 +1236,67 @@ namespace etl
}
}
//*************************************************************************
/// Detects existence of specified value in list.
///\param value The value to find in list
//*************************************************************************
bool contains(const_reference value) const
{
const_iterator i_item = begin();
while (i_item != end())
{
if (*i_item == value)
{
return true;
}
++i_item;
}
return false;
}
private:
#if ETL_USING_CPP17
//***************************************************************************
/// Create a linked list from a number of bidirectional_link nodes.
//***************************************************************************
template <typename... TLinks>
link_type* make_linked_list(size_t& count, link_type& first, TLinks&... links)
{
TLink* current = &first;
++count;
((current->etl_next = &links, static_cast<TLink&>(links).etl_previous = current, current = &links, ++count), ...);
return current;
}
#elif ETL_USING_CPP11
//***************************************************************************
/// Create a linked list from a number of bidirectional_link nodes.
//***************************************************************************
link_type* make_linked_list(size_t& count, link_type& first)
{
++count;
return &first;
}
//***************************************************************************
/// Create a linked list from a number of bidirectional_link nodes.
//***************************************************************************
template <typename... TLinks>
link_type* make_linked_list(size_t& count, link_type& first, link_type& next, TLinks&... links)
{
++count;
first.etl_next = &next;
next.etl_previous = &first;
return make_linked_list(count, next, static_cast<link_type&>(links)...);
}
#endif
// Disabled.
intrusive_list(const intrusive_list& other);
intrusive_list& operator = (const intrusive_list& rhs);

View File

@ -271,6 +271,14 @@ namespace etl
return Max_Size;
}
//*************************************************************************
/// Returns the maximum size of an item in the pool.
//*************************************************************************
size_t max_item_size() const
{
return Item_Size;
}
//*************************************************************************
/// Returns the maximum number of items in the pool.
//*************************************************************************
@ -377,39 +385,13 @@ namespace etl
//*************************************************************************
void release_item(char* p_value)
{
//// Does it belong to us?
//ETL_ASSERT(is_item_in_pool(p_value), ETL_ERROR(pool_object_not_in_pool));
//if (p_next != ETL_NULLPTR)
//{
// // Point it to the current free item.
// *(uintptr_t*)p_value = reinterpret_cast<uintptr_t>(p_next);
//}
//else
//{
// // This is the only free item.
// *((uintptr_t*)p_value) = 0;
//}
//p_next = p_value;
//--items_allocated;
// Does it belong to us?
ETL_ASSERT(is_item_in_pool(p_value), ETL_ERROR(pool_object_not_in_pool));
if (items_allocated > 0)
{
if (p_next != ETL_NULLPTR)
{
// Point it to the current free item.
*(uintptr_t*)p_value = reinterpret_cast<uintptr_t>(p_next);
}
else
{
// This is the only free item.
*((uintptr_t*)p_value) = 0;
}
// Point it to the current free item.
*(uintptr_t*)p_value = reinterpret_cast<uintptr_t>(p_next);
p_next = p_value;

View File

@ -139,7 +139,7 @@ namespace etl
{
ETL_STATIC_ASSERT(Size >= sizeof(T), "Type size is too large");
::new (static_cast<void*>(buffer)) T(value);
::new (static_cast<void*>(buffer.raw)) T(value);
}
//***********************************
@ -148,7 +148,7 @@ namespace etl
template <typename T>
void assign_at_offset(size_t offset, const T& value)
{
char* p = static_cast<char*>(buffer) + offset;
char* p = static_cast<char*>(buffer.raw) + offset;
ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception));
::new (p) T(value);
@ -160,7 +160,7 @@ namespace etl
template <typename T, size_t Offset>
void assign_at_offset(const T& value)
{
char* p = static_cast<char*>(buffer) + Offset;
char* p = static_cast<char*>(buffer.raw) + Offset;
ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Type size is too large");
::new (p) T(value);
@ -171,35 +171,41 @@ namespace etl
/// Emplace from parameters
//***********************************
template <typename T, typename... TArgs>
void emplace(TArgs... args)
T& emplace(TArgs... args)
{
ETL_STATIC_ASSERT(Size >= sizeof(T), "Type size is too large");
::new (static_cast<void*>(buffer)) T(etl::forward<TArgs>(args)...);
::new (static_cast<void*>(buffer.raw)) T(etl::forward<TArgs>(args)...);
return ref<T>();
}
//***********************************
/// Emplace from parameters at offset
//***********************************
template <typename T, typename... TArgs>
void emplace_at_offset(size_t offset, TArgs... args)
T& emplace_at_offset(size_t offset, TArgs... args)
{
char* p = static_cast<char*>(buffer) + offset;
char* p = static_cast<char*>(buffer.raw) + offset;
ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception));
::new (p) T(etl::forward<TArgs>(args)...);
return ref_at_offset<T>(offset);
}
//***********************************
/// Emplace from parameters at offset
//***********************************
template <typename T, size_t Offset, typename... TArgs>
void emplace_at_offset(TArgs... args)
T& emplace_at_offset(TArgs... args)
{
char* p = static_cast<char*>(buffer) + Offset;
char* p = static_cast<char*>(buffer.raw) + Offset;
ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Type size is too large");
::new (p) T(etl::forward<TArgs>(args)...);
return ref_at_offset<T, Offset>();
}
#endif
@ -209,9 +215,9 @@ namespace etl
template <typename T>
ETL_NODISCARD T& ref()
{
ETL_STATIC_ASSERT(sizeof(T) <= Size, "Size of T is too large");
ETL_STATIC_ASSERT(sizeof(T) <= Size, "Size of type too large for storage");
return *static_cast<T*>(buffer);
return *reinterpret_cast<T*>(buffer.raw);
}
//***********************************
@ -220,9 +226,9 @@ namespace etl
template <typename T>
ETL_NODISCARD const T& ref() const
{
ETL_STATIC_ASSERT(sizeof(T) <= Size, "Size of T is too large");
ETL_STATIC_ASSERT(sizeof(T) <= Size, "Size of type too large for storage");
return *static_cast<const T*>(buffer);
return *reinterpret_cast<const T*>(buffer.raw);
}
//***********************************
@ -233,9 +239,7 @@ namespace etl
{
ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception));
char* p = buffer + offset;
return *static_cast<T*>(p);
return *reinterpret_cast<T*>(buffer.raw + offset);
}
//***********************************
@ -246,9 +250,7 @@ namespace etl
{
ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception));
char* p = buffer + offset;
return *static_cast<const T*>(p);
return *reinterpret_cast<const T*>(buffer.raw + offset);
}
//***********************************
@ -257,11 +259,9 @@ namespace etl
template <typename T, size_t Offset>
ETL_NODISCARD T& ref_at_offset()
{
ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Size of T is too large");
ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Size of type too large for storage");
char* p = buffer + Offset;
return *static_cast<T*>(p);
return *reinterpret_cast<T*>(buffer.raw + Offset);
}
//***********************************
@ -270,11 +270,9 @@ namespace etl
template <typename T, size_t Offset>
ETL_NODISCARD const T& ref_at_offset() const
{
ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Size of T is too large");
ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Size of type too large for storage");
char* p = buffer + Offset;
return *static_cast<const T*>(p);
return *reinterpret_cast<const T*>(buffer.raw + Offset);
}
//***********************************
@ -411,38 +409,44 @@ namespace etl
/// Emplace from parameters
//***********************************
template <typename T, typename... TArgs>
void emplace(TArgs... args)
T& emplace(TArgs... args)
{
ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception));
::new (pbuffer) T(etl::forward<TArgs>(args)...);
return ref<T>();
}
//***********************************
/// Emplace from parameters at offset
//***********************************
template <typename T, typename... TArgs>
void emplace_at_offset(size_t offset, TArgs... args)
T& emplace_at_offset(size_t offset, TArgs... args)
{
ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
char* p = pbuffer + offset;
ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception));
::new (p) T(etl::forward<TArgs>(args)...);
return ref_at_offset<T>(offset);
}
//***********************************
/// Emplace from parameters at offset
//***********************************
template <typename T, size_t Offset, typename... TArgs>
void emplace_at_offset(TArgs... args)
T& emplace_at_offset(TArgs... args)
{
ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
char* p = pbuffer + Offset;
ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception));
::new (p) T(etl::forward<TArgs>(args)...);
return ref_at_offset<T, Offset>();
}
#endif
@ -455,7 +459,9 @@ namespace etl
ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception));
return *reinterpret_cast<T*>(pbuffer);
T* p = reinterpret_cast<T*>(pbuffer);
return *p;
}
//***********************************
@ -467,7 +473,9 @@ namespace etl
ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception));
return *reinterpret_cast<const T*>(pbuffer);
const T* p = reinterpret_cast<const T*>(pbuffer);
return *p;
}
//***********************************
@ -477,10 +485,11 @@ namespace etl
ETL_NODISCARD T& ref_at_offset(size_t offset)
{
ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
char* p = pbuffer + offset;
ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception));
return *reinterpret_cast<T*>(p);
T* p = reinterpret_cast<T*>(pbuffer + offset);
return *p;
}
//***********************************
@ -490,10 +499,11 @@ namespace etl
ETL_NODISCARD const T& ref_at_offset(size_t offset) const
{
ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
char* p = pbuffer + offset;
ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception));
return *reinterpret_cast<const T*>(p);
const T* p = reinterpret_cast<const T*>(pbuffer + offset);
return *p;
}
//***********************************
@ -503,10 +513,11 @@ namespace etl
ETL_NODISCARD T& ref_at_offset()
{
ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
char* p = pbuffer + Offset;
ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception));
return *reinterpret_cast<T*>(p);
T* p = reinterpret_cast<T*>(pbuffer + Offset);
return *p;
}
//***********************************
@ -516,10 +527,11 @@ namespace etl
ETL_NODISCARD const T& ref_at_offset() const
{
ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
char* p = pbuffer + Offset;
ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception));
return *reinterpret_cast<const T*>(p);
const T* p = reinterpret_cast<const T*>(pbuffer + Offset);
return *p;
}
//***********************************

View File

@ -54,6 +54,27 @@ SOFTWARE.
namespace etl
{
//*****************************************************************************
/// Obtain the address represented by p without forming a reference to the object pointed to by p.
/// Defined when not using the STL or C++20
//*****************************************************************************
template <typename T>
ETL_CONSTEXPR T* to_address(T* p)
{
return p;
}
//*****************************************************************************
/// Obtain the address represented by itr without forming a reference to the object pointed to by itr.
/// Requires that the iterator defines operator->()
/// Defined when not using the STL or C++20
//*****************************************************************************
template <typename Iterator>
ETL_CONSTEXPR typename Iterator::pointer to_address(const Iterator& itr)
{
return etl::to_address(itr.operator->());
}
#if ETL_USING_STL
//*****************************************************************************
/// Fills uninitialised memory range with a value.
@ -112,7 +133,7 @@ namespace etl
while (o_begin != o_end)
{
::new (static_cast<void*>(etl::addressof(*o_begin))) value_type(value);
::new (static_cast<void*>(etl::to_address(o_begin))) value_type(value);
++o_begin;
}
@ -259,7 +280,7 @@ namespace etl
while (i_begin != i_end)
{
::new (static_cast<void*>(etl::addressof(*o_end))) value_type(*i_begin);
::new (static_cast<void*>(etl::to_address(o_end))) value_type(*i_begin);
++i_begin;
++o_end;
}
@ -407,7 +428,7 @@ namespace etl
while (i_begin != i_end)
{
::new (static_cast<void*>(etl::addressof(*o_end))) value_type(etl::move(*i_begin));
::new (static_cast<void*>(etl::to_address(o_end))) value_type(etl::move(*i_begin));
++i_begin;
++o_end;
}
@ -532,7 +553,7 @@ namespace etl
while (n-- != 0)
{
::new (static_cast<void*>(etl::addressof(*o_end))) value_type(etl::move(*i_begin));
::new (static_cast<void*>(etl::to_address(o_end))) value_type(etl::move(*i_begin));
++i_begin;
++o_end;
}
@ -665,7 +686,7 @@ namespace etl
while (o_begin != o_end)
{
::new (static_cast<void*>(etl::addressof(*o_begin))) value_type;
::new (static_cast<void*>(etl::to_address(o_begin))) value_type;
++o_begin;
}
}
@ -844,7 +865,7 @@ namespace etl
while (o_begin != o_end)
{
::new (static_cast<void*>(etl::addressof(*o_begin))) value_type();
::new (static_cast<void*>(etl::to_address(o_begin))) value_type();
++o_begin;
}
}
@ -1095,7 +1116,7 @@ namespace etl
{
while (i_begin != i_end)
{
etl::destroy_at(etl::addressof(*i_begin));
etl::destroy_at(etl::to_address(i_begin));
++i_begin;
}
}
@ -1127,7 +1148,7 @@ namespace etl
while (i_begin != i_end)
{
etl::destroy_at(etl::addressof(*i_begin));
etl::destroy_at(etl::to_address(i_begin));
++i_begin;
}
}
@ -1182,7 +1203,7 @@ namespace etl
{
while (n > 0)
{
etl::destroy_at(etl::addressof(*i_begin));
etl::destroy_at(etl::to_address(i_begin));
++i_begin;
--n;
}
@ -1218,7 +1239,7 @@ namespace etl
while (n > 0)
{
etl::destroy_at(etl::addressof(*i_begin));
etl::destroy_at(etl::to_address(i_begin));
++i_begin;
--n;
}
@ -2264,13 +2285,13 @@ namespace etl
/// \param destination begin
/// \return A pointer to the destination.
//***************************************************************************
template <typename TPointer>
typename etl::enable_if<etl::is_trivially_copyable<typename etl::iterator_traits<TPointer>::value_type>::value, TPointer>::type
mem_copy(const TPointer sb, const TPointer se, TPointer db) ETL_NOEXCEPT
template <typename T>
typename etl::enable_if<etl::is_trivially_copyable<typename etl::iterator_traits<T*>::value_type>::value, T*>::type
mem_copy(const T* sb, const T* se, T* db) ETL_NOEXCEPT
{
return reinterpret_cast<TPointer>(memcpy(reinterpret_cast<void*>(db),
reinterpret_cast<void*>(sb),
sizeof(typename etl::iterator_traits<TPointer>::value_type) * static_cast<size_t>(se - sb)));
return reinterpret_cast<T*>(memcpy(reinterpret_cast<void*>(db),
reinterpret_cast<const void*>(sb),
sizeof(typename etl::iterator_traits<T*>::value_type) * static_cast<size_t>(se - sb)));
}
//***************************************************************************
@ -2280,13 +2301,13 @@ namespace etl
/// \param source length
/// \param destination begin
//***************************************************************************
template <typename TPointer>
typename etl::enable_if<etl::is_trivially_copyable<typename etl::iterator_traits<TPointer>::value_type>::value, TPointer>::type
mem_copy(const TPointer sb, size_t n, TPointer db) ETL_NOEXCEPT
template <typename T>
typename etl::enable_if<etl::is_trivially_copyable<typename etl::iterator_traits<T*>::value_type>::value, T*>::type
mem_copy(const T* sb, size_t n, T* db) ETL_NOEXCEPT
{
return reinterpret_cast<TPointer>(memcpy(reinterpret_cast<void*>(db),
reinterpret_cast<void*>(sb),
sizeof(typename etl::iterator_traits<TPointer>::value_type) * n));
return reinterpret_cast<T*>(memcpy(reinterpret_cast<void*>(db),
reinterpret_cast<const void*>(sb),
sizeof(typename etl::iterator_traits<T*>::value_type) * n));
}
//***************************************************************************
@ -2296,13 +2317,13 @@ namespace etl
/// \param source end
/// \param destination begin
//***************************************************************************
template <typename TPointer>
typename etl::enable_if<etl::is_trivially_copyable<typename etl::iterator_traits<TPointer>::value_type>::value, TPointer>::type
mem_move(const TPointer sb, const TPointer se, TPointer db) ETL_NOEXCEPT
template <typename T>
typename etl::enable_if<etl::is_trivially_copyable<typename etl::iterator_traits<T*>::value_type>::value, T*>::type
mem_move(const T* sb, const T* se, T* db) ETL_NOEXCEPT
{
return reinterpret_cast<TPointer>(memmove(reinterpret_cast<void*>(db),
reinterpret_cast<void*>(sb),
sizeof(typename etl::iterator_traits<TPointer>::value_type) * static_cast<size_t>(se - sb)));
return reinterpret_cast<T*>(memmove(reinterpret_cast<void*>(db),
reinterpret_cast<const void*>(sb),
sizeof(typename etl::iterator_traits<T*>::value_type) * static_cast<size_t>(se - sb)));
}
//***************************************************************************
@ -2312,32 +2333,32 @@ namespace etl
/// \param source length
/// \param destination begin
//***************************************************************************
template <typename TPointer>
typename etl::enable_if<etl::is_trivially_copyable<typename etl::iterator_traits<TPointer>::value_type>::value, TPointer>::type
mem_move(const TPointer sb, size_t n, TPointer db) ETL_NOEXCEPT
template <typename T>
typename etl::enable_if<etl::is_trivially_copyable<typename etl::iterator_traits<T*>::value_type>::value, T*>::type
mem_move(const T* sb, size_t n, T* db) ETL_NOEXCEPT
{
return reinterpret_cast<TPointer>(memmove(reinterpret_cast<void*>(db),
reinterpret_cast<void*>(sb),
sizeof(typename etl::iterator_traits<TPointer>::value_type) * n));
return reinterpret_cast<T*>(memmove(reinterpret_cast<void*>(db),
reinterpret_cast<const void*>(sb),
sizeof(typename etl::iterator_traits<T*>::value_type) * n));
}
//***************************************************************************
/// Template wrapper for memcmp.
/// \param source begin
/// \param source end
/// \param destination begin
/// \param sb Source begin
/// \param se Source end
/// \param db Destination begin
/// \return < 0 The first byte that does not match in both memory blocks has a lower value in 'sb' than in 'db' when evaluated as unsigned char values.
/// 0 The contents of both memory blocks are equal
/// > 0 The first byte that does not match in both memory blocks has a greater value in 'sb' than in 'db' when evaluated as unsigned char values.
//***************************************************************************
template <typename TPointer>
template <typename T>
ETL_NODISCARD
typename etl::enable_if<etl::is_trivially_copyable<typename etl::iterator_traits<TPointer>::value_type>::value, int>::type
mem_compare(const TPointer sb, const TPointer se, TPointer db) ETL_NOEXCEPT
typename etl::enable_if<etl::is_trivially_copyable<typename etl::iterator_traits<T*>::value_type>::value, int>::type
mem_compare(const T* sb, const T* se, const T* db) ETL_NOEXCEPT
{
return memcmp(reinterpret_cast<void*>(db),
reinterpret_cast<void*>(sb),
sizeof(typename etl::iterator_traits<TPointer>::value_type) * static_cast<size_t>(se - sb));
return memcmp(reinterpret_cast<const void*>(db),
reinterpret_cast<const void*>(sb),
sizeof(typename etl::iterator_traits<T*>::value_type) * static_cast<size_t>(se - sb));
}
//***************************************************************************
@ -2349,14 +2370,14 @@ namespace etl
/// 0 The contents of both memory blocks are equal
/// > 0 The first byte that does not match in both memory blocks has a greater value in 'sb' than in 'db' when evaluated as unsigned char values.
//***************************************************************************
template <typename TPointer>
template <typename T>
ETL_NODISCARD
typename etl::enable_if<etl::is_trivially_copyable<typename etl::iterator_traits<TPointer>::value_type>::value, int>::type
mem_compare(const TPointer sb, size_t n, TPointer db) ETL_NOEXCEPT
typename etl::enable_if<etl::is_trivially_copyable<typename etl::iterator_traits<T*>::value_type>::value, int>::type
mem_compare(const T* sb, size_t n, const T* db) ETL_NOEXCEPT
{
return memcmp(reinterpret_cast<void*>(db),
reinterpret_cast<void*>(sb),
sizeof(typename etl::iterator_traits<TPointer>::value_type) * n);
return memcmp(reinterpret_cast<const void*>(db),
reinterpret_cast<const void*>(sb),
sizeof(typename etl::iterator_traits<T*>::value_type) * n);
}
//***************************************************************************
@ -2384,7 +2405,7 @@ namespace etl
//***************************************************************************
template <typename TPointer, typename T>
typename etl::enable_if<etl::is_trivially_copyable<typename etl::iterator_traits<TPointer>::value_type>::value, TPointer>::type
mem_set(const TPointer db, size_t n, T value) ETL_NOEXCEPT
mem_set(TPointer db, size_t n, T value) ETL_NOEXCEPT
{
return reinterpret_cast<TPointer>(memset(reinterpret_cast<void*>(db),
static_cast<char>(value),

View File

@ -53,8 +53,6 @@ SOFTWARE.
#include "platform.h"
#if ETL_HAS_VIRTUAL_MESSAGES
#include "message.h"
#include "error_handler.h"
#include "static_assert.h"
@ -286,11 +284,39 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
#if !ETL_HAS_VIRTUAL_MESSAGES
//********************************************
void delete_message(etl::imessage* pmsg)
{
(delete_message_type<TMessageTypes>(pmsg) || ...);
}
//********************************************
template <typename TType>
bool delete_message_type(etl::imessage* pmsg)
{
if (TType::ID == pmsg->get_message_id())
{
TType* p = static_cast<TType*>(pmsg);
p->~TType();
return true;
}
else
{
return false;
}
}
#endif
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -584,11 +610,40 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
case T3::ID: static_cast<const T3*>(pmsg)->~T3(); break;
case T4::ID: static_cast<const T4*>(pmsg)->~T4(); break;
case T5::ID: static_cast<const T5*>(pmsg)->~T5(); break;
case T6::ID: static_cast<const T6*>(pmsg)->~T6(); break;
case T7::ID: static_cast<const T7*>(pmsg)->~T7(); break;
case T8::ID: static_cast<const T8*>(pmsg)->~T8(); break;
case T9::ID: static_cast<const T9*>(pmsg)->~T9(); break;
case T10::ID: static_cast<const T10*>(pmsg)->~T10(); break;
case T11::ID: static_cast<const T11*>(pmsg)->~T11(); break;
case T12::ID: static_cast<const T12*>(pmsg)->~T12(); break;
case T13::ID: static_cast<const T13*>(pmsg)->~T13(); break;
case T14::ID: static_cast<const T14*>(pmsg)->~T14(); break;
case T15::ID: static_cast<const T15*>(pmsg)->~T15(); break;
case T16::ID: static_cast<const T16*>(pmsg)->~T16(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -613,7 +668,7 @@ namespace etl
case T14::ID: ::new (p) T14(static_cast<const T14&>(msg)); break;
case T15::ID: ::new (p) T15(static_cast<const T15&>(msg)); break;
case T16::ID: ::new (p) T16(static_cast<const T16&>(msg)); break;
default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -642,7 +697,7 @@ namespace etl
case T14::ID: ::new (p) T14(static_cast<T14&&>(msg)); break;
case T15::ID: ::new (p) T15(static_cast<T15&&>(msg)); break;
case T16::ID: ::new (p) T16(static_cast<T16&&>(msg)); break;
default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
#endif
@ -879,11 +934,40 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
case T3::ID: static_cast<const T3*>(pmsg)->~T3(); break;
case T4::ID: static_cast<const T4*>(pmsg)->~T4(); break;
case T5::ID: static_cast<const T5*>(pmsg)->~T5(); break;
case T6::ID: static_cast<const T6*>(pmsg)->~T6(); break;
case T7::ID: static_cast<const T7*>(pmsg)->~T7(); break;
case T8::ID: static_cast<const T8*>(pmsg)->~T8(); break;
case T9::ID: static_cast<const T9*>(pmsg)->~T9(); break;
case T10::ID: static_cast<const T10*>(pmsg)->~T10(); break;
case T11::ID: static_cast<const T11*>(pmsg)->~T11(); break;
case T12::ID: static_cast<const T12*>(pmsg)->~T12(); break;
case T13::ID: static_cast<const T13*>(pmsg)->~T13(); break;
case T14::ID: static_cast<const T14*>(pmsg)->~T14(); break;
case T15::ID: static_cast<const T15*>(pmsg)->~T15(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -907,7 +991,7 @@ namespace etl
case T13::ID: ::new (p) T13(static_cast<const T13&>(msg)); break;
case T14::ID: ::new (p) T14(static_cast<const T14&>(msg)); break;
case T15::ID: ::new (p) T15(static_cast<const T15&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -1172,11 +1256,39 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
case T3::ID: static_cast<const T3*>(pmsg)->~T3(); break;
case T4::ID: static_cast<const T4*>(pmsg)->~T4(); break;
case T5::ID: static_cast<const T5*>(pmsg)->~T5(); break;
case T6::ID: static_cast<const T6*>(pmsg)->~T6(); break;
case T7::ID: static_cast<const T7*>(pmsg)->~T7(); break;
case T8::ID: static_cast<const T8*>(pmsg)->~T8(); break;
case T9::ID: static_cast<const T9*>(pmsg)->~T9(); break;
case T10::ID: static_cast<const T10*>(pmsg)->~T10(); break;
case T11::ID: static_cast<const T11*>(pmsg)->~T11(); break;
case T12::ID: static_cast<const T12*>(pmsg)->~T12(); break;
case T13::ID: static_cast<const T13*>(pmsg)->~T13(); break;
case T14::ID: static_cast<const T14*>(pmsg)->~T14(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -1199,7 +1311,7 @@ namespace etl
case T12::ID: ::new (p) T12(static_cast<const T12&>(msg)); break;
case T13::ID: ::new (p) T13(static_cast<const T13&>(msg)); break;
case T14::ID: ::new (p) T14(static_cast<const T14&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -1463,11 +1575,38 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
case T3::ID: static_cast<const T3*>(pmsg)->~T3(); break;
case T4::ID: static_cast<const T4*>(pmsg)->~T4(); break;
case T5::ID: static_cast<const T5*>(pmsg)->~T5(); break;
case T6::ID: static_cast<const T6*>(pmsg)->~T6(); break;
case T7::ID: static_cast<const T7*>(pmsg)->~T7(); break;
case T8::ID: static_cast<const T8*>(pmsg)->~T8(); break;
case T9::ID: static_cast<const T9*>(pmsg)->~T9(); break;
case T10::ID: static_cast<const T10*>(pmsg)->~T10(); break;
case T11::ID: static_cast<const T11*>(pmsg)->~T11(); break;
case T12::ID: static_cast<const T12*>(pmsg)->~T12(); break;
case T13::ID: static_cast<const T13*>(pmsg)->~T13(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -1489,7 +1628,7 @@ namespace etl
case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break;
case T12::ID: ::new (p) T12(static_cast<const T12&>(msg)); break;
case T13::ID: ::new (p) T13(static_cast<const T13&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -1748,11 +1887,37 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
case T3::ID: static_cast<const T3*>(pmsg)->~T3(); break;
case T4::ID: static_cast<const T4*>(pmsg)->~T4(); break;
case T5::ID: static_cast<const T5*>(pmsg)->~T5(); break;
case T6::ID: static_cast<const T6*>(pmsg)->~T6(); break;
case T7::ID: static_cast<const T7*>(pmsg)->~T7(); break;
case T8::ID: static_cast<const T8*>(pmsg)->~T8(); break;
case T9::ID: static_cast<const T9*>(pmsg)->~T9(); break;
case T10::ID: static_cast<const T10*>(pmsg)->~T10(); break;
case T11::ID: static_cast<const T11*>(pmsg)->~T11(); break;
case T12::ID: static_cast<const T12*>(pmsg)->~T12(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -1773,7 +1938,7 @@ namespace etl
case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break;
case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break;
case T12::ID: ::new (p) T12(static_cast<const T12&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -2031,11 +2196,36 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
case T3::ID: static_cast<const T3*>(pmsg)->~T3(); break;
case T4::ID: static_cast<const T4*>(pmsg)->~T4(); break;
case T5::ID: static_cast<const T5*>(pmsg)->~T5(); break;
case T6::ID: static_cast<const T6*>(pmsg)->~T6(); break;
case T7::ID: static_cast<const T7*>(pmsg)->~T7(); break;
case T8::ID: static_cast<const T8*>(pmsg)->~T8(); break;
case T9::ID: static_cast<const T9*>(pmsg)->~T9(); break;
case T10::ID: static_cast<const T10*>(pmsg)->~T10(); break;
case T11::ID: static_cast<const T11*>(pmsg)->~T11(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -2055,7 +2245,7 @@ namespace etl
case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break;
case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break;
case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -2312,11 +2502,35 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
case T3::ID: static_cast<const T3*>(pmsg)->~T3(); break;
case T4::ID: static_cast<const T4*>(pmsg)->~T4(); break;
case T5::ID: static_cast<const T5*>(pmsg)->~T5(); break;
case T6::ID: static_cast<const T6*>(pmsg)->~T6(); break;
case T7::ID: static_cast<const T7*>(pmsg)->~T7(); break;
case T8::ID: static_cast<const T8*>(pmsg)->~T8(); break;
case T9::ID: static_cast<const T9*>(pmsg)->~T9(); break;
case T10::ID: static_cast<const T10*>(pmsg)->~T10(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -2335,7 +2549,7 @@ namespace etl
case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break;
case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break;
case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -2591,11 +2805,34 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
case T3::ID: static_cast<const T3*>(pmsg)->~T3(); break;
case T4::ID: static_cast<const T4*>(pmsg)->~T4(); break;
case T5::ID: static_cast<const T5*>(pmsg)->~T5(); break;
case T6::ID: static_cast<const T6*>(pmsg)->~T6(); break;
case T7::ID: static_cast<const T7*>(pmsg)->~T7(); break;
case T8::ID: static_cast<const T8*>(pmsg)->~T8(); break;
case T9::ID: static_cast<const T9*>(pmsg)->~T9(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -2613,7 +2850,7 @@ namespace etl
case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break;
case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break;
case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -2864,11 +3101,33 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
case T3::ID: static_cast<const T3*>(pmsg)->~T3(); break;
case T4::ID: static_cast<const T4*>(pmsg)->~T4(); break;
case T5::ID: static_cast<const T5*>(pmsg)->~T5(); break;
case T6::ID: static_cast<const T6*>(pmsg)->~T6(); break;
case T7::ID: static_cast<const T7*>(pmsg)->~T7(); break;
case T8::ID: static_cast<const T8*>(pmsg)->~T8(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -2885,7 +3144,7 @@ namespace etl
case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break;
case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break;
case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -3135,11 +3394,32 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
case T3::ID: static_cast<const T3*>(pmsg)->~T3(); break;
case T4::ID: static_cast<const T4*>(pmsg)->~T4(); break;
case T5::ID: static_cast<const T5*>(pmsg)->~T5(); break;
case T6::ID: static_cast<const T6*>(pmsg)->~T6(); break;
case T7::ID: static_cast<const T7*>(pmsg)->~T7(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -3155,7 +3435,7 @@ namespace etl
case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break;
case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -3404,11 +3684,31 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
case T3::ID: static_cast<const T3*>(pmsg)->~T3(); break;
case T4::ID: static_cast<const T4*>(pmsg)->~T4(); break;
case T5::ID: static_cast<const T5*>(pmsg)->~T5(); break;
case T6::ID: static_cast<const T6*>(pmsg)->~T6(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -3423,7 +3723,7 @@ namespace etl
case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -3671,11 +3971,30 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
case T3::ID: static_cast<const T3*>(pmsg)->~T3(); break;
case T4::ID: static_cast<const T4*>(pmsg)->~T4(); break;
case T5::ID: static_cast<const T5*>(pmsg)->~T5(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -3689,7 +4008,7 @@ namespace etl
case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -3932,11 +4251,29 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
case T3::ID: static_cast<const T3*>(pmsg)->~T3(); break;
case T4::ID: static_cast<const T4*>(pmsg)->~T4(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -3949,7 +4286,7 @@ namespace etl
case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -4191,11 +4528,28 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
case T3::ID: static_cast<const T3*>(pmsg)->~T3(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -4207,7 +4561,7 @@ namespace etl
case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -4448,11 +4802,27 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
case T2::ID: static_cast<const T2*>(pmsg)->~T2(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -4463,7 +4833,7 @@ namespace etl
{
case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -4703,11 +5073,26 @@ namespace etl
{
etl::imessage* pmsg = static_cast<etl::imessage*>(data);
#if ETL_HAS_VIRTUAL_MESSAGES
pmsg->~imessage();
#else
delete_message(pmsg);
#endif
}
}
#include "private/diagnostic_pop.h"
//********************************************
void delete_message(etl::imessage* pmsg)
{
switch (pmsg->get_message_id())
{
case T1::ID: static_cast<const T1*>(pmsg)->~T1(); break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
//********************************************
void add_new_message(const etl::imessage& msg)
{
@ -4717,7 +5102,7 @@ namespace etl
switch (id)
{
case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
default: break;
default: ETL_ASSERT_FAIL(ETL_ERROR(unhandled_message_exception)); break;
}
}
@ -4741,8 +5126,5 @@ namespace etl
};
#endif
}
#else
#error "etl::message_packet is not compatible with non-virtual etl::imessage"
#endif
#endif

View File

@ -54,9 +54,7 @@ SOFTWARE.
#include "platform.h"
#include "message.h"
#include "shared_message.h"
#if ETL_HAS_VIRTUAL_MESSAGES
#include "message_packet.h"
#endif
#include "message_packet.h"
#include "message_types.h"
#include "alignment.h"
#include "error_handler.h"
@ -412,9 +410,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<TMessageTypes...> message_packet;
#endif
//**********************************************
message_router()
@ -562,9 +558,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -709,9 +703,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -856,9 +848,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -1002,9 +992,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -1146,9 +1134,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -1289,9 +1275,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -1431,9 +1415,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -1572,9 +1554,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8, T9> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -1711,9 +1691,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7, T8> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -1849,9 +1827,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2, T3, T4, T5, T6, T7> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -1985,9 +1961,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2, T3, T4, T5, T6> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -2120,9 +2094,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2, T3, T4, T5> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -2253,9 +2225,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2, T3, T4> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -2385,9 +2355,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2, T3> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -2516,9 +2484,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet<T1, T2> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)
@ -2646,9 +2612,7 @@ namespace etl
{
public:
#if ETL_HAS_VIRTUAL_MESSAGES
typedef etl::message_packet< T1> message_packet;
#endif
//**********************************************
message_router(etl::message_router_id_t id_)

46
include/etl/monostate.h Normal file
View File

@ -0,0 +1,46 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2025 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies 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.
******************************************************************************/
#ifndef ETL_MONOSTATE_INCLUDED
#define ETL_MONOSTATE_INCLUDED
#include "platform.h"
namespace etl
{
//***************************************************************************
/// A 'no-value' placeholder.
//***************************************************************************
struct monostate
{
};
}
#endif

View File

@ -38,7 +38,7 @@ SOFTWARE.
#include "span.h"
///\defgroup multi_multi_span multi_span multi_span
/// Scatter/Gather functionality
/// Allows Scatter/Gather functionality
///\ingroup containers
namespace etl
@ -62,36 +62,56 @@ namespace etl
//*************************************************************************
/// Iterator
//*************************************************************************
class iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, element_type>
class iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, element_type>
{
public:
friend class multi_span;
friend class const_iterator;
iterator()
: p_current(ETL_NULLPTR)
, p_end(ETL_NULLPTR)
//*****************************************
ETL_CONSTEXPR14 iterator()
: p_span_list(ETL_NULLPTR)
, p_current_span(ETL_NULLPTR)
, p_value(ETL_NULLPTR)
{
}
//*****************************************
iterator& operator ++()
ETL_CONSTEXPR14 iterator(const iterator& other)
: p_span_list(other.p_span_list)
, p_current_span(other.p_current_span)
, p_value(other.p_value)
{
if (p_current != p_end)
}
//*****************************************
ETL_CONSTEXPR14 iterator& operator =(const iterator& rhs)
{
p_span_list = rhs.p_span_list;
p_current_span = rhs.p_current_span;
p_value = rhs.p_value;
return *this;
}
//*****************************************
ETL_CONSTEXPR14 iterator& operator ++()
{
if (p_current_span != p_span_list->end())
{
++p_value;
if (p_value == p_current->end())
if (p_value == p_current_span->end())
{
do
{
++p_current;
} while ((p_current != p_end) && p_current->empty());
++p_current_span;
} while ((p_current_span != p_span_list->end()) && p_current_span->empty());
if (p_current != p_end)
if (p_current_span != p_span_list->end())
{
p_value = p_current->begin();
p_value = p_current_span->begin();
}
else
{
@ -104,7 +124,7 @@ namespace etl
}
//*****************************************
iterator operator ++(int)
ETL_CONSTEXPR14 iterator operator ++(int)
{
iterator temp = *this;
@ -113,10 +133,54 @@ namespace etl
return temp;
}
//*****************************************
ETL_CONSTEXPR14 iterator& operator --()
{
if (p_current_span == p_span_list->end())
{
--p_current_span;
p_value = p_current_span->end();
--p_value;
}
else if ((p_current_span != p_span_list->begin()) || (p_value != p_current_span->begin()))
{
if (p_value == p_current_span->begin())
{
do
{
--p_current_span;
} while ((p_current_span != p_span_list->begin()) && p_current_span->empty());
p_value = p_current_span->end();
--p_value;
}
else
{
--p_value;
}
}
else
{
p_value = ETL_NULLPTR;
}
return *this;
}
//*****************************************
ETL_CONSTEXPR14 iterator operator --(int)
{
iterator temp = *this;
operator --();
return temp;
}
//*************************************************************************
/// * operator
//*************************************************************************
reference operator *()
ETL_CONSTEXPR14 reference operator *()
{
return *p_value;
}
@ -124,7 +188,7 @@ namespace etl
//*************************************************************************
/// * operator
//*************************************************************************
const_reference operator *() const
ETL_CONSTEXPR14 const_reference operator *() const
{
return *p_value;
}
@ -132,55 +196,57 @@ namespace etl
//*************************************************************************
/// -> operator
//*************************************************************************
pointer operator ->()
ETL_CONSTEXPR14 pointer operator ->()
{
return &operator*();
return p_value;
}
//*************************************************************************
/// -> operator
//*************************************************************************
const_pointer operator ->() const
ETL_CONSTEXPR14 const_pointer operator ->() const
{
return &operator*();
return p_value;
}
//*************************************************************************
/// == operator
//*************************************************************************
friend bool operator ==(const iterator& lhs, const iterator& rhs)
ETL_CONSTEXPR14 friend bool operator ==(const iterator& lhs, const iterator& rhs)
{
return (lhs.p_current == rhs.p_current);
return (lhs.p_current_span == rhs.p_current_span) && (lhs.p_value == rhs.p_value);
}
//*************************************************************************
/// != operator
//*************************************************************************
friend bool operator !=(const iterator& lhs, const iterator& rhs)
ETL_CONSTEXPR14 friend bool operator !=(const iterator& lhs, const iterator& rhs)
{
return !(lhs == rhs);
}
private:
typedef const span_type* span_pointer;
typedef const span_list_type* span_list_pointer;
typedef typename span_list_type::iterator span_list_iterator;
//*****************************************
iterator(span_list_iterator p_current_, span_list_iterator p_end_)
: p_current(p_current_)
, p_end(p_end_)
ETL_CONSTEXPR14 iterator(const span_list_type& span_list_, span_list_iterator p_current_span_)
: p_span_list(&span_list_)
, p_current_span(p_current_span_)
, p_value(ETL_NULLPTR)
{
if (p_current != p_end)
if (p_current_span != p_span_list->end())
{
while ((p_current != p_end) && p_current->empty())
while ((p_current_span != p_span_list->end()) && p_current_span->empty())
{
++p_current;
++p_current_span;
}
if (p_current != p_end)
if (p_current_span != p_span_list->end())
{
p_value = p_current->begin();
p_value = p_current_span->begin();
}
else
{
@ -189,13 +255,216 @@ namespace etl
}
}
typedef const span_type* span_list_pointer;
span_list_pointer p_current;
span_list_pointer p_end;
span_list_pointer p_span_list;
span_pointer p_current_span;
pointer p_value;
};
//*************************************************************************
/// Const Iterator
//*************************************************************************
class const_iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, const element_type>
{
public:
friend class multi_span;
//*****************************************
ETL_CONSTEXPR14 const_iterator()
: p_span_list(ETL_NULLPTR)
, p_current_span(ETL_NULLPTR)
, p_value(ETL_NULLPTR)
{
}
//*****************************************
ETL_CONSTEXPR14 const_iterator(const const_iterator& other)
: p_span_list(other.p_span_list)
, p_current_span(other.p_current_span)
, p_value(other.p_value)
{
}
//*****************************************
ETL_CONSTEXPR14 const_iterator& operator =(const const_iterator& rhs)
{
p_span_list = rhs.p_span_list;
p_current_span = rhs.p_current_span;
p_value = rhs.p_value;
return *this;
}
//*****************************************
ETL_CONSTEXPR14 const_iterator(const etl::multi_span<T>::iterator& other)
: p_span_list(other.p_span_list)
, p_current_span(other.p_current_span)
, p_value(other.p_value)
{
}
//*****************************************
ETL_CONSTEXPR14 const_iterator& operator =(const etl::multi_span<T>::iterator& rhs)
{
p_span_list = rhs.p_span_list;
p_current_span = rhs.p_current_span;
p_value = rhs.p_value;
return *this;
}
//*****************************************
ETL_CONSTEXPR14 const_iterator& operator ++()
{
if (p_current_span != p_span_list->end())
{
++p_value;
if (p_value == p_current_span->end())
{
do
{
++p_current_span;
} while ((p_current_span != p_span_list->end()) && p_current_span->empty());
if (p_current_span != p_span_list->end())
{
p_value = p_current_span->begin();
}
else
{
p_value = ETL_NULLPTR;
}
}
}
return *this;
}
//*****************************************
ETL_CONSTEXPR14 const_iterator operator ++(int)
{
const_iterator temp = *this;
operator ++();
return temp;
}
//*****************************************
ETL_CONSTEXPR14 const_iterator& operator --()
{
if (p_current_span == p_span_list->end())
{
--p_current_span;
p_value = p_current_span->end();
--p_value;
}
else if ((p_current_span != p_span_list->begin()) || (p_value != p_current_span->begin()))
{
if (p_value == p_current_span->begin())
{
do
{
--p_current_span;
} while ((p_current_span != p_span_list->begin()) && p_current_span->empty());
p_value = p_current_span->end();
--p_value;
}
else
{
--p_value;
}
}
else
{
p_value = ETL_NULLPTR;
}
return *this;
}
//*****************************************
ETL_CONSTEXPR14 const_iterator operator --(int)
{
const_iterator temp = *this;
operator --();
return temp;
}
//*************************************************************************
/// * operator
//*************************************************************************
ETL_CONSTEXPR14 const_reference operator *() const
{
return *p_value;
}
//*************************************************************************
/// -> operator
//*************************************************************************
ETL_CONSTEXPR14 const_pointer operator ->() const
{
return p_value;
}
//*************************************************************************
/// == operator
//*************************************************************************
ETL_CONSTEXPR14 friend bool operator ==(const const_iterator& lhs, const const_iterator& rhs)
{
return (lhs.p_current_span == rhs.p_current_span) && (lhs.p_value == rhs.p_value);
}
//*************************************************************************
/// != operator
//*************************************************************************
ETL_CONSTEXPR14 friend bool operator !=(const const_iterator& lhs, const const_iterator& rhs)
{
return !(lhs == rhs);
}
private:
typedef const span_type* span_pointer;
typedef const span_list_type* span_list_pointer;
typedef const typename span_list_type::iterator span_list_iterator;
//*****************************************
ETL_CONSTEXPR14 const_iterator(const span_list_type& span_list_, span_list_iterator p_current_span_)
: p_span_list(&span_list_)
, p_current_span(p_current_span_)
, p_value(ETL_NULLPTR)
{
if (p_current_span != p_span_list->end())
{
while ((p_current_span != p_span_list->end()) && p_current_span->empty())
{
++p_current_span;
}
if (p_current_span != p_span_list->end())
{
p_value = p_current_span->begin();
}
else
{
p_value = ETL_NULLPTR;
}
}
}
span_list_pointer p_span_list;
span_pointer p_current_span;
const_pointer p_value;
};
typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
typedef ETL_OR_STD::reverse_iterator<const_iterator> const_reverse_iterator;
//*************************************************************************
/// Constructor.
//*************************************************************************
@ -229,7 +498,7 @@ namespace etl
//*************************************************************************
template <typename TIterator>
ETL_CONSTEXPR14 multi_span(TIterator begin_, TIterator end_)
: span_list(etl::addressof(*begin_), etl::distance(begin_, end_))
: span_list(etl::to_address(begin_), etl::distance(begin_, end_))
{
}
@ -238,7 +507,7 @@ namespace etl
//*************************************************************************
template <typename TIterator>
ETL_CONSTEXPR14 multi_span(TIterator begin_, size_t length_)
: span_list(etl::addressof(*begin_), length_)
: span_list(etl::to_address(begin_), length_)
{
}
@ -253,7 +522,7 @@ namespace etl
//*************************************************************************
/// Assignment operator
//*************************************************************************
ETL_CONSTEXPR14 multi_span& operator = (const multi_span & other)
ETL_CONSTEXPR14 multi_span& operator =(const multi_span & other)
{
span_list = other.span_list;
@ -265,7 +534,15 @@ namespace etl
//*************************************************************************
ETL_CONSTEXPR14 iterator begin() const
{
return iterator(span_list.begin(), span_list.end());
return iterator(span_list, span_list.begin());
}
//*************************************************************************
///
//*************************************************************************
ETL_CONSTEXPR14 const_iterator cbegin() const
{
return const_iterator(span_list, span_list.cbegin());
}
//*************************************************************************
@ -273,7 +550,66 @@ namespace etl
//*************************************************************************
ETL_CONSTEXPR14 iterator end() const
{
return iterator(span_list.end(), span_list.end());
return iterator(span_list, span_list.end());
}
//*************************************************************************
///
//*************************************************************************
ETL_CONSTEXPR14 const_iterator cend() const
{
return const_iterator(span_list, span_list.cend());
}
//*************************************************************************
///
//*************************************************************************
ETL_CONSTEXPR14 reverse_iterator rbegin() const
{
return reverse_iterator(end());
}
//*************************************************************************
///
//*************************************************************************
ETL_CONSTEXPR14 reverse_iterator crbegin() const
{
return const_reverse_iterator(cend());
}
//*************************************************************************
///
//*************************************************************************
ETL_CONSTEXPR14 reverse_iterator rend() const
{
return reverse_iterator(begin());
}
//*************************************************************************
///
//*************************************************************************
ETL_CONSTEXPR14 const_reverse_iterator crend() const
{
return const_reverse_iterator(cbegin());
}
//*************************************************************************
/// Returns a reference to the indexed value.
//*************************************************************************
ETL_CONSTEXPR14 reference operator[](size_t i) const
{
// Find the span in the span list.
size_t number_of_spans = span_list.size();
size_t index = 0;
while ((i >= span_list[index].size()) && (index < number_of_spans))
{
i -= span_list[index].size();
++index;
}
return span_list[index][i];
}
//*************************************************************************

View File

@ -30,25 +30,43 @@ SOFTWARE.
#define ETL_NTH_TYPE_INCLUDED
#include "platform.h"
#include "static_assert.h"
#if ETL_NOT_USING_CPP11
#if !defined(ETL_IN_UNIT_TEST)
#error NOT SUPPORTED FOR C++03 OR BELOW
#endif
#else
namespace etl
{
#if ETL_USING_CPP11
template <size_t N, typename T1, typename... TRest>
namespace private_nth_type
{
//***********************************
template <size_t N, typename T1, typename... TRest>
struct nth_type_helper
{
using type = typename nth_type_helper<N - 1U, TRest...>::type;
};
template <typename T1, typename... TRest>
struct nth_type_helper<0U, T1, TRest...>
{
using type = T1;
};
}
//***********************************
template <size_t N, typename... TTypes>
struct nth_type
{
using type = typename nth_type<N - 1U, TRest...>::type;
};
template <typename T1, typename... TRest>
struct nth_type<0U, T1, TRest...>
{
using type = T1;
ETL_STATIC_ASSERT(N < sizeof...(TTypes), "etl::nth_type index 'N' out of bounds");
using type = typename private_nth_type::nth_type_helper<N, TTypes...>::type;
};
//***********************************
template <size_t N, typename... TTypes>
using nth_type_t = typename nth_type<N, TTypes...>::type;
#endif
}
#endif
#endif

View File

@ -484,14 +484,16 @@ namespace etl
//*************************************************************************
template <typename... TArgs>
ETL_CONSTEXPR20_STL
void emplace(TArgs&& ... args)
T& emplace(TArgs&& ... args)
{
storage.construct(etl::forward<TArgs>(args)...);
return storage.u.value;
}
#else
//*************************************************************************
/// Emplaces a value.
/// 1 parameter.
/// 0 parameters.
//*************************************************************************
T& emplace()
{
@ -1048,14 +1050,16 @@ namespace etl
//*************************************************************************
template <typename... TArgs>
ETL_CONSTEXPR14
void emplace(TArgs&& ... args)
T& emplace(TArgs&& ... args)
{
storage.construct(etl::forward<TArgs>(args)...);
return storage.value;
}
#else
//*************************************************************************
/// Emplaces a value.
/// 1 parameter.
/// 0 parameters.
//*************************************************************************
T& emplace()
{

View File

@ -134,7 +134,7 @@ namespace etl
inline constexpr size_t parameter_pack_v = etl::parameter_pack<TTypes...>::template index_of_type<T>::value;
#endif
#if ETL_USING_CPP17 && (!ETL_USING_GCC_COMPILER || (__GNUC__ > 7))
#if ETL_USING_CPP17 && !ETL_USING_GCC_COMPILER
//***********************************
template <typename... TTypes>
template <typename T>

View File

@ -314,7 +314,7 @@ SOFTWARE.
//*************************************
// The macros below are dependent on the profile.
// C++11
#if ETL_USING_CPP11 && !defined(ETL_FORCE_NO_ADVANCED_CPP)
#if ETL_USING_CPP11
#define ETL_CONSTEXPR constexpr
#define ETL_CONSTEXPR11 constexpr // Synonym for ETL_CONSTEXPR
#define ETL_CONSTANT constexpr
@ -354,10 +354,16 @@ SOFTWARE.
//*************************************
// C++14
#if ETL_USING_CPP14 && !defined(ETL_FORCE_NO_ADVANCED_CPP)
#define ETL_CONSTEXPR14 constexpr
#define ETL_DEPRECATED [[deprecated]]
#define ETL_DEPRECATED_REASON(reason) [[deprecated(reason)]]
#if ETL_USING_CPP14
#define ETL_CONSTEXPR14 constexpr
#if !defined(ETL_IN_UNIT_TEST)
#define ETL_DEPRECATED [[deprecated]]
#define ETL_DEPRECATED_REASON(reason) [[deprecated(reason)]]
#else
#define ETL_DEPRECATED
#define ETL_DEPRECATED_REASON(reason)
#endif
#else
#define ETL_CONSTEXPR14
#define ETL_DEPRECATED
@ -366,7 +372,7 @@ SOFTWARE.
//*************************************
// C++17
#if ETL_USING_CPP17 && !defined(ETL_FORCE_NO_ADVANCED_CPP)
#if ETL_USING_CPP17
#define ETL_CONSTEXPR17 constexpr
#define ETL_IF_CONSTEXPR constexpr
#define ETL_NODISCARD [[nodiscard]]
@ -384,7 +390,7 @@ SOFTWARE.
//*************************************
// C++20
#if ETL_USING_CPP20 && !defined(ETL_FORCE_NO_ADVANCED_CPP)
#if ETL_USING_CPP20
#define ETL_LIKELY [[likely]]
#define ETL_UNLIKELY [[unlikely]]
#define ETL_CONSTEXPR20 constexpr
@ -410,7 +416,7 @@ SOFTWARE.
//*************************************
// C++23
#if ETL_USING_CPP23 && !defined(ETL_FORCE_NO_ADVANCED_CPP)
#if ETL_USING_CPP23
#define ETL_ASSUME(expression) [[assume(expression)]]
#else
#define ETL_ASSUME ETL_DO_NOTHING
@ -468,6 +474,15 @@ SOFTWARE.
#else
#define ETL_HAS_ATOMIC 0
#endif
#if ((ETL_USING_CPP17 && (ETL_USING_STL || defined(ETL_IN_UNIT_TEST))) || \
defined(ETL_COMPILER_ARM5) || \
defined(ETL_COMPILER_ARM6) || \
defined(ETL_COMPILER_GCC) || \
defined(ETL_COMPILER_CLANG))
#define ETL_HAS_ATOMIC_ALWAYS_LOCK_FREE 1
#else
#define ETL_HAS_ATOMIC_ALWAYS_LOCK_FREE 0
#endif
#endif
//*************************************
@ -494,6 +509,26 @@ SOFTWARE.
#define ETL_HAS_INITIALIZER_LIST 0
#endif
//*************************************
// Determine if the ETL should use __attribute__((packed).
#if defined(ETL_COMPILER_CLANG) || defined(ETL_COMPILER_GCC) || defined(ETL_COMPILER_INTEL) || defined(ETL_COMPILER_ARM6)
#define ETL_PACKED_CLASS(class_type) class __attribute__((packed)) class_type
#define ETL_PACKED_STRUCT(struct_type) struct __attribute__((packed)) struct_type
#define ETL_END_PACKED
#define ETL_HAS_PACKED 1
#elif defined(ETL_COMPILER_MICROSOFT)
#define ETL_PACKED_CLASS(class_type) __pragma(pack(push, 1)) class class_type
#define ETL_PACKED_STRUCT(struct_type) __pragma(pack(push, 1)) struct struct_type
#define ETL_PACKED
#define ETL_END_PACKED __pragma(pack(pop))
#define ETL_HAS_PACKED 1
#else
#define ETL_PACKED_CLASS(class_type) class class_type
#define ETL_PACKED_STRUCT(struct_type) struct struct_type
#define ETL_END_PACKED
#define ETL_HAS_PACKED 0
#endif
//*************************************
// Check for availability of certain builtins
#include "profiles/determine_builtin_support.h"
@ -538,6 +573,7 @@ namespace etl
static ETL_CONSTANT bool has_8bit_types = (ETL_USING_8BIT_TYPES == 1);
static ETL_CONSTANT bool has_64bit_types = (ETL_USING_64BIT_TYPES == 1);
static ETL_CONSTANT bool has_atomic = (ETL_HAS_ATOMIC == 1);
static ETL_CONSTANT bool has_atomic_always_lock_free = (ETL_HAS_ATOMIC_ALWAYS_LOCK_FREE == 1);
static ETL_CONSTANT bool has_nullptr = (ETL_HAS_NULLPTR == 1);
static ETL_CONSTANT bool has_char8_t = (ETL_HAS_CHAR8_T == 1);
static ETL_CONSTANT bool has_native_char8_t = (ETL_HAS_NATIVE_CHAR8_T == 1);
@ -552,6 +588,7 @@ namespace etl
static ETL_CONSTANT bool has_mutable_array_view = (ETL_HAS_MUTABLE_ARRAY_VIEW == 1);
static ETL_CONSTANT bool has_ideque_repair = (ETL_HAS_IDEQUE_REPAIR == 1);
static ETL_CONSTANT bool has_virtual_messages = (ETL_HAS_VIRTUAL_MESSAGES == 1);
static ETL_CONSTANT bool has_packed = (ETL_HAS_PACKED == 1);
static ETL_CONSTANT bool has_chrono_literals_day = (ETL_HAS_CHRONO_LITERALS_DAY == 1);
static ETL_CONSTANT bool has_chrono_literals_weekday = (ETL_HAS_CHRONO_LITERALS_WEEKDAY == 1);
static ETL_CONSTANT bool has_chrono_literals_month = (ETL_HAS_CHRONO_LITERALS_MONTH == 1);

View File

@ -148,6 +148,8 @@ namespace etl
public:
typedef size_t size_type;
typedef typename etl::make_unsigned<ETL_BITSET_ELEMENT_TYPE>::type element_type;
typedef element_type element_t; // Backward compatibility

View File

@ -171,6 +171,7 @@ namespace etl
typedef TElement element_type;
typedef TElement* pointer;
typedef const TElement* const_pointer;
typedef size_t size_type;
static ETL_CONSTANT size_t npos = etl::integral_limits<size_t>::max;
static ETL_CONSTANT size_t Bits_Per_Element = etl::integral_limits<TElement>::bits;
@ -1937,6 +1938,8 @@ namespace etl
typedef typename etl::private_bitset::bitset_common<Active_Bits, TElement>::span_type span_type;
typedef typename etl::private_bitset::bitset_common<Active_Bits, TElement>::const_span_type const_span_type;
using etl::private_bitset::bitset_common<Active_Bits, TElement>::Bits_Per_Element;
using etl::private_bitset::bitset_common<Active_Bits, TElement>::All_Set_Element;
using etl::private_bitset::bitset_common<Active_Bits, TElement>::All_Clear_Element;
@ -2826,6 +2829,8 @@ namespace etl
{
public:
typedef size_t size_type;
typedef etl::private_bitset::bitset_common<0U, unsigned char>::element_type element_type;
typedef etl::private_bitset::bitset_common<0U, unsigned char>::span_type span_type;
typedef etl::private_bitset::bitset_common<0U, unsigned char>::const_span_type const_span_type;
@ -2850,6 +2855,8 @@ namespace etl
ETL_STATIC_ASSERT(etl::is_unsigned<TElement>::value, "The element type must be unsigned");
typedef size_t size_type;
typedef typename etl::private_bitset::bitset_common<Active_Bits, TElement>::element_type element_type;
typedef typename etl::private_bitset::bitset_common<Active_Bits, TElement>::span_type span_type;
typedef typename etl::private_bitset::bitset_common<Active_Bits, TElement>::const_span_type const_span_type;

View File

@ -181,7 +181,7 @@ namespace etl
private:
unsigned char value;
uint_least8_t value;
};
//***********************************************************************

View File

@ -181,15 +181,7 @@ namespace etl
private:
//***********************************************************************
/// Normalise to a in-range month
//***********************************************************************
ETL_CONSTEXPR void normalise() ETL_NOEXCEPT
{
value = ((value % 12U) == 0U) ? 12U : value;
}
unsigned char value;
uint_least8_t value;
};
//***********************************************************************
@ -302,9 +294,18 @@ namespace etl
{
if (m1.ok() && m2.ok())
{
etl::chrono::months ms(static_cast<signed>(static_cast<unsigned>(m1)) -
static_cast<signed>(static_cast<unsigned>(m2)) % 12);
// Calculate the signed difference.
int difference = static_cast<int>(static_cast<unsigned>(m1)) - static_cast<int>(static_cast<unsigned>(m2));
// Adjust for wrap-around.
if (difference < 0)
{
difference += 12;
}
etl::chrono::months ms(difference);
// Check for validity.
if (m1 == (m2 + ms))
{
return ms;

View File

@ -163,7 +163,7 @@ namespace etl
// Accumulator_Bits > Chunk_Bits
// Not Reflected
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, bool Reflect>
static
static ETL_CONSTEXPR14
typename etl::enable_if<(Accumulator_Bits > Chunk_Bits) && !Reflect, TAccumulator>::type
crc_update_chunk(TAccumulator crc, uint8_t value, const TAccumulator table[])
{
@ -181,7 +181,7 @@ namespace etl
// Accumulator_Bits > Chunk_Bits
// Reflected
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, bool Reflect>
static
static ETL_CONSTEXPR14
typename etl::enable_if<(Accumulator_Bits > Chunk_Bits) && Reflect, TAccumulator>::type
crc_update_chunk(TAccumulator crc, uint8_t value, const TAccumulator table[])
{
@ -199,7 +199,7 @@ namespace etl
// Accumulator_Bits == Chunk_Bits
// Not Reflected
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, bool Reflect>
static
static ETL_CONSTEXPR14
typename etl::enable_if<(Accumulator_Bits == Chunk_Bits) && !Reflect, TAccumulator>::type
crc_update_chunk(TAccumulator crc, uint8_t value, const TAccumulator table[])
{
@ -216,7 +216,7 @@ namespace etl
// Accumulator_Bits == Chunk_Bits
// Reflected
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, bool Reflect>
static
static ETL_CONSTEXPR14
typename etl::enable_if<(Accumulator_Bits == Chunk_Bits) && Reflect, TAccumulator>::type
crc_update_chunk(TAccumulator crc, uint8_t value, const TAccumulator table[])
{
@ -241,8 +241,10 @@ namespace etl
struct crc_table<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Polynomial, Reflect, 4U>
{
//*************************************************************************
#if !ETL_USING_CPP11
TAccumulator add(TAccumulator crc, uint8_t value) const
{
#endif
static ETL_CONSTANT TAccumulator table[4U] =
{
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 0U, Chunk_Bits>::value,
@ -250,7 +252,10 @@ namespace etl
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 2U, Chunk_Bits>::value,
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 3U, Chunk_Bits>::value
};
#if ETL_USING_CPP11
ETL_CONSTEXPR14 TAccumulator add(TAccumulator crc, uint8_t value) const
{
#endif
if ETL_IF_CONSTEXPR(Reflect)
{
crc = crc_update_chunk<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Reflect>(crc, value, table);
@ -269,6 +274,10 @@ namespace etl
return crc;
}
};
#if ETL_USING_CPP11
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, TAccumulator Polynomial, bool Reflect>
ETL_CONSTANT TAccumulator crc_table<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Polynomial, Reflect, 4U>::table[4U];
#endif
//*********************************
// Table size of 16.
@ -276,8 +285,10 @@ namespace etl
struct crc_table<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Polynomial, Reflect, 16U>
{
//*************************************************************************
#if !ETL_USING_CPP11
TAccumulator add(TAccumulator crc, uint8_t value) const
{
#endif
static ETL_CONSTANT TAccumulator table[16U] =
{
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 0U, Chunk_Bits>::value,
@ -297,7 +308,10 @@ namespace etl
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 14U, Chunk_Bits>::value,
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 15U, Chunk_Bits>::value
};
#if ETL_USING_CPP11
ETL_CONSTEXPR14 TAccumulator add(TAccumulator crc, uint8_t value) const
{
#endif
if ETL_IF_CONSTEXPR(Reflect)
{
crc = crc_update_chunk<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Reflect>(crc, value, table);
@ -312,6 +326,10 @@ namespace etl
return crc;
}
};
#if ETL_USING_CPP11
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, TAccumulator Polynomial, bool Reflect>
ETL_CONSTANT TAccumulator crc_table<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Polynomial, Reflect, 16U>::table[16U];
#endif
//*********************************
// Table size of 256.
@ -319,9 +337,11 @@ namespace etl
struct crc_table<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Polynomial, Reflect, 256U>
{
//*************************************************************************
#if !ETL_USING_CPP11
TAccumulator add(TAccumulator crc, uint8_t value) const
{
static ETL_CONSTANT TAccumulator table[256U] =
#endif
static ETL_CONSTANT TAccumulator table[256U]=
{
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 0U, Chunk_Bits>::value,
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 1U, Chunk_Bits>::value,
@ -580,13 +600,20 @@ namespace etl
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 254U, Chunk_Bits>::value,
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 255U, Chunk_Bits>::value
};
#if ETL_USING_CPP11
ETL_CONSTEXPR14 TAccumulator add(TAccumulator crc, uint8_t value) const
{
#endif
crc = crc_update_chunk<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Reflect>(crc, value, table);
return crc;
}
};
#if ETL_USING_CPP11
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, TAccumulator Polynomial, bool Reflect>
ETL_CONSTANT TAccumulator crc_table<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Polynomial, Reflect, 256U>::table[256U];
#endif
//*****************************************************************************
// CRC Policies.
//*****************************************************************************
@ -615,7 +642,7 @@ namespace etl
}
//*************************************************************************
accumulator_type final(accumulator_type crc) const
ETL_CONSTEXPR accumulator_type final(accumulator_type crc) const
{
return crc ^ TCrcParameters::Xor_Out;
}
@ -643,7 +670,7 @@ namespace etl
}
//*************************************************************************
accumulator_type final(accumulator_type crc) const
ETL_CONSTEXPR accumulator_type final(accumulator_type crc) const
{
return crc ^ TCrcParameters::Xor_Out;
}
@ -671,7 +698,7 @@ namespace etl
}
//*************************************************************************
accumulator_type final(accumulator_type crc) const
ETL_CONSTEXPR accumulator_type final(accumulator_type crc) const
{
return crc ^ TCrcParameters::Xor_Out;
}
@ -691,7 +718,7 @@ namespace etl
//*************************************************************************
/// Default constructor.
//*************************************************************************
crc_type()
ETL_CONSTEXPR14 crc_type()
{
this->reset();
}
@ -702,7 +729,7 @@ namespace etl
/// \param end End of the range.
//*************************************************************************
template<typename TIterator>
crc_type(TIterator begin, const TIterator end)
ETL_CONSTEXPR14 crc_type(TIterator begin, const TIterator end)
{
this->reset();
this->add(begin, end);

View File

@ -66,11 +66,11 @@ namespace etl
//***********************************
template <typename TDelegate, typename TReturn, typename TParam>
struct call_if_impl
{
{
etl::optional<TReturn> call_if(TParam param)
{
TDelegate& d = static_cast<TDelegate&>(*this);
TDelegate& d = static_cast<TDelegate&>(*this);
etl::optional<TReturn> result;
if (d.is_valid())
@ -88,8 +88,8 @@ namespace etl
{
bool call_if()
{
TDelegate& d = static_cast<TDelegate&>(*this);
TDelegate& d = static_cast<TDelegate&>(*this);
if (d.is_valid())
{
d();
@ -168,6 +168,22 @@ namespace etl
}
};
//*****************************************************************
/// The tag to identify an etl::delegate.
///\ingroup delegate
//*****************************************************************
struct delegate_tag
{
};
//***************************************************************************
/// is_delegate
//***************************************************************************
template <typename T>
struct is_delegate : etl::bool_constant<etl::is_base_of<delegate_tag, T>::value>
{
};
//*************************************************************************
/// Declaration.
//*************************************************************************
@ -175,14 +191,19 @@ namespace etl
class delegate;
template <typename TReturn, typename TParam>
class delegate<TReturn(TParam)> : public private_delegate::call_if_impl<delegate<TReturn(TParam)>, TReturn, TParam>
class delegate<TReturn(TParam)> : public private_delegate::call_if_impl<delegate<TReturn(TParam)>, TReturn, TParam>,
public delegate_tag
{
private:
typedef delegate<TReturn(TParam)> delegate_type;
public:
typedef TReturn (*function_type)(TParam);
typedef TReturn return_type;
typedef TParam argument_type;
using private_delegate::call_if_impl<delegate<TReturn(TParam)>, TReturn, TParam>::call_if;
//*************************************************************************
@ -204,7 +225,7 @@ namespace etl
// Construct from a functor.
//*************************************************************************
template <typename TFunctor>
delegate(TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, int>::type = 0)
delegate(TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, int>::type = 0)
{
assign((void*)(&instance), functor_stub<TFunctor>);
}
@ -213,7 +234,7 @@ namespace etl
// Construct from a const functor.
//*************************************************************************
template <typename TFunctor>
delegate(const TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, int>::type = 0)
delegate(const TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, int>::type = 0)
{
assign((void*)(&instance), const_functor_stub<TFunctor>);
}
@ -232,7 +253,7 @@ namespace etl
//*************************************************************************
template <typename TFunctor>
static
typename etl::enable_if<etl::is_class<TFunctor>::value &&!etl::is_same<delegate_type, TFunctor>::value, delegate>::type
typename etl::enable_if<etl::is_class<TFunctor>::value &&!is_delegate<TFunctor>::value, delegate>::type
create(TFunctor& instance)
{
return delegate((void*)(&instance), functor_stub<TFunctor>);
@ -243,7 +264,7 @@ namespace etl
//*************************************************************************
template <typename TFunctor>
static
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate>::type
create(const TFunctor& instance)
{
return delegate((void*)(&instance), const_functor_stub<TFunctor>);
@ -330,7 +351,7 @@ namespace etl
/// Set from Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, void>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, void>::type
set(TFunctor& instance)
{
assign((void*)(&instance), functor_stub<TFunctor>);
@ -340,7 +361,7 @@ namespace etl
/// Set from const Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, void>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, void>::type
set(const TFunctor& instance)
{
assign((void*)(&instance), const_functor_stub<TFunctor>);
@ -467,7 +488,7 @@ namespace etl
/// Create from Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate&>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate&>::type
operator =(TFunctor& instance)
{
assign((void*)(&instance), functor_stub<TFunctor>);
@ -478,7 +499,7 @@ namespace etl
/// Create from const Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate&>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate&>::type
operator =(const TFunctor& instance)
{
assign((void*)(&instance), const_functor_stub<TFunctor>);
@ -684,6 +705,10 @@ namespace etl
public:
typedef TReturn (*function_type)(void);
typedef TReturn return_type;
typedef void argument_type;
using private_delegate::call_if_impl< delegate<TReturn(void)>, TReturn, void>::call_if;
//*************************************************************************
@ -705,7 +730,7 @@ namespace etl
// Construct from functor.
//*************************************************************************
template <typename TFunctor>
delegate(TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, int>::type = 0)
delegate(TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, int>::type = 0)
{
assign((void*)(&instance), functor_stub<TFunctor>);
}
@ -714,7 +739,7 @@ namespace etl
// Construct from const functor.
//*************************************************************************
template <typename TFunctor>
delegate(const TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, int>::type = 0)
delegate(const TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, int>::type = 0)
{
assign((void*)(&instance), const_functor_stub<TFunctor>);
}
@ -733,7 +758,7 @@ namespace etl
//*************************************************************************
template <typename TFunctor>
static
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate>::type
create(TFunctor& instance)
{
return delegate((void*)(&instance), functor_stub<TFunctor>);
@ -744,7 +769,7 @@ namespace etl
//*************************************************************************
template <typename TFunctor>
static
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate>::type
create(const TFunctor& instance)
{
return delegate((void*)(&instance), const_functor_stub<TFunctor>);
@ -831,7 +856,7 @@ namespace etl
/// Set from Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, void>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, void>::type
set(TFunctor& instance)
{
assign((void*)(&instance), functor_stub<TFunctor>);
@ -841,7 +866,7 @@ namespace etl
/// Set from const Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, void>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, void>::type
set(const TFunctor& instance)
{
assign((void*)(&instance), const_functor_stub<TFunctor>);
@ -968,7 +993,7 @@ namespace etl
/// Create from Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate&>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate&>::type
operator =(TFunctor& instance)
{
assign((void*)(&instance), functor_stub<TFunctor>);
@ -979,7 +1004,7 @@ namespace etl
/// Create from const Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate&>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate&>::type
operator =(const TFunctor& instance)
{
assign((void*)(&instance), const_functor_stub<TFunctor>);

View File

@ -52,6 +52,7 @@ Original publication: https://www.codeproject.com/Articles/1170503/The-Impossibl
#include "../error_handler.h"
#include "../exception.h"
#include "../type_traits.h"
#include "../function_traits.h"
#include "../utility.h"
#include "../optional.h"
@ -83,16 +84,38 @@ namespace etl
}
};
//*****************************************************************
/// The tag to identify an etl::delegate.
///\ingroup delegate
//*****************************************************************
struct delegate_tag
{
};
//***************************************************************************
/// is_delegate
//***************************************************************************
template <typename T>
struct is_delegate : etl::bool_constant<etl::is_base_of<delegate_tag, T>::value>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_delegate_v = is_delegate<T>::value;
#endif
//*************************************************************************
/// Declaration.
//*************************************************************************
template <typename T> class delegate;
template <typename T>
class delegate;
//*************************************************************************
/// Specialisation.
//*************************************************************************
template <typename TReturn, typename... TParams>
class delegate<TReturn(TParams...)> final
class delegate<TReturn(TParams...)> final : public delegate_tag
{
public:
@ -111,7 +134,7 @@ namespace etl
//*************************************************************************
// Construct from lambda or functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 delegate(TLambda& instance)
{
assign((void*)(&instance), lambda_stub<TLambda>);
@ -120,12 +143,18 @@ namespace etl
//*************************************************************************
// Construct from const lambda or functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 delegate(const TLambda& instance)
{
assign((void*)(&instance), const_lambda_stub<TLambda>);
}
//*************************************************************************
// Delete construction from rvalue reference lambda or functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
ETL_CONSTEXPR14 delegate(TLambda&& instance) = delete;
//*************************************************************************
/// Create from function (Compile time).
//*************************************************************************
@ -139,7 +168,7 @@ namespace etl
//*************************************************************************
/// Create from Lambda or Functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_NODISCARD
static ETL_CONSTEXPR14 delegate create(TLambda& instance)
{
@ -149,7 +178,7 @@ namespace etl
//*************************************************************************
/// Create from const Lambda or Functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_NODISCARD
static ETL_CONSTEXPR14 delegate create(const TLambda& instance)
{
@ -257,7 +286,7 @@ namespace etl
//*************************************************************************
/// Set from Lambda or Functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 void set(TLambda& instance)
{
assign((void*)(&instance), lambda_stub<TLambda>);
@ -266,7 +295,7 @@ namespace etl
//*************************************************************************
/// Set from const Lambda or Functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 void set(const TLambda& instance)
{
assign((void*)(&instance), const_lambda_stub<TLambda>);
@ -348,7 +377,7 @@ namespace etl
//*************************************************************************
/// Execute the delegate if valid.
/// 'void' return.
/// 'void' return delegate.
//*************************************************************************
template <typename TRet = TReturn>
ETL_CONSTEXPR14
@ -368,7 +397,7 @@ namespace etl
//*************************************************************************
/// Execute the delegate if valid.
/// Non 'void' return.
/// Non 'void' return delegate.
//*************************************************************************
template <typename TRet = TReturn>
ETL_CONSTEXPR14
@ -427,7 +456,7 @@ namespace etl
//*************************************************************************
/// Create from Lambda or Functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 delegate& operator =(TLambda& instance)
{
assign((void*)(&instance), lambda_stub<TLambda>);
@ -437,7 +466,7 @@ namespace etl
//*************************************************************************
/// Create from const Lambda or Functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 delegate& operator =(const TLambda& instance)
{
assign((void*)(&instance), const_lambda_stub<TLambda>);
@ -447,6 +476,7 @@ namespace etl
//*************************************************************************
/// Checks equality.
//*************************************************************************
ETL_NODISCARD
ETL_CONSTEXPR14 bool operator == (const delegate& rhs) const
{
return invocation == rhs.invocation;
@ -472,6 +502,7 @@ namespace etl
//*************************************************************************
/// Returns <b>true</b> if the delegate is valid.
//*************************************************************************
ETL_NODISCARD
ETL_CONSTEXPR14 operator bool() const
{
return is_valid();
@ -627,6 +658,92 @@ namespace etl
//*************************************************************************
invocation_element invocation;
};
#if ETL_USING_CPP17
//*************************************************************************
/// Make a delegate from a free function.
//*************************************************************************
template <auto Function>
ETL_NODISCARD
constexpr auto make_delegate() ETL_NOEXCEPT
{
using function_type = typename etl::function_traits<decltype(Function)>::function_type;
return etl::delegate<function_type>::template create<Function>();
}
//*************************************************************************
/// Make a delegate from a functor or lambda function.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value, void>>
ETL_NODISCARD
constexpr auto make_delegate(TLambda& instance) ETL_NOEXCEPT
{
using function_type = typename etl::function_traits<decltype(&TLambda::operator())>::function_type;
return etl::delegate<function_type>(instance);
}
//*************************************************************************
/// Make a delegate from a functor, compile time.
//*************************************************************************
template <typename T, T& Instance>
ETL_NODISCARD
constexpr auto make_delegate() ETL_NOEXCEPT
{
using function_type = typename etl::function_traits<decltype(&T::operator())>::function_type;
return etl::delegate<function_type>::template create<T, Instance>();
}
//*************************************************************************
/// Make a delegate from a member function at compile time.
//*************************************************************************
template <typename T, auto Method, T& Instance, typename = etl::enable_if_t<!etl::function_traits<decltype(Method)>::is_const>>
ETL_NODISCARD
constexpr auto make_delegate() ETL_NOEXCEPT
{
using function_type = typename etl::function_traits<decltype(Method)>::function_type;
return etl::delegate<function_type>::template create<T, Method, Instance>();
}
//*************************************************************************
/// Make a delegate from a const member function at compile time.
//*************************************************************************
template <typename T, auto Method, const T& Instance, typename = etl::enable_if_t<etl::function_traits<decltype(Method)>::is_const>>
ETL_NODISCARD
constexpr auto make_delegate() ETL_NOEXCEPT
{
using function_type = typename etl::function_traits<decltype(Method)>::function_type;
return etl::delegate<function_type>::template create<T, Method, Instance>();
}
//*************************************************************************
/// Make a delegate from a member function at run time.
//*************************************************************************
template <typename T, auto Method>
ETL_NODISCARD
constexpr auto make_delegate(T& instance) ETL_NOEXCEPT
{
using function_type = typename etl::function_traits<decltype(Method)>::function_type;
return etl::delegate<function_type>::template create<T, Method>(instance);
}
//*************************************************************************
/// Make a delegate from a member function at run time.
//*************************************************************************
template <typename T, auto Method>
ETL_NODISCARD
constexpr auto make_delegate(const T& instance) ETL_NOEXCEPT
{
using function_type = typename etl::function_traits<decltype(Method)>::function_type;
return etl::delegate<function_type>::template create<T, Method>(instance);
}
#endif
}
#endif

View File

@ -0,0 +1,54 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2023 John Wellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies 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.
******************************************************************************/
#ifndef ETL_TUPLE_ELEMENT_INCLUDED
#define ETL_TUPLE_ELEMENT_INCLUDED
namespace etl
{
#if ETL_USING_CPP11
//***************************************************************************
template <size_t Index, typename TType>
struct tuple_element;
//***************************************************************************
template<size_t Index, typename TType>
struct tuple_element<Index, const TType>
{
using type = typename etl::add_const_t<typename etl::tuple_element<Index, TType>::type>;
};
//***************************************************************************
template <size_t Index, typename TType>
using tuple_element_t = typename tuple_element<Index, TType>::type;
#endif
}
#endif

View File

@ -0,0 +1,53 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2023 John Wellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies 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.
******************************************************************************/
#ifndef ETL_TUPLE_SIZE_INCLUDED
#define ETL_TUPLE_SIZE_INCLUDED
namespace etl
{
//***************************************************************************
template <typename T>
struct tuple_size;
//***************************************************************************
template <typename T>
struct tuple_size<const T> : etl::integral_constant<size_t, tuple_size<T>::value>
{
};
//***************************************************************************
#if ETL_USING_CPP17
template <typename T>
inline constexpr size_t tuple_size_v = tuple_size<T>::value;
#endif
}
#endif

View File

@ -40,6 +40,7 @@ SOFTWARE.
#include "../error_handler.h"
#include "../null_type.h"
#include "../placement_new.h"
#include "../monostate.h"
#include <stdint.h>
@ -75,9 +76,7 @@ namespace etl
/// Monostate for variants.
///\ingroup variant
//***************************************************************************
struct monostate
{
};
typedef etl::monostate monostate;
//***************************************************************************
/// Base exception for the variant class.
@ -480,6 +479,19 @@ namespace etl
type_id = Type_Id_Lookup<T>::type_id;
}
//***************************************************************************
/// Constructor that catches any types that are not supported.
/// Forces a ETL_STATIC_ASSERT.
//***************************************************************************
template <size_t Index, typename T>
explicit variant(etl::in_place_index_t<Index>, T const& value)
: type_id(Index)
{
ETL_STATIC_ASSERT(Type_Id_Lookup<T>::type_id == Index, "Missmatched type");
::new (static_cast<T*>(data)) T(value);
type_id = Index;
}
//***************************************************************************
/// Copy constructor.
///\param other The other variant object to copy.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -31,18 +31,20 @@ SOFTWARE.
#include "../platform.h"
#include "../utility.h"
#include "../largest.h"
#include "../nth_type.h"
#include "../exception.h"
#include "../type_traits.h"
#include "../integral_limits.h"
#include "../static_assert.h"
#include "../alignment.h"
#include "../error_handler.h"
#include "../parameter_pack.h"
#include "../type_list.h"
#include "../placement_new.h"
#include "../visitor.h"
#include "../memory.h"
#include "../compare.h"
#include "../initializer_list.h"
#include "../monostate.h"
#include <stdint.h>
@ -66,95 +68,19 @@ namespace etl
{
namespace private_variant
{
//***************************************************************************
// This is a copy of the normal etl::parameter_pack, but without the static_assert
// so that the C++11 versions of do_visitor() & do_operator() do not throw a compile time error.
//***************************************************************************
template <typename... TTypes>
class parameter_pack
{
public:
static constexpr size_t size = sizeof...(TTypes);
//***************************************************************************
/// index_of_type
//***************************************************************************
template <typename T>
class index_of_type
{
private:
using type = etl::remove_cvref_t<T>;
//***********************************
template <typename Type, typename T1, typename... TRest>
struct index_of_type_helper
{
static constexpr size_t value = etl::is_same<Type, T1>::value ? 1 : 1 + index_of_type_helper<Type, TRest...>::value;
};
//***********************************
template <typename Type, typename T1>
struct index_of_type_helper<Type, T1>
{
static constexpr size_t value = 1UL;
};
public:
static_assert(etl::is_one_of<type, TTypes...>::value, "T is not in parameter pack");
/// The index value.
static constexpr size_t value = index_of_type_helper<type, TTypes...>::value - 1;
};
//***************************************************************************
/// type_from_index
//***************************************************************************
template <size_t I>
class type_from_index
{
private:
//***********************************
template <size_t II, size_t N, typename T1, typename... TRest>
struct type_from_index_helper
{
using type = typename etl::conditional<II == N, T1, typename type_from_index_helper<II, N + 1, TRest...>::type>::type;
};
//***********************************
template <size_t II, size_t N, typename T1>
struct type_from_index_helper<II, N, T1>
{
using type = T1;
};
public:
/// Template alias
using type = typename type_from_index_helper<I, 0, TTypes...>::type;
};
//***********************************
template <size_t I>
using type_from_index_t = typename type_from_index<I>::type;
};
//*******************************************
// The traits an object may have.
//*******************************************
static constexpr bool Copyable = true;
static constexpr bool Copyable = true;
static constexpr bool Non_Copyable = false;
static constexpr bool Moveable = true;
static constexpr bool Moveable = true;
static constexpr bool Non_Moveable = false;
//*******************************************
// The types of operations we can perform.
//*******************************************
static constexpr int Copy = 0;
static constexpr int Move = 1;
static constexpr int Copy = 0;
static constexpr int Move = 1;
static constexpr int Destroy = 2;
//*******************************************
@ -168,7 +94,7 @@ namespace etl
template <>
struct operation_type<void, Non_Copyable, Non_Moveable>
{
static void do_operation(int , char* , const char* )
static void do_operation(int, char*, const char*)
{
// This should never occur.
#if defined(ETL_IN_UNIT_TEST)
@ -195,9 +121,9 @@ namespace etl
default:
{
// This should never occur.
#if defined(ETL_IN_UNIT_TEST)
#if defined(ETL_IN_UNIT_TEST)
assert(false);
#endif
#endif
break;
}
}
@ -228,9 +154,9 @@ namespace etl
default:
{
// This should never occur.
#if defined(ETL_IN_UNIT_TEST)
#if defined(ETL_IN_UNIT_TEST)
assert(false);
#endif
#endif
break;
}
}
@ -261,9 +187,9 @@ namespace etl
default:
{
// This should never occur.
#if defined(ETL_IN_UNIT_TEST)
#if defined(ETL_IN_UNIT_TEST)
assert(false);
#endif
#endif
break;
}
}
@ -320,14 +246,14 @@ namespace etl
//***************************************************************************
/// variant_alternative
//***************************************************************************
//***************************************************************************
template <size_t Index, typename T>
struct variant_alternative;
template <size_t Index, typename... TTypes>
struct variant_alternative<Index, etl::variant<TTypes...>>
{
using type = typename etl::private_variant::parameter_pack<TTypes...>::template type_from_index<Index>::type;
using type = etl::nth_type_t<Index, TTypes...>;
};
template <size_t Index, typename T>
@ -374,13 +300,10 @@ namespace etl
template <typename T, typename... VTypes>
ETL_CONSTEXPR14 const T&& get(const etl::variant<VTypes...>&& v);
//***************************************************************************
/// Monostate for variants.
///\ingroup variant
//***************************************************************************
struct monostate
{
};
#if ETL_NOT_USING_CPP17
#include "variant_select_do_visitor.h"
#include "variant_select_do_operator.h"
#endif
constexpr bool operator >(etl::monostate, etl::monostate) noexcept { return false; }
constexpr bool operator <(etl::monostate, etl::monostate) noexcept { return false; }
@ -455,11 +378,6 @@ namespace etl
{
public:
//***************************************************************************
/// The type used for ids.
//***************************************************************************
using type_id_t = uint_least8_t ;
//***************************************************************************
/// get() is a friend function.
//***************************************************************************
@ -529,13 +447,13 @@ namespace etl
// Get the index of a type.
//*******************************************
template <typename T>
using index_of_type = typename etl::private_variant::parameter_pack<TTypes...>::template index_of_type<etl::remove_cvref_t<T>>;
using index_of_type = etl::type_list_index_of_type<etl::type_list<TTypes...>, etl::remove_cvref_t<T>>;
//*******************************************
// Get the type from the index.
//*******************************************
template <size_t Index>
using type_from_index = typename etl::private_variant::parameter_pack<TTypes...>::template type_from_index<Index>::type;
using type_from_index = typename etl::type_list_type_at_index<etl::type_list<TTypes...>, Index>::type;
public:
@ -546,7 +464,7 @@ namespace etl
#include "diagnostic_uninitialized_push.h"
ETL_CONSTEXPR14 variant()
{
using type = typename etl::private_variant::parameter_pack<TTypes...>::template type_from_index<0U>::type;
using type = type_from_index<0U>;
default_construct_in_place<type>(data);
operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
@ -592,7 +510,7 @@ namespace etl
ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t<Index>, TArgs&&... args)
: type_id(Index)
{
using type = typename private_variant::parameter_pack<TTypes...>:: template type_from_index_t<Index>;
using type = type_from_index<Index>;
static_assert(etl::is_one_of<type, TTypes...> ::value, "Unsupported type");
construct_in_place_args<type>(data, etl::forward<TArgs>(args)...);
@ -625,7 +543,7 @@ namespace etl
ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t<Index>, std::initializer_list<U> init, TArgs&&... args)
: type_id(Index)
{
using type = typename private_variant::parameter_pack<TTypes...>:: template type_from_index_t<Index>;
using type = type_from_index<Index>;
static_assert(etl::is_one_of<type, TTypes...> ::value, "Unsupported type");
construct_in_place_args<type>(data, init, etl::forward<TArgs>(args)...);
@ -715,7 +633,7 @@ namespace etl
operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
type_id = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
type_id = index_of_type<T>::value;
return *static_cast<T*>(data);
}
@ -737,7 +655,7 @@ namespace etl
operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
type_id = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
type_id = index_of_type<T>::value;
return *static_cast<T*>(data);
}
@ -747,9 +665,9 @@ namespace etl
/// Emplace by index with variadic constructor parameters.
//***************************************************************************
template <size_t Index, typename... TArgs>
typename etl::variant_alternative<Index, variant<TArgs...>>::type& emplace(TArgs&&... args)
typename etl::variant_alternative_t<Index, variant<TTypes...>>& emplace(TArgs&&... args)
{
static_assert(Index < etl::private_variant::parameter_pack<TTypes...>::size, "Index out of range");
static_assert(Index < sizeof...(TTypes), "Index out of range");
using type = type_from_index<Index>;
@ -769,9 +687,9 @@ namespace etl
/// Emplace by index with variadic constructor parameters.
//***************************************************************************
template <size_t Index, typename U, typename... TArgs>
typename etl::variant_alternative<Index, variant<TArgs...>>::type& emplace(std::initializer_list<U> il, TArgs&&... args)
typename etl::variant_alternative_t<Index, variant<TTypes...>>& emplace(std::initializer_list<U> il, TArgs&&... args)
{
static_assert(Index < etl::private_variant::parameter_pack<TTypes...>::size, "Index out of range");
static_assert(Index < sizeof...(TTypes), "Index out of range");
using type = type_from_index<Index>;
@ -803,7 +721,7 @@ namespace etl
construct_in_place<type>(data, etl::forward<T>(value));
operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
type_id = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<type>::value;
type_id = index_of_type<type>::value;
return *this;
}
@ -896,7 +814,7 @@ namespace etl
template <typename T, etl::enable_if_t<is_supported_type<T>(), int> = 0>
constexpr bool is_type() const noexcept
{
return (type_id == etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value);
return (type_id == index_of_type<T>::value);
}
//***************************************************************************
@ -937,7 +855,7 @@ namespace etl
#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
#else
do_visitor(v);
do_visitor<sizeof...(TTypes)>(v);
#endif
}
@ -951,7 +869,7 @@ namespace etl
#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
#else
do_visitor(v);
do_visitor<sizeof...(TTypes)>(v);
#endif
}
@ -965,7 +883,7 @@ namespace etl
#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
#else
do_operator(v);
do_operator<sizeof...(TTypes)>(v);
#endif
}
@ -979,7 +897,7 @@ namespace etl
#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
#else
do_operator(v);
do_operator<sizeof...(TTypes)>(v);
#endif
}
@ -996,7 +914,7 @@ namespace etl
#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
#else
do_visitor(v);
do_visitor<sizeof...(TTypes)>(v);
#endif
}
@ -1013,7 +931,7 @@ namespace etl
#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
#else
do_visitor(v);
do_visitor<sizeof...(TTypes)>(v);
#endif
}
@ -1030,7 +948,7 @@ namespace etl
#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
#else
do_operator(v);
do_operator<sizeof...(TTypes)>(v);
#endif
}
@ -1047,7 +965,7 @@ namespace etl
#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
#else
do_operator(v);
do_operator<sizeof...(TTypes)>(v);
#endif
}
@ -1120,103 +1038,21 @@ namespace etl
}
#else
//***************************************************************************
/// /// Call the relevant visitor.
/// Call the relevant visitor.
//***************************************************************************
template <typename TVisitor>
template <size_t NTypes, typename TVisitor>
void do_visitor(TVisitor& visitor)
{
switch (index())
{
case 0: { visitor.visit(etl::get<0>(*this)); break; }
case 1: { visitor.visit(etl::get<1>(*this)); break; }
case 2: { visitor.visit(etl::get<2>(*this)); break; }
case 3: { visitor.visit(etl::get<3>(*this)); break; }
case 4: { visitor.visit(etl::get<4>(*this)); break; }
case 5: { visitor.visit(etl::get<5>(*this)); break; }
case 6: { visitor.visit(etl::get<6>(*this)); break; }
case 7: { visitor.visit(etl::get<7>(*this)); break; }
#if !defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
case 8: { visitor.visit(etl::get<8>(*this)); break; }
case 9: { visitor.visit(etl::get<9>(*this)); break; }
case 10: { visitor.visit(etl::get<10>(*this)); break; }
case 11: { visitor.visit(etl::get<11>(*this)); break; }
case 12: { visitor.visit(etl::get<12>(*this)); break; }
case 13: { visitor.visit(etl::get<13>(*this)); break; }
case 14: { visitor.visit(etl::get<14>(*this)); break; }
case 15: { visitor.visit(etl::get<15>(*this)); break; }
#if !defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
case 16: { visitor.visit(etl::get<16>(*this)); break; }
case 17: { visitor.visit(etl::get<17>(*this)); break; }
case 18: { visitor.visit(etl::get<18>(*this)); break; }
case 19: { visitor.visit(etl::get<19>(*this)); break; }
case 20: { visitor.visit(etl::get<20>(*this)); break; }
case 21: { visitor.visit(etl::get<21>(*this)); break; }
case 22: { visitor.visit(etl::get<22>(*this)); break; }
case 23: { visitor.visit(etl::get<23>(*this)); break; }
#if !defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
case 24: { visitor.visit(etl::get<24>(*this)); break; }
case 25: { visitor.visit(etl::get<25>(*this)); break; }
case 26: { visitor.visit(etl::get<26>(*this)); break; }
case 27: { visitor.visit(etl::get<27>(*this)); break; }
case 28: { visitor.visit(etl::get<28>(*this)); break; }
case 29: { visitor.visit(etl::get<29>(*this)); break; }
case 30: { visitor.visit(etl::get<30>(*this)); break; }
case 31: { visitor.visit(etl::get<31>(*this)); break; }
#endif
#endif
#endif
default: break;
}
etl::private_variant::select_do_visitor<NTypes>::do_visitor(*this, visitor);
}
//***************************************************************************
/// /// Call the relevant visitor.
/// Call the relevant visitor.
//***************************************************************************
template <typename TVisitor>
template <size_t NTypes, typename TVisitor>
void do_visitor(TVisitor& visitor) const
{
switch (index())
{
case 0: { visitor.visit(etl::get<0>(*this)); break; }
case 1: { visitor.visit(etl::get<1>(*this)); break; }
case 2: { visitor.visit(etl::get<2>(*this)); break; }
case 3: { visitor.visit(etl::get<3>(*this)); break; }
case 4: { visitor.visit(etl::get<4>(*this)); break; }
case 5: { visitor.visit(etl::get<5>(*this)); break; }
case 6: { visitor.visit(etl::get<6>(*this)); break; }
case 7: { visitor.visit(etl::get<7>(*this)); break; }
#if !defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
case 8: { visitor.visit(etl::get<8>(*this)); break; }
case 9: { visitor.visit(etl::get<9>(*this)); break; }
case 10: { visitor.visit(etl::get<10>(*this)); break; }
case 11: { visitor.visit(etl::get<11>(*this)); break; }
case 12: { visitor.visit(etl::get<12>(*this)); break; }
case 13: { visitor.visit(etl::get<13>(*this)); break; }
case 14: { visitor.visit(etl::get<14>(*this)); break; }
case 15: { visitor.visit(etl::get<15>(*this)); break; }
#if !defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
case 16: { visitor.visit(etl::get<16>(*this)); break; }
case 17: { visitor.visit(etl::get<17>(*this)); break; }
case 18: { visitor.visit(etl::get<18>(*this)); break; }
case 19: { visitor.visit(etl::get<19>(*this)); break; }
case 20: { visitor.visit(etl::get<20>(*this)); break; }
case 21: { visitor.visit(etl::get<21>(*this)); break; }
case 22: { visitor.visit(etl::get<22>(*this)); break; }
case 23: { visitor.visit(etl::get<23>(*this)); break; }
#if !defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
case 24: { visitor.visit(etl::get<24>(*this)); break; }
case 25: { visitor.visit(etl::get<25>(*this)); break; }
case 26: { visitor.visit(etl::get<26>(*this)); break; }
case 27: { visitor.visit(etl::get<27>(*this)); break; }
case 28: { visitor.visit(etl::get<28>(*this)); break; }
case 29: { visitor.visit(etl::get<29>(*this)); break; }
case 30: { visitor.visit(etl::get<30>(*this)); break; }
case 31: { visitor.visit(etl::get<31>(*this)); break; }
#endif
#endif
#endif
default: break;
}
etl::private_variant::select_do_visitor<NTypes>::do_visitor(*this, visitor);
}
#endif
@ -1282,9 +1118,9 @@ namespace etl
}
#else
//***************************************************************************
/// Call the relevant visitor.
/// Call the relevant operator.
//***************************************************************************
template <typename TVisitor>
template <size_t NTypes, typename TVisitor>
void do_operator(TVisitor& visitor)
{
#if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
@ -1301,54 +1137,13 @@ namespace etl
ETL_STATIC_ASSERT(sizeof...(TTypes) <= 32U, "A maximum of 32 types are allowed in this variant");
switch (index())
{
case 0: visitor(etl::get<0>(*this)); break;
case 1: visitor(etl::get<1>(*this)); break;
case 2: visitor(etl::get<2>(*this)); break;
case 3: visitor(etl::get<3>(*this)); break;
case 4: visitor(etl::get<4>(*this)); break;
case 5: visitor(etl::get<5>(*this)); break;
case 6: visitor(etl::get<6>(*this)); break;
case 7: visitor(etl::get<7>(*this)); break;
#if !defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
case 8: visitor(etl::get<8>(*this)); break;
case 9: visitor(etl::get<9>(*this)); break;
case 10: visitor(etl::get<10>(*this)); break;
case 11: visitor(etl::get<11>(*this)); break;
case 12: visitor(etl::get<12>(*this)); break;
case 13: visitor(etl::get<13>(*this)); break;
case 14: visitor(etl::get<14>(*this)); break;
case 15: visitor(etl::get<15>(*this)); break;
#if !defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
case 16: visitor(etl::get<16>(*this)); break;
case 17: visitor(etl::get<17>(*this)); break;
case 18: visitor(etl::get<18>(*this)); break;
case 19: visitor(etl::get<19>(*this)); break;
case 20: visitor(etl::get<20>(*this)); break;
case 21: visitor(etl::get<21>(*this)); break;
case 22: visitor(etl::get<22>(*this)); break;
case 23: visitor(etl::get<23>(*this)); break;
#if !defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
case 24: visitor(etl::get<24>(*this)); break;
case 25: visitor(etl::get<25>(*this)); break;
case 26: visitor(etl::get<26>(*this)); break;
case 27: visitor(etl::get<27>(*this)); break;
case 28: visitor(etl::get<28>(*this)); break;
case 29: visitor(etl::get<29>(*this)); break;
case 30: visitor(etl::get<30>(*this)); break;
case 31: visitor(etl::get<31>(*this)); break;
#endif
#endif
#endif
default: break;
}
etl::private_variant::select_do_operator<NTypes>::do_operator(*this, visitor);
}
//***************************************************************************
/// Call the relevant visitor.
/// Call the relevant operator.
//***************************************************************************
template <typename TVisitor>
template <size_t NTypes, typename TVisitor>
void do_operator(TVisitor& visitor) const
{
#if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
@ -1365,48 +1160,7 @@ namespace etl
ETL_STATIC_ASSERT(sizeof...(TTypes) <= 32U, "A maximum of 32 types are allowed in this variant");
switch (index())
{
case 0: visitor(etl::get<0>(*this)); break;
case 1: visitor(etl::get<1>(*this)); break;
case 2: visitor(etl::get<2>(*this)); break;
case 3: visitor(etl::get<3>(*this)); break;
case 4: visitor(etl::get<4>(*this)); break;
case 5: visitor(etl::get<5>(*this)); break;
case 6: visitor(etl::get<6>(*this)); break;
case 7: visitor(etl::get<7>(*this)); break;
#if !defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
case 8: visitor(etl::get<8>(*this)); break;
case 9: visitor(etl::get<9>(*this)); break;
case 10: visitor(etl::get<10>(*this)); break;
case 11: visitor(etl::get<11>(*this)); break;
case 12: visitor(etl::get<12>(*this)); break;
case 13: visitor(etl::get<13>(*this)); break;
case 14: visitor(etl::get<14>(*this)); break;
case 15: visitor(etl::get<15>(*this)); break;
#if !defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
case 16: visitor(etl::get<16>(*this)); break;
case 17: visitor(etl::get<17>(*this)); break;
case 18: visitor(etl::get<18>(*this)); break;
case 19: visitor(etl::get<19>(*this)); break;
case 20: visitor(etl::get<20>(*this)); break;
case 21: visitor(etl::get<21>(*this)); break;
case 22: visitor(etl::get<22>(*this)); break;
case 23: visitor(etl::get<23>(*this)); break;
#if !defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
case 24: visitor(etl::get<24>(*this)); break;
case 25: visitor(etl::get<25>(*this)); break;
case 26: visitor(etl::get<26>(*this)); break;
case 27: visitor(etl::get<27>(*this)); break;
case 28: visitor(etl::get<28>(*this)); break;
case 29: visitor(etl::get<29>(*this)); break;
case 30: visitor(etl::get<30>(*this)); break;
case 31: visitor(etl::get<31>(*this)); break;
#endif
#endif
#endif
default: break;
}
etl::private_variant::select_do_operator<NTypes>::do_operator(*this, visitor);
}
#endif
@ -1469,7 +1223,7 @@ namespace etl
template <typename T, typename... TTypes>
ETL_CONSTEXPR14 bool holds_alternative(const etl::variant<TTypes...>& v) noexcept
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
return (Index == variant_npos) ? false : (v.index() == Index);
}
@ -1560,7 +1314,7 @@ namespace etl
template <typename T, typename... TTypes>
ETL_CONSTEXPR14 T& get(etl::variant<TTypes...>& v)
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
return get<Index>(v);
}
@ -1569,7 +1323,7 @@ namespace etl
template <typename T, typename... TTypes>
ETL_CONSTEXPR14 T&& get(etl::variant<TTypes...>&& v)
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
return get<Index>(etl::move(v));
}
@ -1578,7 +1332,7 @@ namespace etl
template <typename T, typename... TTypes>
ETL_CONSTEXPR14 const T& get(const etl::variant<TTypes...>& v)
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
return get<Index>(v);
}
@ -1587,7 +1341,7 @@ namespace etl
template <typename T, typename... TTypes>
ETL_CONSTEXPR14 const T&& get(const etl::variant<TTypes...>&& v)
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
return get<Index>(etl::move(v));
}
@ -1628,7 +1382,7 @@ namespace etl
template< class T, typename... TTypes >
ETL_CONSTEXPR14 etl::add_pointer_t<T> get_if(etl::variant<TTypes...>* pv) noexcept
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
if ((pv != nullptr) && (pv->index() == Index))
{
@ -1644,7 +1398,7 @@ namespace etl
template< typename T, typename... TTypes >
ETL_CONSTEXPR14 etl::add_pointer_t<const T> get_if(const etl::variant<TTypes...>* pv) noexcept
{
constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
constexpr size_t Index = etl::type_list_index_of_type<etl::type_list<TTypes...>, T>::value;
if ((pv != nullptr) && (pv->index() == Index))
{

View File

@ -337,90 +337,107 @@ namespace etl
//*************************************************************************
/// Constructs a value in the queue 'in place'.
/// If asserts or exceptions are enabled, throws an etl::queue_full if the queue if already full.
///\param value The value to use to construct the item to push to the queue.
///\param args The arguments to the constructor for the new item to push to the queue.
//*************************************************************************
template <typename ... Args>
void emplace(Args && ... args)
reference emplace(Args && ... args)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(queue_full));
#endif
::new (&p_buffer[in]) T(etl::forward<Args>(args)...);
reference value = p_buffer[in];
::new (&value) T(etl::forward<Args>(args)...);
add_in();
return value;
}
#else
//*************************************************************************
/// Constructs a value in the queue 'in place'.
/// Constructs a default constructed value in the queue 'in place'.
/// If asserts or exceptions are enabled, throws an etl::queue_full if the queue if already full.
///\param value The value to use to construct the item to push to the queue.
//*************************************************************************
void emplace()
reference emplace()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(queue_full));
#endif
::new (&p_buffer[in]) T();
reference value = p_buffer[in];
::new (&value) T();
add_in();
return value;
}
//*************************************************************************
/// Constructs a value in the queue 'in place'.
/// If asserts or exceptions are enabled, throws an etl::queue_full if the queue if already full.
///\param value The value to use to construct the item to push to the queue.
///\param value1 The argument to use to construct the item to push to the queue.
//*************************************************************************
template <typename T1>
void emplace(const T1& value1)
reference emplace(const T1& value1)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(queue_full));
#endif
::new (&p_buffer[in]) T(value1);
reference value = p_buffer[in];
::new (&value) T(value1);
add_in();
return value;
}
//*************************************************************************
/// Constructs a value in the queue 'in place'.
/// If asserts or exceptions are enabled, throws an etl::queue_full if the queue if already full.
///\param value The value to use to construct the item to push to the queue.
///\param value1 The first argument to use to construct the item to push to the queue.
///\param value2 The second argument to use to construct the item to push to the queue.
//*************************************************************************
template <typename T1, typename T2>
void emplace(const T1& value1, const T2& value2)
reference emplace(const T1& value1, const T2& value2)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(queue_full));
#endif
::new (&p_buffer[in]) T(value1, value2);
reference value = p_buffer[in];
::new (&value) T(value1, value2);
add_in();
return value;
}
//*************************************************************************
/// Constructs a value in the queue 'in place'.
/// If asserts or exceptions are enabled, throws an etl::queue_full if the queue if already full.
///\param value The value to use to construct the item to push to the queue.
///\param value1 The first argument to use to construct the item to push to the queue.
///\param value2 The second argument to use to construct the item to push to the queue.
///\param value3 The third argument to use to construct the item to push to the queue.
//*************************************************************************
template <typename T1, typename T2, typename T3>
void emplace(const T1& value1, const T2& value2, const T3& value3)
reference emplace(const T1& value1, const T2& value2, const T3& value3)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(queue_full));
#endif
::new (&p_buffer[in]) T(value1, value2, value3);
reference value = p_buffer[in];
::new (&value) T(value1, value2, value3);
add_in();
return value;
}
//*************************************************************************
/// Constructs a value in the queue 'in place'.
/// If asserts or exceptions are enabled, throws an etl::queue_full if the queue if already full.
///\param value The value to use to construct the item to push to the queue.
///\param value1 The first argument to use to construct the item to push to the queue.
///\param value2 The second argument to use to construct the item to push to the queue.
///\param value3 The third argument to use to construct the item to push to the queue.
///\param value4 The fourth argument to use to construct the item to push to the queue.
//*************************************************************************
template <typename T1, typename T2, typename T3, typename T4>
void emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
reference emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(queue_full));
#endif
::new (&p_buffer[in]) T(value1, value2, value3, value4);
reference value = p_buffer[in];
::new (&value) T(value1, value2, value3, value4);
add_in();
return value;
}
#endif

View File

@ -47,13 +47,13 @@ SOFTWARE.
namespace etl
{
template <size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
template <size_t Memory_Model = etl::memory_model::MEMORY_MODEL_LARGE>
class queue_spsc_atomic_base
{
public:
/// The type used for determining the size of queue.
typedef typename etl::size_type_lookup<MEMORY_MODEL>::type size_type;
typedef typename etl::size_type_lookup<Memory_Model>::type size_type;
//*************************************************************************
/// Is the queue empty?
@ -72,7 +72,7 @@ namespace etl
//*************************************************************************
bool full() const
{
size_type next_index = get_next_index(write.load(etl::memory_order_acquire), RESERVED);
size_type next_index = get_next_index(write.load(etl::memory_order_acquire), Reserved);
return (next_index == read.load(etl::memory_order_acquire));
}
@ -94,7 +94,7 @@ namespace etl
}
else
{
n = RESERVED - read_index + write_index;
n = Reserved - read_index + write_index;
}
return n;
@ -106,7 +106,7 @@ namespace etl
//*************************************************************************
size_type available() const
{
return RESERVED - size() - 1;
return Reserved - size() - 1;
}
//*************************************************************************
@ -114,7 +114,7 @@ namespace etl
//*************************************************************************
size_type capacity() const
{
return RESERVED - 1;
return Reserved - 1;
}
//*************************************************************************
@ -122,7 +122,7 @@ namespace etl
//*************************************************************************
size_type max_size() const
{
return RESERVED - 1;
return Reserved - 1;
}
protected:
@ -130,7 +130,7 @@ namespace etl
queue_spsc_atomic_base(size_type reserved_)
: write(0),
read(0),
RESERVED(reserved_)
Reserved(reserved_)
{
}
@ -151,7 +151,7 @@ namespace etl
etl::atomic<size_type> write; ///< Where to input new data.
etl::atomic<size_type> read; ///< Where to get the oldest data.
const size_type RESERVED; ///< The maximum number of items in the queue.
const size_type Reserved; ///< The maximum number of items in the queue.
private:
@ -182,12 +182,12 @@ namespace etl
/// This queue supports concurrent access by one producer and one consumer.
/// \tparam T The type of value that the queue_spsc_atomic holds.
//***************************************************************************
template <typename T, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
class iqueue_spsc_atomic : public queue_spsc_atomic_base<MEMORY_MODEL>
template <typename T, const size_t Memory_Model = etl::memory_model::MEMORY_MODEL_LARGE>
class iqueue_spsc_atomic : public queue_spsc_atomic_base<Memory_Model>
{
private:
typedef typename etl::queue_spsc_atomic_base<MEMORY_MODEL> base_t;
typedef typename etl::queue_spsc_atomic_base<Memory_Model> base_t;
public:
@ -201,7 +201,7 @@ namespace etl
using base_t::write;
using base_t::read;
using base_t::RESERVED;
using base_t::Reserved;
using base_t::get_next_index;
//*************************************************************************
@ -210,7 +210,7 @@ namespace etl
bool push(const_reference value)
{
size_type write_index = write.load(etl::memory_order_relaxed);
size_type next_index = get_next_index(write_index, RESERVED);
size_type next_index = get_next_index(write_index, Reserved);
if (next_index != read.load(etl::memory_order_acquire))
{
@ -232,7 +232,7 @@ namespace etl
bool push(rvalue_reference value)
{
size_type write_index = write.load(etl::memory_order_relaxed);
size_type next_index = get_next_index(write_index, RESERVED);
size_type next_index = get_next_index(write_index, Reserved);
if (next_index != read.load(etl::memory_order_acquire))
{
@ -257,7 +257,7 @@ namespace etl
bool emplace(Args&&... args)
{
size_type write_index = write.load(etl::memory_order_relaxed);
size_type next_index = get_next_index(write_index, RESERVED);
size_type next_index = get_next_index(write_index, Reserved);
if (next_index != read.load(etl::memory_order_acquire))
{
@ -279,7 +279,7 @@ namespace etl
bool emplace()
{
size_type write_index = write.load(etl::memory_order_relaxed);
size_type next_index = get_next_index(write_index, RESERVED);
size_type next_index = get_next_index(write_index, Reserved);
if (next_index != read.load(etl::memory_order_acquire))
{
@ -302,7 +302,7 @@ namespace etl
bool emplace(const T1& value1)
{
size_type write_index = write.load(etl::memory_order_relaxed);
size_type next_index = get_next_index(write_index, RESERVED);
size_type next_index = get_next_index(write_index, Reserved);
if (next_index != read.load(etl::memory_order_acquire))
{
@ -325,7 +325,7 @@ namespace etl
bool emplace(const T1& value1, const T2& value2)
{
size_type write_index = write.load(etl::memory_order_relaxed);
size_type next_index = get_next_index(write_index, RESERVED);
size_type next_index = get_next_index(write_index, Reserved);
if (next_index != read.load(etl::memory_order_acquire))
{
@ -348,7 +348,7 @@ namespace etl
bool emplace(const T1& value1, const T2& value2, const T3& value3)
{
size_type write_index = write.load(etl::memory_order_relaxed);
size_type next_index = get_next_index(write_index, RESERVED);
size_type next_index = get_next_index(write_index, Reserved);
if (next_index != read.load(etl::memory_order_acquire))
{
@ -371,7 +371,7 @@ namespace etl
bool emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
{
size_type write_index = write.load(etl::memory_order_relaxed);
size_type next_index = get_next_index(write_index, RESERVED);
size_type next_index = get_next_index(write_index, Reserved);
if (next_index != read.load(etl::memory_order_acquire))
{
@ -418,7 +418,7 @@ namespace etl
return false;
}
size_type next_index = get_next_index(read_index, RESERVED);
size_type next_index = get_next_index(read_index, Reserved);
#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
value = etl::move(p_buffer[read_index]);
@ -446,7 +446,7 @@ namespace etl
return false;
}
size_type next_index = get_next_index(read_index, RESERVED);
size_type next_index = get_next_index(read_index, Reserved);
p_buffer[read_index].~T();
@ -518,15 +518,15 @@ namespace etl
/// A fixed capacity spsc queue.
/// This queue supports concurrent access by one producer and one consumer.
/// \tparam T The type this queue should support.
/// \tparam SIZE The maximum capacity of the queue.
/// \tparam MEMORY_MODEL The memory model for the queue. Determines the type of the internal counter variables.
/// \tparam Size The maximum capacity of the queue.
/// \tparam Memory_Model The memory model for the queue. Determines the type of the internal counter variables.
//***************************************************************************
template <typename T, size_t SIZE, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
class queue_spsc_atomic : public iqueue_spsc_atomic<T, MEMORY_MODEL>
template <typename T, size_t Size, const size_t Memory_Model = etl::memory_model::MEMORY_MODEL_LARGE>
class queue_spsc_atomic : public iqueue_spsc_atomic<T, Memory_Model>
{
private:
typedef typename etl::iqueue_spsc_atomic<T, MEMORY_MODEL> base_t;
typedef typename etl::iqueue_spsc_atomic<T, Memory_Model> base_t;
public:
@ -534,19 +534,19 @@ namespace etl
private:
static ETL_CONSTANT size_type RESERVED_SIZE = size_type(SIZE + 1);
static ETL_CONSTANT size_type Reserved_Size = size_type(Size + 1);
public:
ETL_STATIC_ASSERT((SIZE <= (etl::integral_limits<size_type>::max - 1)), "Size too large for memory model");
ETL_STATIC_ASSERT((Size <= (etl::integral_limits<size_type>::max - 1)), "Size too large for memory model");
static ETL_CONSTANT size_type MAX_SIZE = size_type(SIZE);
static ETL_CONSTANT size_type MAX_SIZE = size_type(Size);
//*************************************************************************
/// Default constructor.
//*************************************************************************
queue_spsc_atomic()
: base_t(reinterpret_cast<T*>(&buffer[0]), RESERVED_SIZE)
: base_t(reinterpret_cast<T*>(&buffer[0]), Reserved_Size)
{
}
@ -561,11 +561,11 @@ namespace etl
private:
/// The uninitialised buffer of T used in the queue_spsc.
typename etl::aligned_storage<sizeof(T), etl::alignment_of<T>::value>::type buffer[RESERVED_SIZE];
typename etl::aligned_storage<sizeof(T), etl::alignment_of<T>::value>::type buffer[Reserved_Size];
};
template <typename T, size_t SIZE, const size_t MEMORY_MODEL>
ETL_CONSTANT typename queue_spsc_atomic<T, SIZE, MEMORY_MODEL>::size_type queue_spsc_atomic<T, SIZE, MEMORY_MODEL>::MAX_SIZE;
template <typename T, size_t Size, const size_t Memory_Model>
ETL_CONSTANT typename queue_spsc_atomic<T, Size, Memory_Model>::size_type queue_spsc_atomic<T, Size, Memory_Model>::MAX_SIZE;
}
#endif

View File

@ -822,8 +822,8 @@ namespace etl
private:
queue_spsc_isr(const queue_spsc_isr&);
queue_spsc_isr& operator = (const queue_spsc_isr&);
queue_spsc_isr(const queue_spsc_isr&) ETL_DELETE;
queue_spsc_isr& operator = (const queue_spsc_isr&) ETL_DELETE;
#if ETL_USING_CPP11
queue_spsc_isr(queue_spsc_isr&&) = delete;

View File

@ -35,6 +35,8 @@ SOFTWARE.
#include "static_assert.h"
#include "gcd.h"
#include "type_traits.h"
#include <stddef.h>
#include <stdint.h>
@ -138,6 +140,26 @@ namespace etl
{
};
#if ETL_USING_CPP17
template<typename R1, typename R2>
inline constexpr bool ratio_equal_v = ratio_equal<R1, R2>::value;
template<typename R1, typename R2>
inline constexpr bool ratio_not_equal_v = ratio_not_equal<R1, R2>::value;
template<typename R1, typename R2>
inline constexpr bool ratio_less_v = ratio_less<R1, R2>::value;
template<typename R1, typename R2>
inline constexpr bool ratio_less_equal_v = ratio_less_equal<R1, R2>::value;
template<typename R1, typename R2>
inline constexpr bool ratio_greater_v = ratio_greater<R1, R2>::value;
template<typename R1, typename R2>
inline constexpr bool ratio_greater_equal_v = ratio_greater_equal<R1, R2>::value;
#endif
//***********************************************************************
/// Predefined ration types.
//***********************************************************************
@ -182,7 +204,93 @@ namespace etl
typedef ratio<169, 239> ratio_1_over_root2;
/// An approximation of e.
typedef ratio<106, 39> ratio_e;
typedef ratio<326, 120> ratio_e;
#if ETL_USING_CPP11
namespace private_ratio
{
// Primary template for GCD calculation
template <typename T, T A, T B, bool = (B == 0)>
struct ratio_gcd;
// Specialisation for the case when B is not zero
template <typename T, T A, T B>
struct ratio_gcd<T, A, B, false>
{
static constexpr T value = ratio_gcd<T, B, A % B>::value;
};
// Specialisation for the case when B is zero
template <typename T, T A, T B>
struct ratio_gcd<T, A, B, true>
{
static constexpr T value = (A < 0) ? -A : A;
};
// Primary template for LCM calculation
template <typename T, T A, T B>
struct ratio_lcm
{
private:
static constexpr T product = ((A * B) < 0) ? -(A * B) : A * B;
public:
static constexpr T value = product / ratio_gcd<T, A, B>::value;
};
template<typename R1>
struct ratio_reduce
{
private:
static ETL_CONSTEXPR11 intmax_t gcd = etl::private_ratio::ratio_gcd<intmax_t, R1::num, R1::den>::value;
public:
using type = ratio<R1::num / gcd, R1::den / gcd>;
};
template<typename R1, typename R2>
struct ratio_add
{
private:
static ETL_CONSTEXPR11 intmax_t lcm = etl::private_ratio::ratio_lcm<intmax_t, R1::den, R2::den>::value;
public:
using type = typename ratio_reduce<ratio<R1::num * lcm / R1::den + R2::num * lcm / R2::den, lcm>>::type;
};
template<typename R1, typename R2>
struct ratio_subtract
{
public:
using type = typename ratio_add<R1, ratio<-R2::num, R2::den>>::type;
};
template<typename R1, typename R2>
struct ratio_multiply
{
private:
static ETL_CONSTEXPR11 intmax_t gcd1 = etl::private_ratio::ratio_gcd<intmax_t, R1::num, R2::den>::value;
static ETL_CONSTEXPR11 intmax_t gcd2 = etl::private_ratio::ratio_gcd<intmax_t, R2::num, R1::den>::value;
public:
using type = ratio<(R1::num / gcd1) * (R2::num / gcd2), (R1::den / gcd2) * (R2::den / gcd1)>;
};
template<typename R1, typename R2>
struct ratio_divide
{
public:
using type = typename ratio_multiply<R1, ratio<R2::den, R2::num>>::type;
};
}
#endif
}
#endif

View File

@ -46,14 +46,13 @@ namespace etl
//*****************************************************************************
/// A set of rounding algorithms for scaled integrals.
/// \tparam T The integral type.
/// \tparam SCALING The scaling factor.
/// \tparam Scaling The scaling factor.
///
/// \example For emulating fixed point of two decimal places we could use a
/// scaling factor of '100'. To round the result of scaled int calculations
/// using 'Banker's Rounding' we would define this.
/// \code
/// typedef etl::scaled_rounding<int, 100> Rounding;
/// int final_result = Rounding::round_half_even_unscaled(accumulated_result);
/// int final_result = round_half_even_unscaled<100>(accumulated_result);
/// \endcode
/// \link http://www.clivemaxfield.com/diycalculator/sp-round.shtml
//*****************************************************************************
@ -63,19 +62,25 @@ namespace etl
/// \param value Scaled integral.
/// \return Unscaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_ceiling_unscaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_ceiling_unscaled(T value) ETL_NOEXCEPT
{
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
typedef typename scaled_rounding_t<T>::type scale_t;
if (Scaling == 1)
{
return value;
}
if (value >= 0)
{
return T((value + scale_t(SCALING)) / scale_t(SCALING));
return T((value + scale_t(Scaling - 1U)) / scale_t(Scaling));
}
else
{
return T(value / scale_t(SCALING));
return T(value / scale_t(Scaling));
}
}
@ -84,12 +89,14 @@ namespace etl
/// \param value Scaled integral.
/// \return Scaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_ceiling_scaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_ceiling_scaled(T value) ETL_NOEXCEPT
{
typedef typename scaled_rounding_t<T>::type scale_t;
return round_ceiling_unscaled<SCALING>(value) * scale_t(SCALING);
return round_ceiling_unscaled<Scaling>(value) * scale_t(Scaling);
}
//***************************************************************************
@ -97,19 +104,24 @@ namespace etl
/// \param value Scaled integral.
/// \return Unscaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_floor_unscaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_floor_unscaled(T value) ETL_NOEXCEPT
{
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
typedef typename scaled_rounding_t<T>::type scale_t;
if (Scaling == 1)
{
return value;
}
if (value >= 0)
{
return T(value / scale_t(SCALING));
return T(value / scale_t(Scaling));
}
else
{
return T((value - scale_t(SCALING)) / scale_t(SCALING));
return T((value - scale_t(Scaling - 1)) / scale_t(Scaling));
}
}
@ -118,12 +130,14 @@ namespace etl
/// \param value Scaled integral.
/// \return Scaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_floor_scaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_floor_scaled(T value) ETL_NOEXCEPT
{
typedef typename scaled_rounding_t<T>::type scale_t;
return T(round_floor_unscaled<SCALING>(value) * scale_t(SCALING));
return T(round_floor_unscaled<Scaling>(value) * scale_t(Scaling));
}
//***************************************************************************
@ -132,20 +146,27 @@ namespace etl
/// \param value Scaled integral.
/// \return Unscaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_half_up_unscaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_half_up_unscaled(T value) ETL_NOEXCEPT
{
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
ETL_STATIC_ASSERT((((SCALING / 2U) * 2U) == SCALING), "Scaling must be divisible by 2");
typedef typename scaled_rounding_t<T>::type scale_t;
if (value >= 0)
if (Scaling == 1)
{
return T((value + scale_t(SCALING / 2U)) / scale_t(SCALING));
return value;
}
else
{
return T((value - scale_t(SCALING / 2U)) / scale_t(SCALING));
if (value >= 0)
{
return T((value + scale_t(Scaling / 2U)) / scale_t(Scaling));
}
else
{
return T((value - scale_t(Scaling / 2U)) / scale_t(Scaling));
}
}
}
@ -155,12 +176,14 @@ namespace etl
/// \param value Scaled integral.
/// \return Scaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_half_up_scaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_half_up_scaled(T value) ETL_NOEXCEPT
{
typedef typename scaled_rounding_t<T>::type scale_t;
return T(round_half_up_unscaled<SCALING>(value) * scale_t(SCALING));
return T(round_half_up_unscaled<Scaling>(value) * scale_t(Scaling));
}
//***************************************************************************
@ -169,20 +192,25 @@ namespace etl
/// \param value Scaled integral.
/// \return Unscaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_half_down_unscaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_half_down_unscaled(T value) ETL_NOEXCEPT
{
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
ETL_STATIC_ASSERT((((SCALING / 2U) * 2U) == SCALING), "Scaling must be divisible by 2");
typedef typename scaled_rounding_t<T>::type scale_t;
if (Scaling == 1)
{
return value;
}
if (value >= 0)
{
return T((value + scale_t((SCALING / 2U) - 1U)) / scale_t(SCALING));
return T((value + scale_t((Scaling - 1) / 2U)) / scale_t(Scaling));
}
else
{
return T((value - scale_t((SCALING / 2U) - 1U)) / scale_t(SCALING));
return T((value - scale_t((Scaling - 1) / 2U)) / scale_t(Scaling));
}
}
@ -192,12 +220,14 @@ namespace etl
/// \param value Scaled integral.
/// \return Scaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_half_down_scaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_half_down_scaled(T value) ETL_NOEXCEPT
{
typedef typename scaled_rounding_t<T>::type scale_t;
return T(round_half_down_unscaled<SCALING>(value) * scale_t(SCALING));
return T(round_half_down_unscaled<Scaling>(value) * scale_t(Scaling));
}
//***************************************************************************
@ -205,13 +235,21 @@ namespace etl
/// \param value Scaled integral.
/// \return Unscaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_zero_unscaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_zero_unscaled(T value) ETL_NOEXCEPT
{
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
typedef typename scaled_rounding_t<T>::type scale_t;
return T(value / scale_t(SCALING));
if (Scaling == 1)
{
return value;
}
else
{
return T(value / scale_t(Scaling));
}
}
//***************************************************************************
@ -219,46 +257,49 @@ namespace etl
/// \param value Scaled integral.
/// \return Scaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_zero_scaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_zero_scaled(T value) ETL_NOEXCEPT
{
typedef typename scaled_rounding_t<T>::type scale_t;
return T(round_zero_unscaled<SCALING>(value) * scale_t(SCALING));
return T(round_zero_unscaled<Scaling>(value) * scale_t(Scaling));
}
//***************************************************************************
/// Round toward infinity.
/// Round twords infinity or away from zero.
/// \param value Scaled integral.
/// \return Unscaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_infinity_unscaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_infinity_unscaled(T value) ETL_NOEXCEPT
{
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
typedef typename scaled_rounding_t<T>::type scale_t;
if (value >= 0)
{
return T((value + scale_t(SCALING)) / scale_t(SCALING));
return etl::round_ceiling_unscaled<Scaling>(value);
}
else
{
return T((value - scale_t(SCALING)) / scale_t(SCALING));
return etl::round_floor_unscaled<Scaling>(value);
}
}
//***************************************************************************
/// Round toward infinity.
/// Round twords infinity or away from zero.
/// \param value Scaled integral.
/// \return Scaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_infinity_scaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_infinity_scaled(T value) ETL_NOEXCEPT
{
typedef typename scaled_rounding_t<T>::type scale_t;
return T(round_infinity_unscaled<SCALING>(value) * scale_t(SCALING));
return T(round_infinity_unscaled<Scaling>(value) * scale_t(Scaling));
}
//***************************************************************************
@ -267,28 +308,36 @@ namespace etl
/// \param value Scaled integral.
/// \return Unscaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_half_even_unscaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_half_even_unscaled(T value) ETL_NOEXCEPT
{
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
typedef typename scaled_rounding_t<T>::type scale_t;
// Half?
if ((etl::absolute(value) % scale_t(SCALING)) == scale_t(SCALING / 2U))
if (Scaling == 1)
{
// Odd?
if ((value / scale_t(SCALING)) & 1U)
{
return T(round_half_up_unscaled<SCALING>(value));
}
else
{
return T(round_half_down_unscaled<SCALING>(value));
}
return value;
}
else
{
return T(round_half_up_unscaled<SCALING>(value));
// Half?
if ((etl::absolute(value) % scale_t(Scaling)) == scale_t(Scaling / 2U))
{
// Odd?
if ((value / scale_t(Scaling)) & 1U)
{
return T(round_half_up_unscaled<Scaling>(value));
}
else
{
return T(round_half_down_unscaled<Scaling>(value));
}
}
else
{
return T(round_half_up_unscaled<Scaling>(value));
}
}
}
@ -298,12 +347,14 @@ namespace etl
/// \param value Scaled integral.
/// \return Scaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_half_even_scaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_half_even_scaled(T value) ETL_NOEXCEPT
{
typedef typename scaled_rounding_t<T>::type scale_t;
return T(round_half_even_unscaled<SCALING>(value) * scale_t(SCALING));
return T(round_half_even_unscaled<Scaling>(value) * scale_t(Scaling));
}
//***************************************************************************
@ -312,28 +363,36 @@ namespace etl
/// \param value Scaled integral.
/// \return Unscaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_half_odd_unscaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_half_odd_unscaled(T value) ETL_NOEXCEPT
{
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
typedef typename scaled_rounding_t<T>::type scale_t;
// Half?
if ((etl::absolute(value) % scale_t(SCALING)) == scale_t(SCALING / 2U))
if (Scaling == 1)
{
// Odd?
if ((value / scale_t(SCALING)) & 1U)
{
return T(round_half_down_unscaled<SCALING>(value));
}
else
{
return T(round_half_up_unscaled<SCALING>(value));
}
return value;
}
else
{
return T(round_half_up_unscaled<SCALING>(value));
// Half?
if ((etl::absolute(value) % scale_t(Scaling)) == scale_t(Scaling / 2U))
{
// Odd?
if ((value / scale_t(Scaling)) & 1U)
{
return T(round_half_down_unscaled<Scaling>(value));
}
else
{
return T(round_half_up_unscaled<Scaling>(value));
}
}
else
{
return T(round_half_up_unscaled<Scaling>(value));
}
}
}
@ -343,12 +402,14 @@ namespace etl
/// \param value Scaled integral.
/// \return Scaled, rounded integral.
//***************************************************************************
template <uint32_t SCALING, typename T>
T round_half_odd_scaled(T value)
template <uint32_t Scaling, typename T>
ETL_NODISCARD
ETL_CONSTEXPR14
T round_half_odd_scaled(T value) ETL_NOEXCEPT
{
typedef typename scaled_rounding_t<T>::type scale_t;
return T(round_half_odd_unscaled<SCALING>(value) * scale_t(SCALING));
return T(round_half_odd_unscaled<Scaling>(value) * scale_t(Scaling));
}
}

View File

@ -0,0 +1,172 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2019 John Wellbelove
Copyright(c) 2024 BMW AG
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies 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.
******************************************************************************/
#ifndef ETL_SINGLETON_BASE_INCLUDED
#define ETL_SINGLETON_BASE_INCLUDED
///\defgroup singleton_base singleton_base
/// Templated version of the singleton pattern, implemented as base class
/// for singletons.
///\ingroup etl
#include "platform.h"
#include "error_handler.h"
#include "nullptr.h"
#include "file_error_numbers.h"
namespace etl
{
//*************************************************************************
/// Base singleton error exception.
//*************************************************************************
class singleton_base_exception : public etl::exception
{
public:
singleton_base_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
: exception(reason_, file_name_, line_number_)
{
}
};
//*************************************************************************
/// Singleton not created error exception.
//*************************************************************************
class singleton_base_not_created : public etl::singleton_base_exception
{
public:
singleton_base_not_created(string_type file_name_, numeric_type line_number_)
: singleton_base_exception(ETL_ERROR_TEXT("singleton_base:not created", ETL_SINGLETON_BASE_FILE_ID"A"), file_name_, line_number_)
{
}
};
//*************************************************************************
/// Singleton instance already exists.
//*************************************************************************
class singleton_base_already_created : public etl::singleton_base_exception
{
public:
singleton_base_already_created(string_type file_name_, numeric_type line_number_)
: singleton_base_exception(ETL_ERROR_TEXT("singleton_base:already created", ETL_SINGLETON_BASE_FILE_ID"A"), file_name_, line_number_)
{
}
};
//***********************************************************************
/// Base class for singletons.
/// \tparam T Any type that wants to expose the instance() interface.
///
/// This class is designed to work as a generic base class for any class that wants to
/// provide a singleton interface. It'll also work for classes that do not have a
/// default constructor.
///
/// Usage example:
///
/// class Origin
/// : singleton<Origin>
/// {
/// public:
/// Origin(int x, int y)
/// : singleton<Origin>(*this)
/// {}
///
/// int getX() const;
/// } theOrigin(0, 0);
///
/// int x = Origin::instance().getX();
///
///
/// Note:
///
/// It is important that a call to instance() will not create the instance of the class. It needs
/// to be created by the user before calling instance(). This way, the user has better control
/// over the instance lifetime instead of e.g. lazy initialization.
//***********************************************************************
template <typename T>
class singleton_base
{
public:
//***********************************************************************
// Returns a reference to the instance.
//***********************************************************************
static T& instance()
{
ETL_ASSERT(m_self != ETL_NULLPTR, ETL_ERROR(etl::singleton_base_not_created));
return *m_self;
}
//***********************************************************************
/// Returns whether an instance has been attached to singleton<T> or not.
//***********************************************************************
static bool is_valid()
{
return (m_self != ETL_NULLPTR);
}
protected:
//***********************************************************************
/// Constructs the instance of singleton.
/// theInstance Reference to T, which will be returned when instance() is called.
//***********************************************************************
explicit singleton_base(T& theInstance)
{
ETL_ASSERT(m_self == ETL_NULLPTR, ETL_ERROR(etl::singleton_base_already_created));
m_self = &theInstance;
}
//***********************************************************************
/// Removes the internal reference to the instance passed in the constructor.
//***********************************************************************
~singleton_base()
{
m_self = ETL_NULLPTR;
}
private:
static T* m_self;
};
//***********************************************************************
/// No violation of one definition rule as this is a class template
//***********************************************************************
template<class T>
T* singleton_base<T>::m_self = ETL_NULLPTR;
}
#endif

View File

@ -32,6 +32,10 @@ SOFTWARE.
#define ETL_SPAN_INCLUDED
#include "platform.h"
#include "error_handler.h"
#include "exception.h"
#include "alignment.h"
#include "iterator.h"
#include "algorithm.h"
#include "circular_iterator.h"
@ -46,20 +50,63 @@ SOFTWARE.
#include "private/dynamic_extent.h"
#if ETL_USING_CPP20 && ETL_USING_STL
#include <span>
#endif
///\defgroup span span
///\ingroup containers
namespace etl
{
//***************************************************************************
// Tag to indicate a class is a span.
//***************************************************************************
class span_tag {};
//***************************************************************************
///\ingroup span
/// Exception base for span
//***************************************************************************
class span_exception : public exception
{
public:
span_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
: exception(reason_, file_name_, line_number_)
{
}
};
//***************************************************************************
///\ingroup span
/// Bad alignment exception.
//***************************************************************************
class span_alignment_exception : public span_exception
{
public:
span_alignment_exception(string_type file_name_, numeric_type line_number_)
: span_exception(ETL_ERROR_TEXT("span:alignment", ETL_SPAN_FILE_ID"A"), file_name_, line_number_)
{
}
};
//***************************************************************************
///\ingroup span
/// span size exception.
//***************************************************************************
class span_size_mismatch : public span_exception
{
public:
span_size_mismatch(string_type file_name_, numeric_type line_number_)
: span_exception(ETL_ERROR_TEXT("span:size", ETL_SPAN_FILE_ID"B"), file_name_, line_number_)
{
}
};
//***************************************************************************
/// Span - Fixed Extent
//***************************************************************************
template <typename T, size_t Extent = etl::dynamic_extent>
class span
class span : public span_tag
{
public:
@ -71,8 +118,10 @@ namespace etl
typedef T* pointer;
typedef const T* const_pointer;
typedef T* iterator;
typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
typedef T* iterator;
typedef const T* const_iterator;
typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
typedef ETL_OR_STD::reverse_iterator<const_iterator> const_reverse_iterator;
typedef etl::circular_iterator<pointer> circular_iterator;
typedef etl::circular_iterator<ETL_OR_STD::reverse_iterator<pointer> > reverse_circular_iterator;
@ -84,7 +133,7 @@ namespace etl
//*************************************************************************
template <typename TIterator, typename TSize>
ETL_CONSTEXPR explicit span(const TIterator begin_, const TSize /*size_*/) ETL_NOEXCEPT
: pbegin(etl::addressof(*begin_))
: pbegin(etl::to_address(begin_))
{
}
@ -93,28 +142,40 @@ namespace etl
//*************************************************************************
template <typename TIterator>
ETL_CONSTEXPR explicit span(const TIterator begin_, const TIterator /*end_*/)
: pbegin(etl::addressof(*begin_))
: pbegin(etl::to_address(begin_))
{
}
//*************************************************************************
/// Construct from C array
//*************************************************************************
template<size_t Array_Size>
#if ETL_USING_CPP11
template<size_t Array_Size, typename = typename etl::enable_if<(Array_Size == Extent), void>::type>
ETL_CONSTEXPR span(element_type(&begin_)[Array_Size]) ETL_NOEXCEPT
: pbegin(begin_)
{
}
#else
//*************************************************************************
/// Construct from C array
//*************************************************************************
template<size_t Array_Size>
ETL_CONSTEXPR span(element_type(&begin_)[Array_Size], typename etl::enable_if<(Array_Size == Extent), void>::type* = 0) ETL_NOEXCEPT
: pbegin(begin_)
{
}
#endif
#if ETL_USING_CPP11
//*************************************************************************
/// Construct from a container or other type that supports
/// data() and size() member functions.
//*************************************************************************
template <typename TContainer, typename = typename etl::enable_if<!etl::is_pointer<etl::remove_reference_t<TContainer>>::value &&
template <typename TContainer, typename = typename etl::enable_if<!etl::is_base_of<span_tag, etl::remove_reference_t<TContainer>>::value &&
!etl::is_pointer<etl::remove_reference_t<TContainer>>::value &&
!etl::is_array<etl::remove_reference_t<TContainer>>::value&&
etl::is_same<etl::remove_cv_t<T>, etl::remove_cv_t<typename etl::remove_reference_t<TContainer>::value_type>>::value, void>::type>
ETL_CONSTEXPR span(TContainer&& a) ETL_NOEXCEPT
ETL_CONSTEXPR span(TContainer&& a) ETL_NOEXCEPT
: pbegin(a.data())
{
}
@ -124,7 +185,8 @@ namespace etl
/// data() and size() member functions.
//*************************************************************************
template <typename TContainer>
span(TContainer& a, typename etl::enable_if<!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
span(TContainer& a, typename etl::enable_if<!etl::is_base_of<span_tag, typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_array<TContainer>::value &&
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT
: pbegin(a.data())
@ -136,9 +198,10 @@ namespace etl
/// data() and size() member functions.
//*************************************************************************
template <typename TContainer>
ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if<!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_array<TContainer>::value&&
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT
span(const TContainer& a, typename etl::enable_if<!etl::is_base_of<span_tag, typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_array<TContainer>::value&&
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT
: pbegin(a.data())
{
}
@ -154,13 +217,25 @@ namespace etl
//*************************************************************************
/// Copy constructor
/// From fixed extent span.
//*************************************************************************
template <typename U, size_t N>
ETL_CONSTEXPR span(const etl::span<U, N>& other, typename etl::enable_if<(Extent == etl::dynamic_extent) || (N == etl::dynamic_extent) || (N == Extent), void>::type) ETL_NOEXCEPT
ETL_CONSTEXPR span(const etl::span<U, N>& other, typename etl::enable_if<N == Extent, void>::type* = 0) ETL_NOEXCEPT
: pbegin(other.data())
{
}
//*************************************************************************
/// Copy constructor
/// From dynamic extent span.
//*************************************************************************
template <typename U, size_t N>
ETL_CONSTEXPR14 span(const etl::span<U, N>& other, typename etl::enable_if<N == etl::dynamic_extent, void>::type* = 0)
: pbegin(other.data())
{
ETL_ASSERT(other.size() == Extent, ETL_ERROR(span_size_mismatch));
}
//*************************************************************************
/// Returns a reference to the first element.
//*************************************************************************
@ -185,6 +260,14 @@ namespace etl
return pbegin;
}
//*************************************************************************
/// Returns a const iterator to the beginning of the span.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR const_iterator cbegin() const ETL_NOEXCEPT
{
return pbegin;
}
//*************************************************************************
/// Returns an iterator to the beginning of the span.
//*************************************************************************
@ -201,6 +284,14 @@ namespace etl
return circular_iterator(begin(), end());
}
//*************************************************************************
/// Returns a const iterator to the end of the span.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR const_iterator cend() const ETL_NOEXCEPT
{
return (pbegin + Extent);
}
//*************************************************************************
/// Returns an iterator to the end of the span.
//*************************************************************************
@ -209,6 +300,14 @@ namespace etl
return (pbegin + Extent);
}
//*************************************************************************
// Returns a const reverse iterator to the reverse beginning of the span.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR const_reverse_iterator crbegin() const ETL_NOEXCEPT
{
return const_reverse_iterator((pbegin + Extent));
}
//*************************************************************************
// Returns an reverse iterator to the reverse beginning of the span.
//*************************************************************************
@ -225,6 +324,14 @@ namespace etl
return reverse_circular_iterator(rbegin(), rend());
}
//*************************************************************************
/// Returns a const reverse iterator to the end of the span.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR const_reverse_iterator crend() const ETL_NOEXCEPT
{
return const_reverse_iterator(pbegin);
}
//*************************************************************************
/// Returns a reverse iterator to the end of the span.
//*************************************************************************
@ -238,7 +345,7 @@ namespace etl
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT
{
return false;
return Extent == 0;
}
//*************************************************************************
@ -272,6 +379,26 @@ namespace etl
{
pbegin = other.pbegin;
return *this;
}
//*************************************************************************
/// Returns a reference to the value at index 'i'.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR14 reference at(size_t i)
{
ETL_ASSERT(i < size(), ETL_ERROR(array_out_of_range));
return pbegin[i];
}
//*************************************************************************
/// Returns a const reference to the value at index 'i'.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR14 const_reference at(size_t i) const
{
ETL_ASSERT(i < size(), ETL_ERROR(array_out_of_range));
return pbegin[i];
}
//*************************************************************************
@ -328,14 +455,14 @@ namespace etl
//*************************************************************************
template <size_t OFFSET, size_t COUNT = etl::dynamic_extent>
ETL_NODISCARD ETL_CONSTEXPR
etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : Extent - OFFSET> subspan() const ETL_NOEXCEPT
etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : Extent - OFFSET> subspan() const ETL_NOEXCEPT
{
// If Extent is static, check that OFFSET is within the original span
ETL_STATIC_ASSERT((Extent != etl::dynamic_extent) ? OFFSET <= Extent : true, "OFFSET is not within the original span");
// If count is also static, check that OFFSET + COUNT is within the original span
ETL_STATIC_ASSERT((Extent != etl::dynamic_extent) && (COUNT != etl::dynamic_extent) ? COUNT <= (Extent - OFFSET) : true, "OFFSET + COUNT is not within the original span");
return (COUNT == etl::dynamic_extent) ? etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : Extent - OFFSET>(pbegin + OFFSET, (pbegin + Extent))
: etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : Extent - OFFSET>(pbegin + OFFSET, pbegin + OFFSET + COUNT);
}
@ -351,7 +478,7 @@ namespace etl
// If count is also static, check that OFFSET + COUNT is within the original span
ETL_STATIC_ASSERT((Extent != etl::dynamic_extent) && (COUNT != etl::dynamic_extent) ? COUNT <= (Extent - OFFSET) : true, "OFFSET + COUNT is not within the original span");
if (COUNT == etl::dynamic_extent)
{
return etl::span<element_type, (COUNT != etl::dynamic_extent ? COUNT : Extent - OFFSET)>(pbegin + OFFSET, (pbegin + Extent));
@ -372,16 +499,48 @@ namespace etl
: etl::span<element_type, etl::dynamic_extent>(pbegin + offset, pbegin + offset + count);
}
//*************************************************************************
/// Moves the pointer to the first element of the span further by a specified number of elements.
///\tparam elements Number of elements to move forward
//*************************************************************************
void advance(size_t elements) ETL_NOEXCEPT
{
elements = etl::min(elements, size());
pbegin += elements;
}
//*************************************************************************
/// Reinterpret the span as a span with different element type.
//*************************************************************************
template<typename TNew>
ETL_NODISCARD ETL_CONSTEXPR14 etl::span<TNew, etl::dynamic_extent> reinterpret_as() const
{
ETL_ASSERT(etl::is_aligned<etl::alignment_of<TNew>::value>(pbegin), ETL_ERROR(span_alignment_exception));
return etl::span<TNew, etl::dynamic_extent>(reinterpret_cast<TNew*>(pbegin),
Extent * sizeof(element_type) / sizeof(TNew));
}
private:
pointer pbegin;
};
//*************************************************************************
/// Pseudo constructor for constructing from C array without explicitly
/// specifying type and size
//*************************************************************************
template <typename T, size_t Extent>
ETL_CONSTEXPR span<T, Extent> make_span(T (&data)[Extent])
{
return span<T, Extent>(data);
}
//***************************************************************************
/// Span - Dynamic Extent
//***************************************************************************
template <typename T>
class span<T, etl::dynamic_extent>
class span<T, etl::dynamic_extent> : public span_tag
{
public:
@ -392,9 +551,11 @@ namespace etl
typedef const T& const_reference;
typedef T* pointer;
typedef const T* const_pointer;
typedef T* iterator;
typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
typedef T* iterator;
typedef const T* const_iterator;
typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
typedef ETL_OR_STD::reverse_iterator<const_iterator> const_reverse_iterator;
typedef etl::circular_iterator<pointer> circular_iterator;
typedef etl::circular_iterator<ETL_OR_STD::reverse_iterator<pointer> > reverse_circular_iterator;
@ -415,8 +576,8 @@ namespace etl
//*************************************************************************
template <typename TIterator, typename TSize>
ETL_CONSTEXPR span(const TIterator begin_, const TSize size_) ETL_NOEXCEPT
: pbegin(etl::addressof(*begin_))
, pend(etl::addressof(*begin_) + size_)
: pbegin(etl::to_address(begin_))
, pend(etl::to_address(begin_) + size_)
{
}
@ -425,8 +586,8 @@ namespace etl
//*************************************************************************
template <typename TIterator>
ETL_CONSTEXPR span(const TIterator begin_, const TIterator end_)
: pbegin(etl::addressof(*begin_))
, pend(etl::addressof(*begin_) + etl::distance(begin_, end_))
: pbegin(etl::to_address(begin_))
, pend(etl::to_address(begin_) + etl::distance(begin_, end_))
{
}
@ -445,10 +606,11 @@ namespace etl
/// Construct from a container or other type that supports
/// data() and size() member functions.
//*************************************************************************
template <typename TContainer, typename = typename etl::enable_if<!etl::is_pointer<etl::remove_reference_t<TContainer>>::value &&
template <typename TContainer, typename = typename etl::enable_if<!etl::is_base_of<span_tag, etl::remove_reference_t<TContainer>>::value &&
!etl::is_pointer<etl::remove_reference_t<TContainer>>::value &&
!etl::is_array<etl::remove_reference_t<TContainer>>::value &&
etl::is_same<etl::remove_cv_t<T>, etl::remove_cv_t<typename etl::remove_reference_t<TContainer>::value_type>>::value, void>::type>
ETL_CONSTEXPR span(TContainer&& a) ETL_NOEXCEPT
ETL_CONSTEXPR span(TContainer&& a) ETL_NOEXCEPT
: pbegin(a.data())
, pend(a.data() + a.size())
{
@ -459,7 +621,8 @@ namespace etl
/// data() and size() member functions.
//*************************************************************************
template <typename TContainer>
ETL_CONSTEXPR span(TContainer& a, typename etl::enable_if<!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
ETL_CONSTEXPR span(TContainer& a, typename etl::enable_if<!etl::is_base_of<span_tag, typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_array<TContainer>::value &&
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT
: pbegin(a.data())
@ -472,7 +635,8 @@ namespace etl
/// data() and size() member functions.
//*************************************************************************
template <typename TContainer>
ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if<!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if<!etl::is_base_of<span_tag, typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_array<TContainer>::value &&
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT
: pbegin(a.data())
@ -524,6 +688,14 @@ namespace etl
return pbegin;
}
//*************************************************************************
/// Returns a const iterator to the beginning of the span.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR const_iterator cbegin() const ETL_NOEXCEPT
{
return pbegin;
}
//*************************************************************************
/// Returns an iterator to the beginning of the span.
//*************************************************************************
@ -540,6 +712,14 @@ namespace etl
return circular_iterator(begin(), end());
}
//*************************************************************************
/// Returns a const iterator to the end of the span.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR const_iterator cend() const ETL_NOEXCEPT
{
return pend;
}
//*************************************************************************
/// Returns an iterator to the end of the span.
//*************************************************************************
@ -556,6 +736,14 @@ namespace etl
return reverse_iterator(pend);
}
//*************************************************************************
// Returns a const reverse iterator to the reverse beginning of the span.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR const_reverse_iterator crbegin() const ETL_NOEXCEPT
{
return const_reverse_iterator(pend);
}
//*************************************************************************
/// Returns a reverse circular iterator to the end of the span.
//*************************************************************************
@ -564,6 +752,14 @@ namespace etl
return reverse_circular_iterator(rbegin(), rend());
}
//*************************************************************************
/// Returns a const reverse iterator to the end of the span.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR const_reverse_iterator crend() const ETL_NOEXCEPT
{
return const_reverse_iterator(pbegin);
}
//*************************************************************************
/// Returns a reverse iterator to the end of the span.
//*************************************************************************
@ -614,6 +810,26 @@ namespace etl
return *this;
}
//*************************************************************************
/// Returns a reference to the value at index 'i'.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR14 reference at(size_t i)
{
ETL_ASSERT(i < size(), ETL_ERROR(array_out_of_range));
return pbegin[i];
}
//*************************************************************************
/// Returns a const reference to the value at index 'i'.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR14 const_reference at(size_t i) const
{
ETL_ASSERT(i < size(), ETL_ERROR(array_out_of_range));
return pbegin[i];
}
//*************************************************************************
/// Returns a reference to the indexed value.
//*************************************************************************
@ -662,7 +878,7 @@ namespace etl
//*************************************************************************
template <size_t OFFSET, size_t COUNT = etl::dynamic_extent>
ETL_NODISCARD ETL_CONSTEXPR
etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : etl::dynamic_extent> subspan() const ETL_NOEXCEPT
etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : etl::dynamic_extent> subspan() const ETL_NOEXCEPT
{
return (COUNT == etl::dynamic_extent) ? etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : etl::dynamic_extent>(pbegin + OFFSET, pend)
: etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : etl::dynamic_extent>(pbegin + OFFSET, pbegin + OFFSET + COUNT);
@ -694,12 +910,54 @@ namespace etl
: etl::span<element_type, etl::dynamic_extent>(pbegin + offset, pbegin + offset + count);
}
//*************************************************************************
/// Moves the pointer to the first element of the span further by a specified number of elements.
///\tparam elements Number of elements to move forward
//*************************************************************************
void advance(size_t elements) ETL_NOEXCEPT
{
elements = etl::min(elements, size());
pbegin += elements;
}
//*************************************************************************
/// Reinterpret the span as a span with different element type.
//*************************************************************************
template<typename TNew>
ETL_NODISCARD ETL_CONSTEXPR14 etl::span<TNew, etl::dynamic_extent> reinterpret_as() const
{
ETL_ASSERT(etl::is_aligned<etl::alignment_of<TNew>::value>(pbegin), ETL_ERROR(span_alignment_exception));
return etl::span<TNew, etl::dynamic_extent>(reinterpret_cast<TNew*>(pbegin),
(pend - pbegin) * sizeof(element_type) / sizeof(TNew));
}
private:
pointer pbegin;
pointer pend;
};
//*************************************************************************
/// Pseudo constructor for constructing from container without explicitly
/// specifying type and size
//*************************************************************************
template <typename T>
ETL_CONSTEXPR span<typename T::value_type, etl::dynamic_extent> make_span(T& data)
{
return span<typename T::value_type, etl::dynamic_extent>(data);
}
//*************************************************************************
/// Pseudo constructor for constructing from const container without
/// explicitly specifying type and size
//*************************************************************************
template <typename T>
ETL_CONSTEXPR span<typename T::value_type const, etl::dynamic_extent> make_span(const T& data)
{
return span<typename T::value_type const, etl::dynamic_extent>(data);
}
template <typename T, size_t Extent>
ETL_CONSTANT size_t span<T, Extent>::extent;
@ -746,6 +1004,33 @@ namespace etl
etl::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
//*************************************************************************
/// Copy complete element data from one span to another. If the destination
/// span is bigger than the source span, only the initial part of
/// destination span is overwritten.
///\param src Source
///\param dst Destination
///\return true, if copy was successful (including empty source span, or
/// spans pointing to the same address)
///\return false, if the destination span is shorter than the source span.
//*************************************************************************
template <typename T1, size_t N1, typename T2, size_t N2>
typename etl::enable_if<etl::is_same<typename etl::remove_cv<T1>::type, typename etl::remove_cv<T2>::type>::value &&
!etl::is_const<T2>::value, bool>::type
copy(const etl::span<T1, N1>& src, const etl::span<T2, N2>& dst)
{
if (src.empty() || (src.begin() == dst.begin()))
{
return true;
}
if (src.size() > dst.size())
{
return false;
}
(void) etl::copy(src.begin(), src.end(), dst.begin());
return true;
}
//*************************************************************************
/// Template deduction guides.
//*************************************************************************
@ -818,4 +1103,4 @@ namespace etl
}
}
#endif
#endif

View File

@ -283,13 +283,15 @@ namespace etl
///\param value The value to push to the stack.
//*************************************************************************
template <typename ... Args>
void emplace(Args && ... args)
reference emplace(Args && ... args)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(stack_full));
#endif
base_t::add_in();
::new (&p_buffer[top_index]) T(etl::forward<Args>(args)...);
return p_buffer[top_index];
}
#else
//*************************************************************************
@ -297,13 +299,15 @@ namespace etl
/// If asserts or exceptions are enabled, throws an etl::stack_full if the stack is already full.
///\param value The value to push to the stack.
//*************************************************************************
void emplace()
reference emplace()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(stack_full));
#endif
base_t::add_in();
::new (&p_buffer[top_index]) T();
return p_buffer[top_index];
}
//*************************************************************************
@ -312,13 +316,15 @@ namespace etl
///\param value The value to push to the stack.
//*************************************************************************
template <typename T1>
void emplace(const T1& value1)
reference emplace(const T1& value1)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(stack_full));
#endif
base_t::add_in();
::new (&p_buffer[top_index]) T(value1);
return p_buffer[top_index];
}
//*************************************************************************
@ -327,13 +333,15 @@ namespace etl
///\param value The value to push to the stack.
//*************************************************************************
template <typename T1, typename T2>
void emplace(const T1& value1, const T2& value2)
reference emplace(const T1& value1, const T2& value2)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(stack_full));
#endif
base_t::add_in();
::new (&p_buffer[top_index]) T(value1, value2);
return p_buffer[top_index];
}
//*************************************************************************
@ -342,13 +350,15 @@ namespace etl
///\param value The value to push to the stack.
//*************************************************************************
template <typename T1, typename T2, typename T3>
void emplace(const T1& value1, const T2& value2, const T3& value3)
reference emplace(const T1& value1, const T2& value2, const T3& value3)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(stack_full));
#endif
base_t::add_in();
::new (&p_buffer[top_index]) T(value1, value2, value3);
return p_buffer[top_index];
}
//*************************************************************************
@ -357,13 +367,15 @@ namespace etl
///\param value The value to push to the stack.
//*************************************************************************
template <typename T1, typename T2, typename T3, typename T4>
void emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
reference emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(stack_full));
#endif
base_t::add_in();
::new (&p_buffer[top_index]) T(value1, value2, value3, value4);
return p_buffer[top_index];
}
#endif

View File

@ -48,7 +48,7 @@ namespace etl
{
inline namespace string_literals
{
constexpr etl::string_view operator ""_sv(const char* str, size_t length) noexcept
inline constexpr etl::string_view operator ""_sv(const char* str, size_t length) noexcept
{
return etl::string_view{ str, length };
}
@ -72,6 +72,7 @@ namespace etl
typedef istring interface_type;
typedef istring::value_type value_type;
typedef istring::size_type size_type;
static ETL_CONSTANT size_t MAX_SIZE = MAX_SIZE_;
@ -243,6 +244,16 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
string& operator = (const etl::string_view& view)
{
this->assign(view);
return *this;
}
//*************************************************************************
/// Fix the internal pointers after a low level memory copy.
//*************************************************************************
@ -261,7 +272,7 @@ namespace etl
};
template <size_t MAX_SIZE_>
ETL_CONSTANT size_t string<MAX_SIZE_>::MAX_SIZE;
ETL_CONSTANT typename string<MAX_SIZE_>::size_type string<MAX_SIZE_>::MAX_SIZE;
//***************************************************************************
/// A string implementation that uses a fixed size external buffer.
@ -361,6 +372,16 @@ namespace etl
this->resize(count, c);
}
//*************************************************************************
/// From string_view.
///\param view The string_view.
//*************************************************************************
explicit string_ext(const etl::string_view& view, value_type* buffer, size_type buffer_size)
: istring(buffer, buffer_size - 1U)
{
this->assign(view.begin(), view.end());
}
//*************************************************************************
/// Constructor, from an iterator range.
///\tparam TIterator The iterator type.
@ -385,16 +406,6 @@ namespace etl
}
#endif
//*************************************************************************
/// From string_view.
///\param view The string_view.
//*************************************************************************
explicit string_ext(const etl::string_view& view, value_type* buffer, size_type buffer_size)
: istring(buffer, buffer_size - 1U)
{
this->assign(view.begin(), view.end());
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
@ -408,7 +419,6 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
@ -432,6 +442,16 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
string_ext& operator = (const etl::string_view& view)
{
this->assign(view);
return *this;
}
//*************************************************************************
/// Fix the internal pointers after a low level memory copy.
//*************************************************************************

View File

@ -43,6 +43,14 @@ SOFTWARE.
#include "algorithm.h"
#include "private/minmax_push.h"
#if ETL_USING_STL && ETL_USING_CPP17
#include <string_view>
#endif
#if ETL_USING_STL
#include <ostream>
#endif
#include <stdint.h>
namespace etl
@ -96,9 +104,9 @@ namespace etl
{
public:
typedef T value_type;
typedef TTraits traits_type;
typedef size_t size_type;
typedef T value_type;
typedef TTraits traits_type;
typedef size_t size_type;
typedef const T& const_reference;
typedef const T* const_pointer;
typedef const T* const_iterator;
@ -366,7 +374,7 @@ namespace etl
//*************************************************************************
ETL_CONSTEXPR14 basic_string_view substr(size_type position = 0, size_type count = npos) const
{
basic_string_view view;
basic_string_view view = basic_string_view();
if (position < size())
{
@ -408,20 +416,48 @@ namespace etl
}
ETL_CONSTEXPR14 int compare(size_type position1, size_type count1,
basic_string_view view,
size_type position2, size_type count2) const
basic_string_view view,
size_type position2, size_type count2) const
{
return substr(position1, count1).compare(view.substr(position2, count2));
}
ETL_CONSTEXPR14 int compare(const T* text) const
{
return compare(etl::basic_string_view<T, TTraits>(text));
const T* view_itr = mbegin;
const T* text_itr = text;
while (view_itr != mend && *text_itr != T(0))
{
if (*view_itr < *text_itr)
{
return -1;
}
else if (*view_itr > *text_itr)
{
return 1;
}
++view_itr;
++text_itr;
}
if ((view_itr == mend) && (*text_itr == T(0)))
{
return 0;
}
else if (view_itr == mend)
{
return -1;
}
else
{
return 1;
}
}
ETL_CONSTEXPR14 int compare(size_type position, size_type count, const T* text) const
{
return substr(position, count).compare(etl::basic_string_view<T, TTraits>(text));
return substr(position, count).compare(text);
}
ETL_CONSTEXPR14 int compare(size_type position, size_type count1, const T* text, size_type count2) const
@ -435,7 +471,7 @@ namespace etl
ETL_CONSTEXPR14 bool starts_with(etl::basic_string_view<T, TTraits> view) const
{
return (size() >= view.size()) &&
(compare(0, view.size(), view) == 0);
(compare(0, view.size(), view) == 0);
}
ETL_CONSTEXPR14 bool starts_with(T c) const
@ -448,7 +484,7 @@ namespace etl
size_t lengthtext = TTraits::length(text);
return (size() >= lengthtext) &&
(compare(0, lengthtext, text) == 0);
(compare(0, lengthtext, text) == 0);
}
//*************************************************************************
@ -457,7 +493,7 @@ namespace etl
ETL_CONSTEXPR14 bool ends_with(etl::basic_string_view<T, TTraits> view) const
{
return (size() >= view.size()) &&
(compare(size() - view.size(), npos, view) == 0);
(compare(size() - view.size(), npos, view) == 0);
}
ETL_CONSTEXPR14 bool ends_with(T c) const
@ -471,7 +507,7 @@ namespace etl
size_t lengthview = size();
return (lengthview >= lengthtext) &&
(compare(lengthview - lengthtext, lengthtext, text) == 0);
(compare(lengthview - lengthtext, lengthtext, text) == 0);
}
//*************************************************************************
@ -747,6 +783,30 @@ namespace etl
return find_last_not_of(etl::basic_string_view<T, TTraits>(text), position);
}
//*********************************************************************
/// Checks that the view is within this string
//*********************************************************************
bool contains(const etl::basic_string_view<T, TTraits>& view) const
{
return find(view) != npos;
}
//*********************************************************************
/// Checks that text is within this string
//*********************************************************************
bool contains(const_pointer s) const
{
return find(s) != npos;
}
//*********************************************************************
/// Checks that character is within this string
//*********************************************************************
bool contains(value_type c) const
{
return find(c) != npos;
}
//*************************************************************************
/// Equality for string_view.
//*************************************************************************
@ -916,6 +976,19 @@ void swap(etl::basic_string_view<T, etl::char_traits<T> >& lhs, etl::basic_strin
lhs.swap(rhs);
}
//*************************************************************************
/// Operator overload to write to std basic_ostream
//*************************************************************************
#if ETL_USING_STL
template <typename T>
std::basic_ostream<T, std::char_traits<T> > &operator<<(std::basic_ostream<T, std::char_traits<T> > &os,
etl::basic_string_view<T, etl::char_traits<T> > text)
{
os.write(text.data(), text.size());
return os;
}
#endif
#include "private/minmax_pop.h"
#endif

1259
include/etl/tuple.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -58,10 +58,9 @@ namespace etl
typedef TIdType id_type;
//*********************************************************************
ETL_CONSTEXPR type_def()
: value(TValue())
{
}
#if ETL_USING_CPP11
ETL_CONSTEXPR type_def() = default;
#endif
//*********************************************************************
ETL_CONSTEXPR type_def(TValue value_)
@ -70,10 +69,9 @@ namespace etl
}
//*********************************************************************
ETL_CONSTEXPR type_def(const type_def& other)
: value(other.value)
{
}
#if ETL_USING_CPP11
ETL_CONSTEXPR type_def(const type_def& other) = default;
#endif
//*********************************************************************
ETL_CONSTEXPR operator TValue() const
@ -245,11 +243,9 @@ namespace etl
}
//*********************************************************************
ETL_CONSTEXPR14 type_def& operator =(const type_def& rhs)
{
value = rhs.value;
return *this;
}
#if ETL_USING_CPP11
ETL_CONSTEXPR14 type_def& operator =(const type_def& rhs) = default;
#endif
//*********************************************************************
TValue& get()

293
include/etl/type_list.h Normal file
View File

@ -0,0 +1,293 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2025 John Wellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies 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.
******************************************************************************/
#ifndef ETL_TYPE_LIST_INCLUDED
#define ETL_TYPE_LIST_INCLUDED
#include "platform.h"
#include "algorithm.h"
#include "index_of_type.h"
#include "integral_limits.h"
#include "static_assert.h"
#include "type_traits.h"
#include "utility.h"
#include "largest.h"
#if ETL_USING_CPP11
namespace etl
{
//***************************************************************************
/// Defines a no-position constant.
//***************************************************************************
static ETL_CONSTANT size_t type_list_npos = etl::integral_limits<size_t>::max;
//***************************************************************************
/// Type list forward declaration.
//***************************************************************************
template <typename... TTypes>
struct type_list;
//***************************************************************************
/// The empty type list.
//***************************************************************************
template <>
struct type_list<>
{
static constexpr size_t size = 0U;
using index_sequence_type = etl::make_index_sequence<0>; ///< The index_sequence type for this type_list.
private:
type_list() ETL_DELETE;
type_list(const type_list&) ETL_DELETE;
type_list& operator =(const type_list&) ETL_DELETE;
};
namespace private_type_list
{
// helper to solve the issue that recursed-rest can't be put directly in type_list::tail definition
template <typename... TTypes>
struct recursion_helper
{
using type = type_list<TTypes...>;
};
}
//***************************************************************************
/// Recursive type list implementation for multiple types.
//***************************************************************************
template <typename THead, typename... TTail>
struct type_list<THead, TTail...> : type_list<TTail...>
{
using head = THead;
using tail = typename private_type_list::recursion_helper<TTail...>::type;
static constexpr size_t size = sizeof...(TTail) + 1U;
using index_sequence_type = etl::make_index_sequence<sizeof...(TTail) + 1U>; ///< The index_sequence type for this type_list.
private:
type_list() ETL_DELETE;
type_list(const type_list&) ETL_DELETE;
type_list& operator =(const type_list&) ETL_DELETE;
};
//***************************************************************************
/// Type list implementation for one type.
//***************************************************************************
template <typename THead>
struct type_list<THead> : type_list<>
{
using head = THead;
using tail = typename private_type_list::recursion_helper<>::type;
static constexpr size_t size = 1U;
using index_sequence_type = etl::make_index_sequence<1>; ///< The index_sequence type for this type_list.
private:
type_list() ETL_DELETE;
type_list(const type_list&) ETL_DELETE;
type_list& operator =(const type_list&) ETL_DELETE;
};
//***************************************************************************
/// Type list size.
//***************************************************************************
template <typename TTypes>
struct type_list_size;
template <typename... TTypes>
struct type_list_size<etl::type_list<TTypes...>> : public etl::integral_constant<size_t, sizeof...(TTypes)>
{
};
#if ETL_USING_CPP17
template <typename... TTypes>
inline constexpr size_t type_list_size_v = type_list_size<etl::type_list<TTypes...>>::value;
#endif
//***************************************************************************
/// Defines type as the type found at Index in the type_list.
/// Static asserts if Index is out of range.
//***************************************************************************
template <typename TTypeList, size_t Index>
struct type_list_type_at_index
{
ETL_STATIC_ASSERT(Index < type_list_size<TTypeList>::value, "etl::type_list_type_at_index out of range");
ETL_STATIC_ASSERT((etl::is_base_of<etl::type_list<>, TTypeList>::value), "TTypeList must be an etl::type_list");
using type = typename type_list_type_at_index<typename TTypeList::tail, Index - 1>::type;
};
template <typename TTypeList>
struct type_list_type_at_index<TTypeList, 0>
{
using type = typename TTypeList::head;
};
template <typename TTypeList, size_t Index>
using type_list_type_at_index_t = typename type_list_type_at_index<TTypeList, Index>::type;
//***************************************************************************
/// Defines an integral constant that is the index of the specified type in the type_list.
/// If the type is not in the type_list, then defined as etl::type_list_npos.
//***************************************************************************
template <typename TTypeList, typename T>
struct type_list_index_of_type
: public etl::integral_constant<size_t, etl::is_same<typename TTypeList::head, T>::value ? 0 :
(type_list_index_of_type<typename TTypeList::tail, T>::value == etl::type_list_npos ? etl::type_list_npos :
type_list_index_of_type<typename TTypeList::tail, T>::value + 1)>
{
ETL_STATIC_ASSERT((etl::is_base_of<etl::type_list<>, TTypeList>::value), "TTypeList must be an etl::type_list");
};
template <typename T>
struct type_list_index_of_type<type_list<>, T>
: public etl::integral_constant<size_t, etl::type_list_npos>
{
};
#if ETL_USING_CPP17
template <typename TTypeList, typename T>
inline constexpr size_t type_list_index_of_v = etl::type_list_index_of_type<TTypeList, T>::value;
#endif
//***************************************************************************
/// Defines a bool constant that is true if the type_list contains the specified type, otherwise false.
//***************************************************************************
template <typename T, typename TTypes>
struct type_list_contains;
template <typename T, typename... TTypes>
struct type_list_contains<etl::type_list<TTypes...>, T>
: public etl::integral_constant<bool, etl::is_one_of<T, TTypes...>::value>
{
};
template <typename T>
struct type_list_contains<type_list<>, T>
: public etl::integral_constant<bool, false>
{
};
#if ETL_USING_CPP17
template <typename TTypeList, typename T>
inline constexpr bool type_list_contains_v = etl::type_list_contains<TTypeList, T>::value;
#endif
//***************************************************************************
/// Defines an integral constant that is maximum sizeof all types in the type_list.
/// If the type_list is empty, then defined as 0.
//***************************************************************************
template <typename T>
struct type_list_max_size;
template <typename... TTypes>
struct type_list_max_size<etl::type_list<TTypes...>>
: public etl::integral_constant<size_t, etl::largest<TTypes...>::size>
{
};
template <>
struct type_list_max_size<type_list<>>
: public etl::integral_constant<size_t, 0>
{
};
#if ETL_USING_CPP17
template <typename TTypeList>
inline constexpr size_t type_list_max_size_v = etl::type_list_max_size<TTypeList>::value;
#endif
//***************************************************************************
/// Defines an integral constant that is maximum alignment all types in the type_list.
/// If the type_list is empty, then defined as 1.
//***************************************************************************
template <typename T>
struct type_list_max_alignment;
template <typename... TTypes>
struct type_list_max_alignment<etl::type_list<TTypes...>>
: public etl::integral_constant<size_t, etl::largest<TTypes...>::alignment>
{
};
template <>
struct type_list_max_alignment<type_list<>>
: public etl::integral_constant<size_t, 1>
{
};
#if ETL_USING_CPP17
template <typename TTypeList>
inline constexpr size_t type_list_max_alignment_v = etl::type_list_max_alignment<TTypeList>::value;
#endif
//***************************************************************************
/// Declares a new type_list by selecting types from a given type_list, according to an index sequence.
//***************************************************************************
template <typename TTypeList, size_t... Indices>
struct type_list_select
{
ETL_STATIC_ASSERT((etl::is_base_of<etl::type_list<>, TTypeList>::value), "TTypeList must be an etl::type_list");
using type = type_list<type_list_type_at_index_t<TTypeList, Indices>...>;
};
template <typename TTypeList, size_t... Indices>
using type_list_select_t = typename type_list_select<TTypeList, Indices...>::type;
//***************************************************************************
/// Concatenates two or more type_lists.
//***************************************************************************
template <typename... TTypes>
struct type_list_cat;
template <typename... TTypes1, typename... TTypes2, typename... TTail>
struct type_list_cat<etl::type_list<TTypes1...>, etl::type_list<TTypes2...>, TTail...>
{
using type = typename type_list_cat<etl::type_list<TTypes1..., TTypes2...>, TTail...>::type;
};
template <typename T>
struct type_list_cat<T>
{
using type = T;
};
template <typename... TypeLists>
using type_list_cat_t = typename type_list_cat<TypeLists...>::type;
}
#endif
#endif

View File

@ -628,17 +628,12 @@ namespace etl
{
private:
template<typename T> struct dummy {};
struct internal: TDerived, dummy<int>{};
static TBase* check(TBase*) { return (TBase*)0; }
template<typename T>
static char check(dummy<T>*) { return 0; }
static char check(...) { return 0; }
public:
static const bool value = (sizeof(check((internal*)0)) == sizeof(TBase*));
static const bool value = (sizeof(check((TDerived*)0)) == sizeof(TBase*));
};
// For when TBase or TDerived is a fundamental type.
@ -1327,6 +1322,79 @@ typedef integral_constant<bool, true> true_type;
// ETL extended type traits.
//***************************************************************************
#if ETL_USING_CPP11
//***************************************************************************
/// conjunction
#if ETL_USING_CPP11
template <typename...>
struct conjunction : public etl::true_type
{
};
template <typename T1, typename... Tn>
struct conjunction<T1, Tn...> : public etl::conditional_t<bool(T1::value), etl::conjunction<Tn...>, T1>
{
};
template <typename T>
struct conjunction<T> : public T
{
};
#endif
#if ETL_USING_CPP17
template <typename... T>
inline constexpr bool conjunction_v = conjunction<T...>::value;
#endif
//***************************************************************************
/// disjunction
#if ETL_USING_CPP11
template <typename...>
struct disjunction : public etl::false_type
{
};
template <typename T1, typename... Tn>
struct disjunction<T1, Tn...> : public etl::conditional_t<bool(T1::value), T1, disjunction<Tn...>>
{
};
template <typename T1> struct disjunction<T1> : public T1
{
};
#endif
#if ETL_USING_CPP17
template <typename... T>
inline constexpr bool disjunction_v = etl::disjunction<T...>::value;
#endif
#endif
//***************************************************************************
/// exclusive_disjunction
#if ETL_USING_CPP11
template <typename... TTypes>
struct exclusive_disjunction;
template <typename T>
struct exclusive_disjunction<T> : public etl::bool_constant<T::value>
{
};
// Recursive case: XOR the first two values and recurse
template <typename T1, typename T2, typename... TRest>
struct exclusive_disjunction<T1, T2, TRest...> : public etl::exclusive_disjunction<etl::integral_constant<bool, etl::disjunction<T1, T2>::value && !etl::conjunction<T1, T2>::value>, TRest...>
{
};
#endif
#if ETL_USING_CPP17
template <typename... T>
inline constexpr bool exclusive_disjunction_v = etl::exclusive_disjunction<T...>::value;
#endif
//***************************************************************************
/// conditional_integral_constant
// /\ingroup type_traits
@ -1349,19 +1417,11 @@ typedef integral_constant<bool, true> true_type;
#if ETL_USING_CPP11
//***************************************************************************
/// Template to determine if a type is one of a specified list.
/// Template to determine if a type is a base of all types in a specified list.
///\ingroup types
template <typename T, typename T1, typename... TRest>
struct is_one_of
template <typename T, typename... TRest>
struct is_one_of : etl::disjunction<etl::is_same<T, TRest>...>
{
static const bool value = etl::is_same<T, T1>::value ||
etl::is_one_of<T, TRest...>::value;
};
template <typename T, typename T1>
struct is_one_of<T, T1>
{
static const bool value = etl::is_same<T, T1>::value;
};
#else
//***************************************************************************
@ -1399,21 +1459,46 @@ typedef integral_constant<bool, true> true_type;
inline constexpr bool is_one_of_v = etl::is_one_of<T, TRest...>::value;
#endif
#if ETL_USING_CPP11
namespace private_type_traits
{
//***************************************************************************
// Helper to count occurrences of a type in a list of types
template<typename T, typename... TTypes>
struct count_type;
// Base case: zero occurrences
template<typename T>
struct count_type<T> : etl::integral_constant<size_t, 0>
{
};
// Recursive case: increment count if head is the same as T, otherwise continue with tail
template<typename T, typename THead, typename... TTail>
struct count_type<T, THead, TTail...> : etl::integral_constant<size_t, (etl::is_same<T, THead>::value ? 1 : 0) + count_type<T, TTail...>::value>
{
};
}
template<typename T, typename... TTypes>
struct has_duplicates_of
: etl::integral_constant<bool, (private_type_traits::count_type<T, TTypes...>::value > 1)>
{
};
#endif
#if ETL_USING_CPP17
template <typename T, typename... TRest>
inline constexpr bool has_duplicates_of_v = etl::has_duplicates_of<T, TRest...>::value;
#endif
#if ETL_USING_CPP11
//***************************************************************************
/// Template to determine if a type is a base of all types in a specified list.
///\ingroup types
template <typename T, typename T1, typename... TRest>
struct is_base_of_all
template <typename TBase, typename... TDerived>
struct is_base_of_all : etl::conjunction<etl::is_base_of<TBase, TDerived>...>
{
static const bool value = etl::is_base_of<T, T1>::value &&
etl::is_base_of_all<T, TRest...>::value;
};
template <typename T, typename T1>
struct is_base_of_all<T, T1>
{
static const bool value = etl::is_base_of<T, T1>::value;
};
#endif
@ -1426,18 +1511,11 @@ typedef integral_constant<bool, true> true_type;
//***************************************************************************
/// Template to determine if a type is a base of any type in a specified list.
///\ingroup types
template <typename T, typename T1, typename... TRest>
struct is_base_of_any
template <typename TBase, typename... TDerived>
struct is_base_of_any : etl::disjunction<etl::is_base_of<TBase, TDerived>...>
{
static const bool value = etl::is_base_of<T, T1>::value ||
etl::is_base_of_any<T, TRest...>::value;
};
template <typename T, typename T1>
struct is_base_of_any<T, T1>
{
static const bool value = etl::is_base_of<T, T1>::value;
};
#endif
#if ETL_USING_CPP17
@ -1445,6 +1523,28 @@ typedef integral_constant<bool, true> true_type;
inline constexpr bool is_base_of_any_v = etl::is_base_of_any<T, TRest...>::value;
#endif
//***************************************************************************
/// Get the Nth base of a recursively inherited type.
/// Requires that the class has defined 'base_type'.
//***************************************************************************
// Recursive definition of the type.
template <size_t N, typename TType>
struct nth_base
{
typedef typename nth_base<N - 1U, typename TType::base_type>::type type;
};
template <typename TType>
struct nth_base<0, TType>
{
typedef TType type;
};
#if ETL_USING_CPP11
template <size_t N, typename TType>
using nth_base_t = typename nth_base<N, TType>::type;
#endif
//***************************************************************************
/// A set of templates to allow related types to be derived.
///\ingroup types
@ -1598,70 +1698,15 @@ typedef integral_constant<bool, true> true_type;
#if ETL_USING_CPP11
//***************************************************************************
/// are_all_same
template <typename T, typename T1, typename... TRest>
struct are_all_same
{
static const bool value = etl::is_same<T, T1>::value &&
etl::are_all_same<T, TRest...>::value;
};
template <typename T, typename T1>
struct are_all_same<T, T1>
{
static const bool value = etl::is_same<T, T1>::value;
};
#endif
#if ETL_USING_CPP17
template <typename T, typename T1, typename... TRest>
inline constexpr bool are_all_same_v = are_all_same<T, T1, TRest...>::value;
#endif
//***************************************************************************
/// conjunction
#if ETL_USING_CPP11
template <typename...>
struct conjunction : public etl::true_type
{
};
template <typename T1, typename... Tn>
struct conjunction<T1, Tn...> : public etl::conditional_t<bool(T1::value), etl::conjunction<Tn...>, T1>
{
};
template <typename T>
struct conjunction<T> : public T
template <typename T, typename... TRest>
struct are_all_same : etl::conjunction<etl::is_same<T, TRest>...>
{
};
#endif
#if ETL_USING_CPP17
template <typename... T>
inline constexpr bool conjunction_v = conjunction<T...>::value;
#endif
//***************************************************************************
/// disjunction
#if ETL_USING_CPP11
template <typename...>
struct disjunction : public etl::false_type
{
};
template <typename T1, typename... Tn>
struct disjunction<T1, Tn...> : public etl::conditional_t<bool(T1::value), T1, disjunction<Tn...>>
{
};
template <typename T1> struct disjunction<T1> : public T1
{
};
#endif
#if ETL_USING_CPP17
template <typename... T>
inline constexpr bool disjunction_v = etl::disjunction<T...>::value;
template <typename T, typename... TRest>
inline constexpr bool are_all_same_v = are_all_same<T, TRest...>::value;
#endif
//***************************************************************************
@ -2342,18 +2387,6 @@ typedef integral_constant<bool, true> true_type;
template <typename T, typename... TTypes>
inline constexpr size_t count_of_v = etl::count_of<T, TTypes...>::value;
#endif
#if ETL_USING_CPP11
//*********************************************
// has_duplicates_of
template <typename T, typename... TTypes>
struct has_duplicates_of : etl::bool_constant<(etl::count_of<T, TTypes...>::value > 1U)> {};
#endif
#if ETL_USING_CPP17
template <typename T, typename... TTypes>
inline constexpr bool has_duplicates_of_v = etl::has_duplicates_of<T, TTypes...>::value;
#endif
}
// Helper macros

View File

@ -46,7 +46,7 @@ namespace etl
{
inline namespace string_literals
{
constexpr etl::u16string_view operator ""_sv(const char16_t* str, size_t length) noexcept
inline constexpr etl::u16string_view operator ""_sv(const char16_t* str, size_t length) noexcept
{
return etl::u16string_view{ str, length };
}
@ -227,6 +227,16 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
u16string& operator = (const etl::u16string_view& view)
{
this->assign(view);
return *this;
}
//*************************************************************************
/// Fix the internal pointers after a low level memory copy.
//*************************************************************************
@ -366,8 +376,8 @@ namespace etl
#endif
//*************************************************************************
/// From u16string_view.
///\param view The u16string_view.
/// From string_view.
///\param view The string_view.
//*************************************************************************
explicit u16string_ext(const etl::u16string_view& view, value_type* buffer, size_type buffer_size)
: iu16string(buffer, buffer_size - 1U)
@ -388,7 +398,6 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
@ -412,6 +421,16 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
u16string_ext& operator = (const etl::u16string_view& view)
{
this->assign(view);
return *this;
}
//*************************************************************************
/// Fix the internal pointers after a low level memory copy.
//*************************************************************************

View File

@ -46,7 +46,7 @@ namespace etl
{
inline namespace string_literals
{
constexpr etl::u32string_view operator ""_sv(const char32_t* str, size_t length) noexcept
inline constexpr etl::u32string_view operator ""_sv(const char32_t* str, size_t length) noexcept
{
return etl::u32string_view{ str, length };
}
@ -227,6 +227,16 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
u32string& operator = (const etl::u32string_view& view)
{
this->assign(view);
return *this;
}
//*************************************************************************
/// Fix the internal pointers after a low level memory copy.
//*************************************************************************
@ -366,8 +376,8 @@ namespace etl
#endif
//*************************************************************************
/// From u32string_view.
///\param view The u32string_view.
/// From string_view.
///\param view The string_view.
//*************************************************************************
explicit u32string_ext(const etl::u32string_view& view, value_type* buffer, size_type buffer_size)
: iu32string(buffer, buffer_size - 1U)
@ -388,7 +398,6 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
@ -412,6 +421,16 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
u32string_ext& operator = (const etl::u32string_view& view)
{
this->assign(view);
return *this;
}
//*************************************************************************
/// Fix the internal pointers after a low level memory copy.
//*************************************************************************

View File

@ -49,7 +49,7 @@ namespace etl
{
inline namespace string_literals
{
constexpr etl::u8string_view operator ""_sv(const char8_t* str, size_t length) noexcept
inline constexpr etl::u8string_view operator ""_sv(const char8_t* str, size_t length) noexcept
{
return etl::u8string_view{ str, length };
}
@ -244,6 +244,16 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
u8string& operator = (const etl::u8string_view& view)
{
this->assign(view);
return *this;
}
//*************************************************************************
/// Fix the internal pointers after a low level memory copy.
//*************************************************************************
@ -409,7 +419,6 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
@ -433,6 +442,16 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
u8string_ext& operator = (const etl::u8string_view& view)
{
this->assign(view);
return *this;
}
//*************************************************************************
/// Fix the internal pointers after a low level memory copy.
//*************************************************************************

File diff suppressed because it is too large Load Diff

59
include/etl/uncopyable.h Normal file
View File

@ -0,0 +1,59 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2024 BMW AG
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies 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.
******************************************************************************/
#ifndef ETL_UNCOPYABLE_INCLUDED
#define ETL_UNCOPYABLE_INCLUDED
#include "platform.h"
namespace etl
{
#if ETL_USING_CPP11
//***************************************************************************
/// An uncopyable base class.
/// Can be used to make a class uncopyable by deriving from it.
//***************************************************************************
class uncopyable
{
public:
uncopyable(uncopyable const&) = delete;
uncopyable& operator=(uncopyable const&) = delete;
protected:
uncopyable() = default;
~uncopyable() = default;
};
#endif
}
#endif

View File

@ -52,6 +52,8 @@ SOFTWARE.
#include "placement_new.h"
#include "initializer_list.h"
#include "private/comparator_is_transparent.h"
#include <stddef.h>
//*****************************************************************************
@ -599,6 +601,18 @@ namespace etl
return key_hash_function(key) % number_of_buckets;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns the bucket index for the key.
///\return The bucket index for the key.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_type get_bucket_index(const K& key) const
{
return key_hash_function(key) % number_of_buckets;
}
#endif
//*********************************************************************
/// Returns the size of the bucket key.
///\return The bucket size of the bucket key.
@ -610,6 +624,20 @@ namespace etl
return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns the size of the bucket key.
///\return The bucket size of the bucket key.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_type bucket_size(const K& key) const
{
size_t index = bucket(key);
return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
}
#endif
//*********************************************************************
/// Returns the maximum number of the buckets the container can hold.
///\return The maximum number of the buckets the container can hold.
@ -716,6 +744,52 @@ namespace etl
return pbucket->begin()->key_value_pair.second;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns a reference to the value at index 'key'
///\param key The key.
///\return A reference to the value at index 'key'
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
mapped_reference operator [](const K& key)
{
// Find the bucket.
bucket_t* pbucket = pbuckets + get_bucket_index(key);
// Find the first node in the bucket.
local_iterator inode = pbucket->begin();
// Walk the list looking for the right one.
while (inode != pbucket->end())
{
// Equal keys?
if (key_equal_function(key, inode->key_value_pair.first))
{
// Found a match.
return inode->key_value_pair.second;
}
else
{
++inode;
}
}
// Doesn't exist, so add a new one.
// Get a new node.
node_t* node = allocate_data_node();
node->clear();
::new ((void*)etl::addressof(node->key_value_pair.first)) key_type(key);
::new ((void*)etl::addressof(node->key_value_pair.second)) mapped_type();
ETL_INCREMENT_DEBUG_COUNT;
pbucket->insert_after(pbucket->before_begin(), *node);
adjust_first_last_markers_after_insert(pbucket);
return pbucket->begin()->key_value_pair.second;
}
#endif
//*********************************************************************
/// Returns a reference to the value at index 'key'
/// If asserts or exceptions are enabled, emits an etl::unordered_map_out_of_range if the key is not in the range.
@ -786,6 +860,82 @@ namespace etl
return begin()->second;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns a reference to the value at index 'key'
/// If asserts or exceptions are enabled, emits an etl::unordered_map_out_of_range if the key is not in the range.
///\param key The key.
///\return A reference to the value at index 'key'
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
mapped_reference at(const K& key)
{
// Find the bucket.
bucket_t* pbucket = pbuckets + get_bucket_index(key);
// Find the first node in the bucket.
local_iterator inode = pbucket->begin();
// Walk the list looking for the right one.
while (inode != pbucket->end())
{
// Equal keys?
if (key_equal_function(key, inode->key_value_pair.first))
{
// Found a match.
return inode->key_value_pair.second;
}
else
{
++inode;
}
}
// Doesn't exist.
ETL_ASSERT(false, ETL_ERROR(unordered_map_out_of_range));
return begin()->second;
}
#endif
#if ETL_USING_CPP11
//*********************************************************************
/// Returns a const reference to the value at index 'key'
/// If asserts or exceptions are enabled, emits an etl::unordered_map_out_of_range if the key is not in the range.
///\param key The key.
///\return A const reference to the value at index 'key'
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
const_mapped_reference at(const K& key) const
{
// Find the bucket.
bucket_t* pbucket = pbuckets + get_bucket_index(key);
// Find the first node in the bucket.
local_iterator inode = pbucket->begin();
// Walk the list looking for the right one.
while (inode != pbucket->end())
{
// Equal keys?
if (key_equal_function(key, inode->key_value_pair.first))
{
// Found a match.
return inode->key_value_pair.second;
}
else
{
++inode;
}
}
// Doesn't exist.
ETL_ASSERT(false, ETL_ERROR(unordered_map_out_of_range));
return begin()->second;
}
#endif
//*********************************************************************
/// Assigns values to the unordered_map.
/// If asserts or exceptions are enabled, emits unordered_map_full if the unordered_map does not have enough free space.
@ -1040,6 +1190,41 @@ namespace etl
return n;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Erases an element.
///\param key The key to erase.
///\return The number of elements erased. 0 or 1.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_t erase(const K& key)
{
size_t n = 0UL;
size_t index = get_bucket_index(key);
bucket_t& bucket = pbuckets[index];
local_iterator iprevious = bucket.before_begin();
local_iterator icurrent = bucket.begin();
// Search for the key, if we have it.
while ((icurrent != bucket.end()) && (!key_equal_function(icurrent->key_value_pair.first, key)))
{
++iprevious;
++icurrent;
}
// Did we find it?
if (icurrent != bucket.end())
{
delete_data_node(iprevious, icurrent, bucket);
n = 1;
}
return n;
}
#endif
//*********************************************************************
/// Erases an element.
///\param ielement Iterator to the element.
@ -1141,6 +1326,19 @@ namespace etl
return (find(key) == end()) ? 0 : 1;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Counts an element.
///\param key The key to search for.
///\return 1 if the key exists, otherwise 0.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_t count(const K& key) const
{
return (find(key) == end()) ? 0 : 1;
}
#endif
//*********************************************************************
/// Finds an element.
///\param key The key to search for.
@ -1209,6 +1407,80 @@ namespace etl
return end();
}
#if ETL_USING_CPP11
//*********************************************************************
/// Finds an element.
///\param key The key to search for.
///\return An iterator to the element if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
iterator find(const K& key)
{
size_t index = get_bucket_index(key);
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
{
// Step though the list until we find the end or an equivalent key.
local_iterator inode = bucket.begin();
local_iterator iend = bucket.end();
while (inode != iend)
{
// Do we have this one?
if (key_equal_function(key, inode->key_value_pair.first))
{
return iterator((pbuckets + number_of_buckets), pbucket, inode);
}
++inode;
}
}
return end();
}
#endif
#if ETL_USING_CPP11
//*********************************************************************
/// Finds an element.
///\param key The key to search for.
///\return An iterator to the element if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
const_iterator find(const K& key) const
{
size_t index = get_bucket_index(key);
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
{
// Step though the list until we find the end or an equivalent key.
local_iterator inode = bucket.begin();
local_iterator iend = bucket.end();
while (inode != iend)
{
// Do we have this one?
if (key_equal_function(key, inode->key_value_pair.first))
{
return iterator((pbuckets + number_of_buckets), pbucket, inode);
}
++inode;
}
}
return end();
}
#endif
//*********************************************************************
/// Returns a range containing all elements with key key in the container.
/// The range is defined by two iterators, the first pointing to the first
@ -1251,6 +1523,54 @@ namespace etl
return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns a range containing all elements with key key in the container.
/// The range is defined by two iterators, the first pointing to the first
/// element of the wanted range and the second pointing past the last
/// element of the range.
///\param key The key to search for.
///\return An iterator pair to the range of elements if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
ETL_OR_STD::pair<iterator, iterator> equal_range(const K& key)
{
iterator f = find(key);
iterator l = f;
if (l != end())
{
++l;
}
return ETL_OR_STD::pair<iterator, iterator>(f, l);
}
#endif
#if ETL_USING_CPP11
//*********************************************************************
/// Returns a range containing all elements with key key in the container.
/// The range is defined by two iterators, the first pointing to the first
/// element of the wanted range and the second pointing past the last
/// element of the range.
///\param key The key to search for.
///\return A const iterator pair to the range of elements if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const K& key) const
{
const_iterator f = find(key);
const_iterator l = f;
if (l != end())
{
++l;
}
return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
}
#endif
//*************************************************************************
/// Gets the size of the unordered_map.
//*************************************************************************
@ -1361,6 +1681,25 @@ namespace etl
}
#endif
//*************************************************************************
/// Check if the unordered_map contains the key.
//*************************************************************************
bool contains(const_key_reference key) const
{
return find(key) != end();
}
#if ETL_USING_CPP11
//*************************************************************************
/// Check if the unordered_map contains the key.
//*************************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
bool contains(const K& key) const
{
return find(key) != end();
}
#endif
protected:
//*********************************************************************

View File

@ -52,6 +52,8 @@ SOFTWARE.
#include "placement_new.h"
#include "initializer_list.h"
#include "private/comparator_is_transparent.h"
#include <stddef.h>
//*****************************************************************************
@ -597,6 +599,18 @@ namespace etl
return key_hash_function(key) % number_of_buckets;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns the bucket index for the key.
///\return The bucket index for the key.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_type get_bucket_index(const K& key) const
{
return key_hash_function(key) % number_of_buckets;
}
#endif
//*********************************************************************
/// Returns the size of the bucket key.
///\return The bucket size of the bucket key.
@ -608,6 +622,20 @@ namespace etl
return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns the size of the bucket key.
///\return The bucket size of the bucket key.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_type bucket_size(const K& key) const
{
size_t index = bucket(key);
return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
}
#endif
//*********************************************************************
/// Returns the maximum number of the buckets the container can hold.
///\return The maximum number of the buckets the container can hold.
@ -868,6 +896,43 @@ namespace etl
return n;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Erases an element.
///\param key The key to erase.
///\return The number of elements erased.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_t erase(const K& key)
{
size_t n = 0UL;
size_t bucket_id = get_bucket_index(key);
bucket_t& bucket = pbuckets[bucket_id];
local_iterator iprevious = bucket.before_begin();
local_iterator icurrent = bucket.begin();
while (icurrent != bucket.end())
{
if (key_equal_function(icurrent->key_value_pair.first, key))
{
delete_data_node(iprevious, icurrent, bucket);
++n;
icurrent = iprevious;
}
else
{
++iprevious;
}
++icurrent;
}
return n;
}
#endif
//*********************************************************************
/// Erases an element.
///\param ielement Iterator to the element.
@ -985,6 +1050,35 @@ namespace etl
return n;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Counts an element.
///\param key The key to search for.
///\return 1 if the key exists, otherwise 0.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_t count(const K& key) const
{
size_t n = 0UL;
const_iterator f = find(key);
const_iterator l = f;
if (l != end())
{
++l;
++n;
while ((l != end()) && key_equal_function(key, l->first))
{
++l;
++n;
}
}
return n;
}
#endif
//*********************************************************************
/// Finds an element.
///\param key The key to search for.
@ -1053,6 +1147,80 @@ namespace etl
return end();
}
#if ETL_USING_CPP11
//*********************************************************************
/// Finds an element.
///\param key The key to search for.
///\return An iterator to the element if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
iterator find(const K& key)
{
size_t index = get_bucket_index(key);
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
{
// Step though the list until we find the end or an equivalent key.
local_iterator inode = bucket.begin();
local_iterator iend = bucket.end();
while (inode != iend)
{
// Do we have this one?
if (key_equal_function(key, inode->key_value_pair.first))
{
return iterator((pbuckets + number_of_buckets), pbucket, inode);
}
++inode;
}
}
return end();
}
#endif
#if ETL_USING_CPP11
//*********************************************************************
/// Finds an element.
///\param key The key to search for.
///\return An iterator to the element if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
const_iterator find(const K& key) const
{
size_t index = get_bucket_index(key);
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
{
// Step though the list until we find the end or an equivalent key.
local_iterator inode = bucket.begin();
local_iterator iend = bucket.end();
while (inode != iend)
{
// Do we have this one?
if (key_equal_function(key, inode->key_value_pair.first))
{
return const_iterator((pbuckets + number_of_buckets), pbucket, inode);
}
++inode;
}
}
return end();
}
#endif
//*********************************************************************
/// Returns a range containing all elements with key key in the container.
/// The range is defined by two iterators, the first pointing to the first
@ -1105,6 +1273,64 @@ namespace etl
return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns a range containing all elements with key key in the container.
/// The range is defined by two iterators, the first pointing to the first
/// element of the wanted range and the second pointing past the last
/// element of the range.
///\param key The key to search for.
///\return An iterator pair to the range of elements if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
ETL_OR_STD::pair<iterator, iterator> equal_range(const K& key)
{
iterator f = find(key);
iterator l = f;
if (l != end())
{
++l;
while ((l != end()) && key_equal_function(key, l->first))
{
++l;
}
}
return ETL_OR_STD::pair<iterator, iterator>(f, l);
}
#endif
#if ETL_USING_CPP11
//*********************************************************************
/// Returns a range containing all elements with key key in the container.
/// The range is defined by two iterators, the first pointing to the first
/// element of the wanted range and the second pointing past the last
/// element of the range.
///\param key The key to search for.
///\return A const iterator pair to the range of elements if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const K& key) const
{
const_iterator f = find(key);
const_iterator l = f;
if (l != end())
{
++l;
while ((l != end()) && key_equal_function(key, l->first))
{
++l;
}
}
return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
}
#endif
//*************************************************************************
/// Gets the size of the unordered_multimap.
//*************************************************************************
@ -1216,6 +1442,25 @@ namespace etl
}
#endif
//*************************************************************************
/// Check if the unordered_multimap contains the key.
//*************************************************************************
bool contains(const_key_reference key) const
{
return find(key) != end();
}
#if ETL_USING_CPP11
//*************************************************************************
/// Check if the unordered_map contains the key.
//*************************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
bool contains(const K& key) const
{
return find(key) != end();
}
#endif
protected:
//*********************************************************************

View File

@ -51,6 +51,8 @@ SOFTWARE.
#include "placement_new.h"
#include "initializer_list.h"
#include "private/comparator_is_transparent.h"
#include <stddef.h>
//*****************************************************************************
@ -588,6 +590,18 @@ namespace etl
return key_hash_function(key) % number_of_buckets;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns the bucket index for the key.
///\return The bucket index for the key.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_type get_bucket_index(const K& key) const
{
return key_hash_function(key) % number_of_buckets;
}
#endif
//*********************************************************************
/// Returns the size of the bucket key.
///\return The bucket size of the bucket key.
@ -599,6 +613,20 @@ namespace etl
return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns the size of the bucket key.
///\return The bucket size of the bucket key.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_type bucket_size(const K& key) const
{
size_t index = bucket(key);
return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
}
#endif
//*********************************************************************
/// Returns the maximum number of the buckets the container can hold.
///\return The maximum number of the buckets the container can hold.
@ -712,6 +740,79 @@ namespace etl
return result;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Inserts a value to the unordered_multiset.
/// If asserts or exceptions are enabled, emits unordered_multiset_full if the unordered_multiset is already full.
///\param value The value to insert.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
ETL_OR_STD::pair<iterator, bool> insert(const K& key)
{
ETL_OR_STD::pair<iterator, bool> result(end(), false);
ETL_ASSERT(!full(), ETL_ERROR(unordered_multiset_full));
// Get the hash index.
size_t index = get_bucket_index(key);
// Get the bucket & bucket iterator.
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// The first one in the bucket?
if (bucket.empty())
{
// Get a new node.
node_t* node = allocate_data_node();
node->clear();
::new (&node->key) value_type(key);
ETL_INCREMENT_DEBUG_COUNT;
// Just add the pointer to the bucket;
bucket.insert_after(bucket.before_begin(), *node);
adjust_first_last_markers_after_insert(&bucket);
result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
result.second = true;
}
else
{
// Step though the bucket looking for a place to insert.
local_iterator inode_previous = bucket.before_begin();
local_iterator inode = bucket.begin();
while (inode != bucket.end())
{
// Do we already have this key?
if (key_equal_function(inode->key, key))
{
break;
}
++inode_previous;
++inode;
}
// Get a new node.
node_t* node = allocate_data_node();
node->clear();
::new (&node->key) value_type(key);
ETL_INCREMENT_DEBUG_COUNT;
// Add the node to the end of the bucket;
bucket.insert_after(inode_previous, *node);
adjust_first_last_markers_after_insert(&bucket);
++inode_previous;
result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
result.second = true;
}
return result;
}
#endif
#if ETL_USING_CPP11
//*********************************************************************
/// Inserts a value to the unordered_multiset.
@ -846,6 +947,43 @@ namespace etl
return n;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Erases an element.
///\param key The key to erase.
///\return The number of elements erased. 0 or 1.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_t erase(const K& key)
{
size_t n = 0UL;
size_t bucket_id = get_bucket_index(key);
bucket_t& bucket = pbuckets[bucket_id];
local_iterator iprevious = bucket.before_begin();
local_iterator icurrent = bucket.begin();
while (icurrent != bucket.end())
{
if (key_equal_function(icurrent->key, key))
{
delete_data_node(iprevious, icurrent, bucket);
++n;
icurrent = iprevious;
}
else
{
++iprevious;
}
++icurrent;
}
return n;
}
#endif
//*********************************************************************
/// Erases an element.
///\param ielement Iterator to the element.
@ -963,6 +1101,35 @@ namespace etl
return n;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Counts an element.
///\param key The key to search for.
///\return 1 if the key exists, otherwise 0.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_t count(const K& key) const
{
size_t n = 0UL;
const_iterator f = find(key);
const_iterator l = f;
if (l != end())
{
++l;
++n;
while ((l != end()) && key_equal_function(key, *l))
{
++l;
++n;
}
}
return n;
}
#endif
//*********************************************************************
/// Finds an element.
///\param key The key to search for.
@ -997,6 +1164,43 @@ namespace etl
return end();
}
#if ETL_USING_CPP11
//*********************************************************************
/// Finds an element.
///\param key The key to search for.
///\return An iterator to the element if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
iterator find(const K& key)
{
size_t index = get_bucket_index(key);
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
{
// Step though the list until we find the end or an equivalent key.
local_iterator inode = bucket.begin();
local_iterator iend = bucket.end();
while (inode != iend)
{
// Do we have this one?
if (key_equal_function(key, inode->key))
{
return iterator((pbuckets + number_of_buckets), pbucket, inode);
}
++inode;
}
}
return end();
}
#endif
//*********************************************************************
/// Finds an element.
///\param key The key to search for.
@ -1031,6 +1235,43 @@ namespace etl
return end();
}
#if ETL_USING_CPP11
//*********************************************************************
/// Finds an element.
///\param key The key to search for.
///\return An iterator to the element if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
const_iterator find(const K& key) const
{
size_t index = get_bucket_index(key);
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
{
// Step though the list until we find the end or an equivalent key.
local_iterator inode = bucket.begin();
local_iterator iend = bucket.end();
while (inode != iend)
{
// Do we have this one?
if (key_equal_function(key, inode->key))
{
return iterator((pbuckets + number_of_buckets), pbucket, inode);
}
++inode;
}
}
return end();
}
#endif
//*********************************************************************
/// Returns a range containing all elements with key key in the container.
/// The range is defined by two iterators, the first pointing to the first
@ -1057,6 +1298,35 @@ namespace etl
return ETL_OR_STD::pair<iterator, iterator>(f, l);
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns a range containing all elements with key key in the container.
/// The range is defined by two iterators, the first pointing to the first
/// element of the wanted range and the second pointing past the last
/// element of the range.
///\param key The key to search for.
///\return An iterator pair to the range of elements if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
ETL_OR_STD::pair<iterator, iterator> equal_range(const K& key)
{
iterator f = find(key);
iterator l = f;
if (l != end())
{
++l;
while ((l != end()) && key_equal_function(key, *l))
{
++l;
}
}
return ETL_OR_STD::pair<iterator, iterator>(f, l);
}
#endif
//*********************************************************************
/// Returns a range containing all elements with key key in the container.
/// The range is defined by two iterators, the first pointing to the first
@ -1083,6 +1353,35 @@ namespace etl
return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns a range containing all elements with key key in the container.
/// The range is defined by two iterators, the first pointing to the first
/// element of the wanted range and the second pointing past the last
/// element of the range.
///\param key The key to search for.
///\return A const iterator pair to the range of elements if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const K& key) const
{
const_iterator f = find(key);
const_iterator l = f;
if (l != end())
{
++l;
while ((l != end()) && key_equal_function(key, *l))
{
++l;
}
}
return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
}
#endif
//*************************************************************************
/// Gets the size of the unordered_multiset.
//*************************************************************************
@ -1194,6 +1493,25 @@ namespace etl
}
#endif
//*************************************************************************
/// Check if the unordered_multiset contains the key.
//*************************************************************************
bool contains(key_parameter_t key) const
{
return find(key) != end();
}
#if ETL_USING_CPP11
//*************************************************************************
/// Check if the unordered_map contains the key.
//*************************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
bool contains(const K& key) const
{
return find(key) != end();
}
#endif
protected:
//*********************************************************************

View File

@ -52,6 +52,8 @@ SOFTWARE.
#include "placement_new.h"
#include "initializer_list.h"
#include "private/comparator_is_transparent.h"
#include <stddef.h>
//*****************************************************************************
@ -589,6 +591,18 @@ namespace etl
return key_hash_function(key) % number_of_buckets;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns the bucket index for the key.
///\return The bucket index for the key.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_type get_bucket_index(const K& key) const
{
return key_hash_function(key) % number_of_buckets;
}
#endif
//*********************************************************************
/// Returns the size of the bucket key.
///\return The bucket size of the bucket key.
@ -600,6 +614,20 @@ namespace etl
return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns the size of the bucket key.
///\return The bucket size of the bucket key.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_type bucket_size(const K& key) const
{
size_t index = bucket(key);
return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
}
#endif
//*********************************************************************
/// Returns the maximum number of the buckets the container can hold.
///\return The maximum number of the buckets the container can hold.
@ -730,6 +758,96 @@ namespace etl
return result;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Inserts a value to the unordered_set.
/// If asserts or exceptions are enabled, emits unordered_set_full if the unordered_set is already full.
///\param value The value to insert.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
ETL_OR_STD::pair<iterator, bool> insert(const K& key)
{
ETL_OR_STD::pair<iterator, bool> result(end(), false);
if (full())
{
iterator iter = find(key);
if (iter == end())
{
ETL_ASSERT_FAIL(ETL_ERROR(unordered_set_full));
}
else
{
result.first = iter;
result.second = false;
return result;
}
}
// Get the hash index.
size_t index = get_bucket_index(key);
// Get the bucket & bucket iterator.
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// The first one in the bucket?
if (bucket.empty())
{
// Get a new node.
node_t* node = allocate_data_node();
node->clear();
::new (&node->key) value_type(key);
ETL_INCREMENT_DEBUG_COUNT;
// Just add the pointer to the bucket;
bucket.insert_after(bucket.before_begin(), *node);
adjust_first_last_markers_after_insert(&bucket);
result.first = iterator(pbuckets + number_of_buckets, pbucket, pbucket->begin());
result.second = true;
}
else
{
// Step though the bucket looking for a place to insert.
local_iterator inode_previous = bucket.before_begin();
local_iterator inode = bucket.begin();
while (inode != bucket.end())
{
// Do we already have this key?
if (key_equal_function(inode->key, key))
{
break;
}
++inode_previous;
++inode;
}
// Not already there?
if (inode == bucket.end())
{
// Get a new node.
node_t* node = allocate_data_node();
node->clear();
::new (&node->key) value_type(key);
ETL_INCREMENT_DEBUG_COUNT;
// Add the node to the end of the bucket;
bucket.insert_after(inode_previous, *node);
adjust_first_last_markers_after_insert(&bucket);
++inode_previous;
result.first = iterator(pbuckets + number_of_buckets, pbucket, inode_previous);
result.second = true;
}
}
return result;
}
#endif
#if ETL_USING_CPP11
//*********************************************************************
/// Inserts a value to the unordered_set.
@ -892,6 +1010,41 @@ namespace etl
return n;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Erases an element.
///\param key The key to erase.
///\return The number of elements erased. 0 or 1.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_t erase(const K& key)
{
size_t n = 0UL;
size_t index = get_bucket_index(key);
bucket_t& bucket = pbuckets[index];
local_iterator iprevious = bucket.before_begin();
local_iterator icurrent = bucket.begin();
// Search for the key, if we have it.
while ((icurrent != bucket.end()) && (!key_equal_function(icurrent->key, key)))
{
++iprevious;
++icurrent;
}
// Did we find it?
if (icurrent != bucket.end())
{
delete_data_node(iprevious, icurrent, bucket);
n = 1;
}
return n;
}
#endif
//*********************************************************************
/// Erases an element.
///\param ielement Iterator to the element.
@ -993,6 +1146,19 @@ namespace etl
return (find(key) == end()) ? 0 : 1;
}
#if ETL_USING_CPP11
//*********************************************************************
/// Counts an element.
///\param key The key to search for.
///\return 1 if the key exists, otherwise 0.
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
size_t count(const K& key) const
{
return (find(key) == end()) ? 0 : 1;
}
#endif
//*********************************************************************
/// Finds an element.
///\param key The key to search for.
@ -1061,6 +1227,80 @@ namespace etl
return end();
}
#if ETL_USING_CPP11
//*********************************************************************
/// Finds an element.
///\param key The key to search for.
///\return An iterator to the element if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
iterator find(const K& key)
{
size_t index = get_bucket_index(key);
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
{
// Step though the list until we find the end or an equivalent key.
local_iterator inode = bucket.begin();
local_iterator iend = bucket.end();
while (inode != iend)
{
// Do we have this one?
if (key_equal_function(key, inode->key))
{
return iterator(pbuckets + number_of_buckets, pbucket, inode);
}
++inode;
}
}
return end();
}
#endif
#if ETL_USING_CPP11
//*********************************************************************
/// Finds an element.
///\param key The key to search for.
///\return An iterator to the element if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
const_iterator find(const K& key) const
{
size_t index = get_bucket_index(key);
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
{
// Step though the list until we find the end or an equivalent key.
local_iterator inode = bucket.begin();
local_iterator iend = bucket.end();
while (inode != iend)
{
// Do we have this one?
if (key_equal_function(key, inode->key))
{
return iterator(pbuckets + number_of_buckets, pbucket, inode);
}
++inode;
}
}
return end();
}
#endif
//*********************************************************************
/// Returns a range containing all elements with key 'key' in the container.
/// The range is defined by two iterators, the first pointing to the first
@ -1103,6 +1343,54 @@ namespace etl
return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
}
#if ETL_USING_CPP11
//*********************************************************************
/// Returns a range containing all elements with key 'key' in the container.
/// The range is defined by two iterators, the first pointing to the first
/// element of the wanted range and the second pointing past the last
/// element of the range.
///\param key The key to search for.
///\return An iterator pair to the range of elements if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
ETL_OR_STD::pair<iterator, iterator> equal_range(const K& key)
{
iterator f = find(key);
iterator l = f;
if (l != end())
{
++l;
}
return ETL_OR_STD::pair<iterator, iterator>(f, l);
}
#endif
#if ETL_USING_CPP11
//*********************************************************************
/// Returns a range containing all elements with key 'key' in the container.
/// The range is defined by two iterators, the first pointing to the first
/// element of the wanted range and the second pointing past the last
/// element of the range.
///\param key The key to search for.
///\return A const iterator pair to the range of elements if the key exists, otherwise end().
//*********************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const K& key) const
{
const_iterator f = find(key);
const_iterator l = f;
if (l != end())
{
++l;
}
return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
}
#endif
//*************************************************************************
/// Gets the size of the unordered_set.
//*************************************************************************
@ -1214,6 +1502,25 @@ namespace etl
}
#endif
//*************************************************************************
/// Check if the unordered_set contains the key.
//*************************************************************************
bool contains(key_parameter_t key) const
{
return find(key) != end();
}
#if ETL_USING_CPP11
//*************************************************************************
/// Check if the unordered_map contains the key.
//*************************************************************************
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
bool contains(const K& key) const
{
return find(key) != end();
}
#endif
protected:
//*********************************************************************

View File

@ -34,6 +34,9 @@ SOFTWARE.
#include "platform.h"
#include "type_traits.h"
#include "private/tuple_element.h"
#include "private/tuple_size.h"
#if defined(ETL_IN_UNIT_TEST) || ETL_USING_STL
#if ETL_USING_CPP11
#include <utility>
@ -325,6 +328,33 @@ namespace etl
}
#endif
#if ETL_USING_CPP11
//******************************************************************************
template <size_t Index, typename T1, typename T2>
struct tuple_element<Index, ETL_OR_STD::pair<T1, T2> >
{
ETL_STATIC_ASSERT(Index < 2U, "pair has only 2 elements");
};
template <typename T1, typename T2>
struct tuple_element<0U, ETL_OR_STD::pair<T1, T2> >
{
typedef T1 type;
};
template <typename T1, typename T2>
struct tuple_element<1U, ETL_OR_STD::pair<T1, T2> >
{
typedef T2 type;
};
//******************************************************************************
template <typename T1, typename T2>
struct tuple_size<ETL_OR_STD::pair<T1, T2>> : public etl::integral_constant<size_t, 2U>
{
};
#endif
//******************************************************************************
template <typename T1, typename T2>
inline void swap(pair<T1, T2>& a, pair<T1, T2>& b)
@ -332,7 +362,7 @@ namespace etl
a.swap(b);
}
/// Two pairs of the same type are equal iff their members are equal.
/// Two pairs of the same type are equal if their members are equal.
template <typename T1, typename T2>
inline bool operator ==(const pair<T1, T2>& a, const pair<T1, T2>& b)
{
@ -512,13 +542,13 @@ namespace etl
template <size_t N, size_t... Indices>
struct make_index_sequence<N, etl::integer_sequence<size_t, Indices...>>
{
typedef typename make_index_sequence<N - 1, etl::integer_sequence<size_t, N - 1, Indices...>>::type type;
using type = typename make_index_sequence<N - 1, etl::integer_sequence<size_t, N - 1, Indices...>>::type;
};
template <size_t... Indices>
struct make_index_sequence<0, etl::integer_sequence<size_t, Indices...>>
{
typedef etl::integer_sequence<size_t, Indices...> type;
using type = etl::integer_sequence<size_t, Indices...>;
};
}
@ -526,9 +556,15 @@ namespace etl
template <size_t N>
using make_index_sequence = typename private_integer_sequence::make_index_sequence<N, etl::integer_sequence<size_t>>::type;
template <typename... TTypes>
using make_index_sequence_for = typename private_integer_sequence::make_index_sequence<sizeof...(TTypes), etl::integer_sequence<size_t>>::type;
//***********************************
template <size_t... Indices>
using index_sequence = etl::integer_sequence<size_t, Indices...>;
template <typename... TTypes>
using index_sequence_for = typename etl::make_index_sequence_for<TTypes...>;
#endif
//***************************************************************************
@ -601,10 +637,13 @@ namespace etl
#if ETL_USING_CPP11
//*************************************************************************
/// A function wrapper for free/global functions.
// A function wrapper for free/global functions.
// Deprecated.
// See etl::function_ptr_as_functor for a runtime time wrapper option.
// See etl::function_as_functor for a compile time wrapper option.
//*************************************************************************
template <typename TReturn, typename... TParams>
class functor
class ETL_DEPRECATED functor
{
public:
@ -629,18 +668,18 @@ namespace etl
/// The pointer to the function.
TReturn(*ptr)(TParams...);
};
#endif
#if ETL_USING_CPP11
//*****************************************************************************
// A wrapper for a member function
// Wrap a member function with a static free function.
// Creates a static member function that calls the specified member function.
// Deprecated
// See etl::member_function_as_static
//*****************************************************************************
template <typename T>
class member_function_wrapper;
template <typename TReturn, typename... TParams>
class member_function_wrapper<TReturn(TParams...)>
class ETL_DEPRECATED member_function_wrapper<TReturn(TParams...)>
{
public:
@ -650,12 +689,12 @@ namespace etl
return (Instance.*Method)(etl::forward<TParams>(params)...);
}
};
#endif
#if ETL_USING_CPP11
//*****************************************************************************
// A wrapper for a functor
// Wrap a functor with a static free function.
// Creates a static member function that calls the specified functor.
// Deprecated
// See etl::functor_as_static
//*****************************************************************************
template <typename T>
class functor_wrapper;
@ -672,6 +711,104 @@ namespace etl
}
};
#endif
#if ETL_USING_CPP17
//*****************************************************************************
// Wraps a functor with a static free function at compile time.
// Creates a static member 'call' that calls the specified functor.
//*****************************************************************************
template <auto& Instance>
struct functor_as_static
{
template <typename... TArgs>
static constexpr auto call(TArgs&&... args)
{
return (Instance.operator())(etl::forward<TArgs>(args)...);
}
};
//*****************************************************************************
// Wraps a member function with a static free function at compile time.
// Creates a static member 'call' that calls the specified member function.
//*****************************************************************************
template <auto Method, auto& Instance>
struct member_function_as_static
{
template <typename... TArgs>
static constexpr auto call(TArgs&&... args)
{
return (Instance.*Method)(etl::forward<TArgs>(args)...);
}
};
//*****************************************************************************
// Wraps a member function with a functor at compile time.
// Creates a functor that calls the specified member function.
//*****************************************************************************
template <auto Method, auto& Instance>
class member_function_as_functor
{
public:
template <typename... TArgs>
constexpr auto operator()(TArgs&&... args) const -> decltype((Instance.*Method)(etl::forward<TArgs>(args)...))
{
return (Instance.*Method)(etl::forward<TArgs>(args)...);
}
};
//*****************************************************************************
// Wraps a function with a functor at compile time.
// Creates a functor that calls the specified free function.
//*****************************************************************************
template <auto Function>
class function_as_functor
{
public:
template<typename... TArgs>
constexpr auto operator()(TArgs&&... args) const -> decltype(Function(etl::forward<TArgs>(args)...))
{
return Function(etl::forward<TArgs>(args)...);
}
};
#endif
#if ETL_USING_CPP11
//*****************************************************************************
// Wraps a function pointer with a functor at run time.
// Creates a functor that calls the specified free function.
//*****************************************************************************
template <typename T>
class function_ptr_as_functor;
template <typename TReturn, typename... TArgs>
class function_ptr_as_functor<TReturn(TArgs...)>
{
public:
//*********************************
/// Constructor.
//*********************************
constexpr function_ptr_as_functor(TReturn(*ptr_)(TArgs...))
: ptr(ptr_)
{
}
//*********************************
/// Const function operator.
//*********************************
constexpr TReturn operator()(TArgs... args) const
{
return ptr(etl::forward<TArgs>(args)...);
}
private:
/// The pointer to the function.
TReturn(*ptr)(TArgs...);
};
#endif
}
#endif

View File

@ -47,7 +47,6 @@ SOFTWARE.
#include "functional.h"
#include "static_assert.h"
#include "placement_new.h"
#include "algorithm.h"
#include "initializer_list.h"
#include <stddef.h>

View File

@ -39,8 +39,8 @@ SOFTWARE.
///\ingroup utilities
#define ETL_VERSION_MAJOR 20
#define ETL_VERSION_MINOR 39
#define ETL_VERSION_PATCH 4
#define ETL_VERSION_MINOR 40
#define ETL_VERSION_PATCH 0
#define ETL_VERSION ETL_STRING(ETL_VERSION_MAJOR) "." ETL_STRING(ETL_VERSION_MINOR) "." ETL_STRING(ETL_VERSION_PATCH)
#define ETL_VERSION_W ETL_WIDE_STRING(ETL_VERSION_MAJOR) L"." ETL_WIDE_STRING(ETL_VERSION_MINOR) L"." ETL_WIDE_STRING(ETL_VERSION_PATCH)

View File

@ -46,7 +46,7 @@ namespace etl
{
inline namespace string_literals
{
constexpr etl::wstring_view operator ""_sv(const wchar_t* str, size_t length) noexcept
inline constexpr etl::wstring_view operator ""_sv(const wchar_t* str, size_t length) noexcept
{
return etl::wstring_view{ str, length };
}
@ -227,6 +227,16 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
wstring& operator = (const etl::wstring_view& view)
{
this->assign(view);
return *this;
}
//*************************************************************************
/// Fix the internal pointers after a low level memory copy.
//*************************************************************************
@ -366,8 +376,8 @@ namespace etl
#endif
//*************************************************************************
/// From wstring_view.
///\param view The wstring_view.
/// From string_view.
///\param view The string_view.
//*************************************************************************
explicit wstring_ext(const etl::wstring_view& view, value_type* buffer, size_type buffer_size)
: iwstring(buffer, buffer_size - 1U)
@ -388,7 +398,6 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
@ -412,6 +421,16 @@ namespace etl
return *this;
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
wstring_ext& operator = (const etl::wstring_view& view)
{
this->assign(view);
return *this;
}
//*************************************************************************
/// Fix the internal pointers after a low level memory copy.
//*************************************************************************

View File

@ -1,6 +1,6 @@
{
"name": "Embedded Template Library",
"version": "20.39.4",
"version": "20.40.0",
"authors": {
"name": "John Wellbelove",
"email": "john.wellbelove@etlcpp.com"

View File

@ -1,5 +1,5 @@
name=Embedded Template Library
version=20.39.4
version=20.40.0
author= John Wellbelove <john.wellbelove@etlcpp.com>
maintainer=John Wellbelove <john.wellbelove@etlcpp.com>
license=MIT

View File

@ -1,4 +1,68 @@
===============================================================================
20.40.0
Updates:
Added new C++17 function wrappers
Simplified definition of is_base_of
Fixed static definition for etl::string
Redefined ETL_DEPRECATED
Updated nth_type to handle a type list of zero length
Updated Github Actions to checkout@v4
Added make_delegate for C++17
Added starts_with and ends_with to basic_string
Made construction from std::basic_string_view explicit
Added contains member function to string_view
Fixed possible null dereference for etl::multi_span operator ->
Fixed shadowing warnings
Changed etl::mem_cast to support bidirectional iterators
Make 'packed' have better cross platform functionality
Fixes:
#937 ETL_USING_LEGACY_VARIANT Is always getting evaluated to 1
#940 Allow etl::observer notification without argument
#942 Warning on pragma c++20-compat
#951 Can't get call_if to work because of etl::optional
#956 Fix build error (etl::circular_buffer)
#957 Support heterogenous lookup for maps
#959 Treat bitset with size_type
#972 Template not allowed warning in parameter pack
#979 QueuedMessageRouter does not work : message are not sent to queue
#980 Documentation clarification: Add link from endianess to unaligned_type
#982 Added return to etl::optional emplace, fixed typo
#984 Update Base64 Documentation
#986 Added const iterators to span
#987 Fix test loop
#992 Return reference from emplace() in etl::queue. Added return reference from stack::emplace
#993 Need "lighter weight" ETL_ASSERT
#997 Request: operator[ ] for containers can be configured to emit an exception
#1000 Make ETL_TYPEDEF Trivially Copyable
#1017 etl::max_element has undefined behavior if the range is empty
#1016 Allow compile time CRC calculation
#1019 UB when passing a temporary lambda to a delegate
#1022 Request: Add option to disable non-lock-free atomics - Added is_always_lock_free member constant to etl::atomic
#1030 Modify etl::message_packet to not require polymorphic messages
#1031 etl::string is invalid if calling assign() with itself. Added additional checks for self assignment.
#1032 Tasking Compiler Failure For parameter_pack.h
Pull Requests:
#947 Remove unused git submodule config
#965 Fix accident creation of a delegate to an rvalue delegate when copying/assigning from delegate with mismatching signature
#985 Add uncopyable.h, class uncopyable
#986 Added const iterators to span
#989 Packed unaligned_type
#990 Add contains() method to etl::unordered_map and etl::unordered_set
#992 Return reference from emplace() in etl::queue
#999 Add at_address() to etl::unaligned_type. Added etl::unaligned_type_ext instead at_address()
#1001 Add max_item_size() to etl::ipool
#1002 Add singleton_base
#1005 Fixed memory.h: mem_copy, mem_move, mem_compare for pointers to const
#1006 Fix arm64 signed char
#1007 Fix fixed extent span empty()
#1021 Some minor cleanup changes
#1014 Added missing rational arithmetic functions from <ratio>
#1027 Add etl::make_span()
===============================================================================
20.39.4
#948 Bug in queue pop can break queue.empty()
@ -13,6 +77,8 @@ Removed C++11 restriction on etl::observer::notification
Fixes:
#917 unaligned_type doesn't compile with floating point types
#923 Missing equality operator for class expected
#930 Unused parameter warnings
Pull Requests:
#946 Make include paths to private files relative

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5.0)
cmake_minimum_required(VERSION 3.10.0)
project(etl_unit_tests LANGUAGES CXX)
#include(FetchContent)
@ -410,6 +410,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
-Wuseless-cast
-Wshadow
-Wnull-dereference
-g
)
endif ()

View File

@ -209,6 +209,13 @@ public:
other.valid = false;
}
TestDataM(const TestDataM&& other) noexcept
: value(std::move(other.value))
, valid(true)
{
other.valid = false;
}
virtual ~TestDataM()
{
valid = false;
@ -249,8 +256,8 @@ public:
return valid;
}
T value;
bool valid;
T value;
mutable bool valid;
private:

Some files were not shown because too many files have changed in this diff Show More