mirror of
https://github.com/ETLCPP/etl.git
synced 2026-11-09 22:59:47 +08:00
Merge branch 'development' into jhe/semaphores
This commit is contained in:
commit
6f0c02c397
@ -5,7 +5,7 @@
|
||||
"build": {
|
||||
"dockerfile": "../Dockerfile",
|
||||
"args": {
|
||||
"BASE_IMAGE_NAME": "silkeh/clang:18-bullseye",
|
||||
"BASE_IMAGE_NAME": "silkeh/clang:18",
|
||||
"DEBIAN_SNAPSHOT": "none"
|
||||
},
|
||||
"context": "../context"
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
"build": {
|
||||
"dockerfile": "../Dockerfile",
|
||||
"args": {
|
||||
"BASE_IMAGE_NAME": "silkeh/clang:19-bullseye",
|
||||
"BASE_IMAGE_NAME": "silkeh/clang:19",
|
||||
"DEBIAN_SNAPSHOT": "none"
|
||||
},
|
||||
"context": "../context"
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
"build": {
|
||||
"dockerfile": "../Dockerfile",
|
||||
"args": {
|
||||
"BASE_IMAGE_NAME": "silkeh/clang:20-bullseye",
|
||||
"BASE_IMAGE_NAME": "silkeh/clang:20",
|
||||
"DEBIAN_SNAPSHOT": "none"
|
||||
},
|
||||
"context": "../context"
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
"build": {
|
||||
"dockerfile": "../Dockerfile",
|
||||
"args": {
|
||||
"BASE_IMAGE_NAME": "silkeh/clang:21-bullseye",
|
||||
"BASE_IMAGE_NAME": "silkeh/clang:21",
|
||||
"DEBIAN_SNAPSHOT": "none"
|
||||
},
|
||||
"context": "../context"
|
||||
|
||||
4
.github/workflows/bazel-gcc-c++23-no-stl.yml
vendored
4
.github/workflows/bazel-gcc-c++23-no-stl.yml
vendored
@ -44,7 +44,7 @@ jobs:
|
||||
- uses: actions/checkout@v6.0.3
|
||||
|
||||
- name: Build
|
||||
run: bazel build //test:etl_tests --cxxopt=-std=c++23 --copt=-DETL_NO_STL
|
||||
run: bazel build //test:etl_tests --cxxopt=-std=c++23 --copt=-DETL_NO_STL --//:etl_profile=//:no_profile
|
||||
|
||||
- name: Run tests
|
||||
run: bazel test //test:etl_tests --cxxopt=-std=c++23 --copt=-DETL_NO_STL --test_output=all
|
||||
run: bazel test //test:etl_tests --cxxopt=-std=c++23 --copt=-DETL_NO_STL --//:etl_profile=//:no_profile --test_output=all
|
||||
|
||||
3
.github/workflows/clang-c++11.yml
vendored
3
.github/workflows/clang-c++11.yml
vendored
@ -50,7 +50,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -79,7 +78,6 @@ jobs:
|
||||
export CXX=clang++
|
||||
export CXXFLAGS="-stdlib=libc++"
|
||||
export LDFLAGS="-stdlib=libc++"
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -101,7 +99,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
3
.github/workflows/clang-c++14.yml
vendored
3
.github/workflows/clang-c++14.yml
vendored
@ -50,7 +50,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -79,7 +78,6 @@ jobs:
|
||||
export CXX=clang++
|
||||
export CXXFLAGS="-stdlib=libc++"
|
||||
export LDFLAGS="-stdlib=libc++"
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -101,7 +99,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
3
.github/workflows/clang-c++17.yml
vendored
3
.github/workflows/clang-c++17.yml
vendored
@ -50,7 +50,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -79,7 +78,6 @@ jobs:
|
||||
export CXX=clang++
|
||||
export CXXFLAGS="-stdlib=libc++"
|
||||
export LDFLAGS="-stdlib=libc++"
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -101,7 +99,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
8
.github/workflows/clang-c++20.yml
vendored
8
.github/workflows/clang-c++20.yml
vendored
@ -62,7 +62,6 @@ jobs:
|
||||
export CXX=clang++-17
|
||||
export CXXFLAGS="-stdlib=libc++"
|
||||
export LDFLAGS="-stdlib=libc++"
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./
|
||||
clang-17 --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -91,7 +90,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang-17
|
||||
export CXX=clang++-17
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./
|
||||
clang-17 --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -120,7 +118,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang-17
|
||||
export CXX=clang++-17
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./
|
||||
clang-17 --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -149,7 +146,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang-17
|
||||
export CXX=clang++-17
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./
|
||||
clang-17 --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -171,7 +167,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -193,7 +188,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -215,7 +209,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -237,7 +230,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
32
.github/workflows/clang-c++23.yml
vendored
32
.github/workflows/clang-c++23.yml
vendored
@ -57,12 +57,19 @@ jobs:
|
||||
export CXX=clang++
|
||||
export CXXFLAGS="-stdlib=libc++"
|
||||
export LDFLAGS="-stdlib=libc++"
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 -DETL_ENABLE_SANITIZER=ON ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
- name: Run tests
|
||||
# The system libc++/libc++abi are not built with ASan. Exception objects
|
||||
# (e.g. std::runtime_error's reference counted string) are allocated with
|
||||
# operator new inside libc++.so, but released with free() inside
|
||||
# libc++abi.so, which AddressSanitizer reports as an alloc-dealloc-mismatch.
|
||||
# This is a libc++ packaging issue, not an ETL defect, so the check is
|
||||
# disabled for this job only.
|
||||
env:
|
||||
ASAN_OPTIONS: alloc_dealloc_mismatch=0
|
||||
run: ./test/etl_tests -v
|
||||
|
||||
build-clang-cpp23-linux-no-stl:
|
||||
@ -79,8 +86,7 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 -DETL_ENABLE_SANITIZER=ON ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
@ -101,8 +107,7 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 -DETL_ENABLE_SANITIZER=ON ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
@ -123,8 +128,7 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 -DETL_ENABLE_SANITIZER=ON ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
@ -145,8 +149,7 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 -DETL_ENABLE_SANITIZER=ON ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
@ -167,8 +170,7 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 -DETL_ENABLE_SANITIZER=ON ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
@ -189,8 +191,7 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 -DETL_ENABLE_SANITIZER=ON ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
@ -211,8 +212,7 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 -DETL_ENABLE_SANITIZER=ON ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
|
||||
9
.github/workflows/clang-c++26.yml
vendored
9
.github/workflows/clang-c++26.yml
vendored
@ -55,7 +55,6 @@ jobs:
|
||||
export CXX=clang++ && \
|
||||
export CXXFLAGS=-stdlib=libc++ && \
|
||||
export LDFLAGS=-stdlib=libc++ && \
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ && \
|
||||
clang --version && \
|
||||
make -j \$(getconf _NPROCESSORS_ONLN) && \
|
||||
@ -77,7 +76,6 @@ jobs:
|
||||
cd /workspaces/etl && \
|
||||
export CC=clang && \
|
||||
export CXX=clang++ && \
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ && \
|
||||
clang --version && \
|
||||
make -j \$(getconf _NPROCESSORS_ONLN) && \
|
||||
@ -99,7 +97,6 @@ jobs:
|
||||
cd /workspaces/etl && \
|
||||
export CC=clang && \
|
||||
export CXX=clang++ && \
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ && \
|
||||
clang --version && \
|
||||
make -j \$(getconf _NPROCESSORS_ONLN) && \
|
||||
@ -121,7 +118,6 @@ jobs:
|
||||
cd /workspaces/etl && \
|
||||
export CC=clang && \
|
||||
export CXX=clang++ && \
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./ && \
|
||||
clang --version && \
|
||||
make -j \$(getconf _NPROCESSORS_ONLN) && \
|
||||
@ -143,7 +139,6 @@ jobs:
|
||||
cd /workspaces/etl && \
|
||||
export CC=clang && \
|
||||
export CXX=clang++ && \
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./ && \
|
||||
clang --version && \
|
||||
make -j \$(getconf _NPROCESSORS_ONLN) && \
|
||||
@ -163,7 +158,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -185,7 +179,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -207,7 +200,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
@ -229,7 +221,6 @@ jobs:
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./
|
||||
clang --version
|
||||
make -j "$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
2
.github/workflows/gcc-c++11.yml
vendored
2
.github/workflows/gcc-c++11.yml
vendored
@ -49,7 +49,6 @@ jobs:
|
||||
- name: Build
|
||||
run: |
|
||||
git fetch
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
export CC=gcc
|
||||
export CXX=g++
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./
|
||||
@ -72,7 +71,6 @@ jobs:
|
||||
- name: Build
|
||||
run: |
|
||||
git fetch
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
export CC=gcc
|
||||
export CXX=g++
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./
|
||||
|
||||
2
.github/workflows/gcc-c++14.yml
vendored
2
.github/workflows/gcc-c++14.yml
vendored
@ -48,7 +48,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
export CC=gcc
|
||||
export CXX=g++
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./
|
||||
@ -70,7 +69,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
export CC=gcc
|
||||
export CXX=g++
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./
|
||||
|
||||
2
.github/workflows/gcc-c++17.yml
vendored
2
.github/workflows/gcc-c++17.yml
vendored
@ -48,7 +48,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
export CC=gcc
|
||||
export CXX=g++
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./
|
||||
@ -70,7 +69,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
export CC=gcc
|
||||
export CXX=g++
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./
|
||||
|
||||
4
.github/workflows/gcc-c++20.yml
vendored
4
.github/workflows/gcc-c++20.yml
vendored
@ -48,7 +48,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
export CC=gcc
|
||||
export CXX=g++
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./
|
||||
@ -70,7 +69,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
export CC=gcc
|
||||
export CXX=g++
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./
|
||||
@ -92,7 +90,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
export CC=gcc
|
||||
export CXX=g++
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./
|
||||
@ -114,7 +111,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
export CC=gcc
|
||||
export CXX=g++
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./
|
||||
|
||||
4
.github/workflows/gcc-c++23.yml
vendored
4
.github/workflows/gcc-c++23.yml
vendored
@ -48,7 +48,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
export CC=gcc-14
|
||||
export CXX=g++-14
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
|
||||
@ -70,7 +69,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
export CC=gcc-14
|
||||
export CXX=g++-14
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
|
||||
@ -92,7 +90,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
export CC=gcc-14
|
||||
export CXX=g++-14
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
|
||||
@ -114,7 +111,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
|
||||
export CC=gcc-14
|
||||
export CXX=g++-14
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./
|
||||
|
||||
4
.github/workflows/gcc-c++26.yml
vendored
4
.github/workflows/gcc-c++26.yml
vendored
@ -50,7 +50,6 @@ jobs:
|
||||
run: |
|
||||
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
|
||||
cd /workspaces/etl && \
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
|
||||
export CC=gcc && \
|
||||
export CXX=g++ && \
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ && \
|
||||
@ -72,7 +71,6 @@ jobs:
|
||||
run: |
|
||||
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
|
||||
cd /workspaces/etl && \
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
|
||||
export CC=gcc && \
|
||||
export CXX=g++ && \
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ && \
|
||||
@ -94,7 +92,6 @@ jobs:
|
||||
run: |
|
||||
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
|
||||
cd /workspaces/etl && \
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
|
||||
export CC=gcc && \
|
||||
export CXX=g++ && \
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./ && \
|
||||
@ -116,7 +113,6 @@ jobs:
|
||||
run: |
|
||||
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-ubuntu-2604 bash -c "\
|
||||
cd /workspaces/etl && \
|
||||
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 && \
|
||||
export CC=gcc && \
|
||||
export CXX=g++ && \
|
||||
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./ && \
|
||||
|
||||
13
BUILD.bazel
13
BUILD.bazel
@ -20,14 +20,23 @@ package(default_visibility = ["//visibility:public"])
|
||||
# strip_include_prefix = ".",
|
||||
# )
|
||||
#
|
||||
# The default is empty, so ETL's built-in defaults are used unless overridden.
|
||||
# The default of this label_flag is incompatible. This makes sure that the consumer
|
||||
# explicitly sets a profile, even if it is the `no_profile` defined below.
|
||||
|
||||
label_flag(
|
||||
name = "etl_profile",
|
||||
build_setting_default = ":no_profile",
|
||||
build_setting_default = ":incompatible_profile",
|
||||
)
|
||||
|
||||
cc_library(name = "no_profile")
|
||||
|
||||
cc_library(
|
||||
name = "incompatible_profile",
|
||||
target_compatible_with = [
|
||||
"@platforms//:incompatible",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "etl",
|
||||
hdrs = glob(["include/**/*.h"]),
|
||||
|
||||
@ -38,13 +38,23 @@ Defines data as an array of 'int', of length '10', containing the supplied data.
|
||||
**C++11 and above**
|
||||
|
||||
```cpp
|
||||
template <typename T, typename... TValues>
|
||||
constexpr auto make_array(TValues&&... values) -> etl::array<T, sizeof...(TValues)>
|
||||
template <typename T = void, typename... TValues>
|
||||
constexpr auto make_array(TValues&&... values) -> etl::array</*element-type*/, sizeof...(TValues)>
|
||||
```
|
||||
|
||||
The element type is `T` when supplied, otherwise the decayed common type of
|
||||
the arguments (the Library Fundamentals TS `make_array` design). An empty
|
||||
array requires the element type to be supplied explicitly, e.g.
|
||||
`etl::make_array<int>()`; a call with neither an element type nor arguments
|
||||
is ill-formed, as there is nothing to deduce the element type from.
|
||||
|
||||
### Example
|
||||
```cpp
|
||||
auto data = etl::make_array<int>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
// Deduced element type: etl::array<int, 10>.
|
||||
auto data = etl::make_array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
|
||||
// Explicit element type: etl::array<char, 10>. Each argument is converted.
|
||||
auto chars = etl::make_array<char>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
```
|
||||
|
||||
## Member types
|
||||
|
||||
@ -65,15 +65,20 @@ Defines data as an `forward_list` of int, of length 10, containing the supplied
|
||||
## Make template
|
||||
**C++11 and above**
|
||||
```cpp
|
||||
template <typename... T>
|
||||
constexpr auto make_forward_list(T&&... t) -> etl::forward_list<typename etl::common_type_t<T...>, sizeof...(T)>
|
||||
template <typename T = void, typename... TValues>
|
||||
constexpr auto make_forward_list(TValues&&... values) -> etl::forward_list</*element-type*/, sizeof...(TValues)>
|
||||
```
|
||||
|
||||
The element type is deduced as the common type of the arguments.
|
||||
The element type is `T` when supplied, otherwise the decayed common type of
|
||||
the arguments (the Library Fundamentals TS `make_array` design).
|
||||
|
||||
### Example
|
||||
```cpp
|
||||
// Deduced element type: etl::forward_list<int, 10>.
|
||||
auto data = etl::make_forward_list(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
|
||||
// Explicit element type: etl::forward_list<char, 10>. Each argument is converted.
|
||||
auto chars = etl::make_forward_list<char>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
```
|
||||
|
||||
## Member types
|
||||
|
||||
@ -8,7 +8,7 @@ weight: 4
|
||||
Similar to: `std::forward_list`
|
||||
{{< /callout >}}
|
||||
|
||||
An intrusive forward list.https://www.messenger.com/t/837634551/
|
||||
An intrusive forward list.
|
||||
|
||||
```cpp
|
||||
template <typename TValue, typename TLink>
|
||||
|
||||
@ -69,15 +69,20 @@ Defines data as an list of `int`, of length `10`, containing the supplied data.
|
||||
## Make template
|
||||
**C++11 and above**
|
||||
```cpp
|
||||
template <typename... T>
|
||||
constexpr auto make_list(T&&... t) -> etl::list<typename etl::common_type_t<T...>, sizeof...(T)>
|
||||
template <typename T = void, typename... TValues>
|
||||
constexpr auto make_list(TValues&&... values) -> etl::list</*element-type*/, sizeof...(TValues)>
|
||||
```
|
||||
|
||||
The element type is deduced as the common type of the arguments.
|
||||
The element type is `T` when supplied, otherwise the decayed common type of
|
||||
the arguments (the Library Fundamentals TS `make_array` design).
|
||||
|
||||
### Example
|
||||
```cpp
|
||||
// Deduced element type: etl::list<int, 10>.
|
||||
auto data = etl::make_list(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
|
||||
// Explicit element type: etl::list<char, 10>. Each argument is converted.
|
||||
auto chars = etl::make_list<char>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
```
|
||||
|
||||
## Member types
|
||||
|
||||
@ -239,7 +239,7 @@ The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`)
|
||||
---
|
||||
|
||||
```cpp
|
||||
pair<iterator, bool> emplace((const value_type& value))
|
||||
pair<iterator, bool> emplace(const value_type& value)
|
||||
pair<iterator, bool> emplace(const key_type& key, const mapped_type& value)
|
||||
```
|
||||
**Description**
|
||||
|
||||
@ -239,7 +239,7 @@ The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`)
|
||||
---
|
||||
|
||||
```cpp
|
||||
pair<iterator, bool> emplace((const value_type& value))
|
||||
pair<iterator, bool> emplace(const value_type& value)
|
||||
pair<iterator, bool> emplace(const key_type& key, const mapped_type& value)
|
||||
```
|
||||
**Description**
|
||||
|
||||
@ -69,11 +69,19 @@ const_reverse_iterator reverse_iterator<const_iterator>
|
||||
```cpp
|
||||
circular_buffer<typename T, size_t SIZE>();
|
||||
|
||||
circular_buffer<typename T, size_t SIZE>(size_t initial_size);
|
||||
|
||||
circular_buffer<typename T, size_t SIZE>(size_t initial_size, const_reference value);
|
||||
|
||||
circular_buffer<typename T, size_t SIZE>(const etl::circular_buffer<typename T, size_t SIZE>& other);
|
||||
|
||||
circular_buffer<typename T, size_t SIZE>(etl::circular_buffer<typename T, size_t SIZE>&& other);
|
||||
```
|
||||
|
||||
The `initial_size` constructor fills the buffer with default-constructed values.
|
||||
The `initial_size` and `value` constructor fills the buffer with copies of `value`.
|
||||
If `initial_size` exceeds `SIZE`, the buffer is filled to its capacity.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
@ -81,6 +89,10 @@ circular_buffer_ext(void* buffer, size_t max_size)
|
||||
|
||||
circular_buffer_ext(size_t max_size) 20.32.1
|
||||
|
||||
circular_buffer_ext(size_t initial_size, void* buffer, size_t max_size)
|
||||
|
||||
circular_buffer_ext(size_t initial_size, const_reference value, void* buffer, size_t max_size)
|
||||
|
||||
template <typename TIterator>
|
||||
circular_buffer_ext(TIterator first, const TIterator& last, void* buffer, size_t max_size)
|
||||
|
||||
@ -89,6 +101,10 @@ circular_buffer_ext(std::initializer_list<T> init, void* buffer, size_t max_size
|
||||
circular_buffer_ext(const circular_buffer_ext& other, void* buffer, size_t max_size)
|
||||
```
|
||||
|
||||
The `initial_size` constructor fills the buffer with default-constructed values.
|
||||
The `initial_size` and `value` constructor fills the buffer with copies of `value`.
|
||||
If `initial_size` exceeds `max_size`, the buffer is filled to its capacity. The external storage must contain at least `max_size + 1` elements.
|
||||
|
||||
## Status
|
||||
|
||||
```cpp
|
||||
@ -225,6 +241,26 @@ Returns the remaining available capacity in the `circular_buffer`.
|
||||
|
||||
## Modifiers
|
||||
|
||||
```cpp
|
||||
void assign(iterator first, const iterator& last)
|
||||
void assign(const_iterator first, const const_iterator& last)
|
||||
|
||||
template <typename TIterator>
|
||||
void assign(TIterator first, const TIterator& last)
|
||||
```
|
||||
**Description**
|
||||
Replaces the contents of the circular buffer with the elements in the range `[first, last)`. If the range exceeds the capacity, only the last `capacity()` elements are retained. The range may refer to the circular buffer being assigned.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
void assign(size_type n, const_reference value)
|
||||
```
|
||||
**Description**
|
||||
Replaces the contents of the circular buffer with `n` copies of `value`. If `n` exceeds the capacity, the buffer is filled to its capacity. `value` may refer to an element in the circular buffer being assigned.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
void set_buffer(void* buffer)
|
||||
```
|
||||
|
||||
@ -34,13 +34,20 @@ Defines data as an `deque` of `int`, of length `10`, containing the supplied dat
|
||||
## Make template
|
||||
**C++11 and above**
|
||||
```cpp
|
||||
template <typename T, typename... TValues>
|
||||
constexpr auto make_deque(TValues&&... values) -> etl::deque<T, sizeof...(TValues)>
|
||||
template <typename T = void, typename... TValues>
|
||||
constexpr auto make_deque(TValues&&... values) -> etl::deque</*element-type*/, sizeof...(TValues)>
|
||||
```
|
||||
|
||||
The element type is `T` when supplied, otherwise the decayed common type of
|
||||
the arguments (the Library Fundamentals TS `make_array` design).
|
||||
|
||||
### Example
|
||||
```cpp
|
||||
auto data = etl::make_deque<int>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
// Deduced element type: etl::deque<int, 10>.
|
||||
auto data = etl::make_deque(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
|
||||
// Explicit element type: etl::deque<char, 10>. Each argument is converted.
|
||||
auto chars = etl::make_deque<char>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
```
|
||||
|
||||
## Member types
|
||||
|
||||
@ -333,4 +333,4 @@ operator >=
|
||||
|
||||
## Technical stuff
|
||||
|
||||
The const set is implemented as a sorted array key/value pairs.
|
||||
The const set is implemented as a sorted array of values.
|
||||
|
||||
@ -333,4 +333,4 @@ operator >=
|
||||
|
||||
## Technical stuff
|
||||
|
||||
The const set is implemented as a sorted array key/value pairs.
|
||||
The const set is implemented as a sorted array of values.
|
||||
|
||||
@ -235,55 +235,60 @@ The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`)
|
||||
---
|
||||
|
||||
```cpp
|
||||
pair<iterator, bool> emplace((const_reference value))
|
||||
pair<iterator, bool> emplace(const key_type& key, const mapped_type& value)
|
||||
pair<iterator, bool> emplace(const_reference value)
|
||||
```
|
||||
**Description**
|
||||
Inserts key/value pairs into the set by constructing directly into storage.
|
||||
Inserts a value into the set by constructing directly into storage.
|
||||
The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`)
|
||||
|
||||
---
|
||||
|
||||
**C++03**
|
||||
The emplace functions differ from that of std::set in that, due to C++03 not supporting 'perfect forwarding'.
|
||||
The emplace functions differ from that of std::multiset in that, due to C++03 not supporting 'perfect forwarding'.
|
||||
|
||||
```cpp
|
||||
pair<iterator, bool> emplace()
|
||||
```
|
||||
**Description**
|
||||
Emplaces a default constructed value into the set.
|
||||
|
||||
```cpp
|
||||
template <typename T1>
|
||||
pair<iterator, bool> emplace(const key_type& key, const T1& value1)
|
||||
pair<iterator, bool> emplace(const T1& value1)
|
||||
```
|
||||
**Description**
|
||||
Emplaces a value constructed from `key` and 1 argument into the set.
|
||||
Emplaces a value constructed from 1 argument into the set.
|
||||
|
||||
```cpp
|
||||
template <typename T1, typename T2>
|
||||
pair<iterator, bool> emplace(const key_type& key, const T1& value1, const T2& value2)
|
||||
pair<iterator, bool> emplace(const T1& value1, const T2& value2)
|
||||
```
|
||||
**Description**
|
||||
Emplaces a value constructed from `key` and 2 arguments into the set.
|
||||
Emplaces a value constructed from 2 arguments into the set.
|
||||
|
||||
```cpp
|
||||
template <typename T1, typename T2, typename T3>
|
||||
pair<iterator, bool> emplace(const key_type& key, const T1& value1, const T2& value2, const T3& value3)
|
||||
pair<iterator, bool> emplace(const T1& value1, const T2& value2, const T3& value3)
|
||||
```
|
||||
**Description**
|
||||
Emplaces a value constructed from `key` and 3 arguments into the set.
|
||||
Emplaces a value constructed from 3 arguments into the set.
|
||||
|
||||
```cpp
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
pair<iterator, bool> emplace(const key_type& key, const T1& value1, const T2& value2, const T3& value3, const T4& value4)
|
||||
pair<iterator, bool> emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
|
||||
```
|
||||
**Description**
|
||||
Emplaces a value constructed from `key` and 4 arguments into the set.
|
||||
Emplaces a value constructed from 4 arguments into the set.
|
||||
|
||||
---
|
||||
|
||||
**C++11**
|
||||
```cpp
|
||||
template <typename ... Args>
|
||||
pair<iterator, bool> emplace(const key_type& key, Args&& ... args)
|
||||
pair<iterator, bool> emplace(Args&& ... args)
|
||||
```
|
||||
**Description**
|
||||
Emplaces a value constructed from the `key` and arguments into the set.
|
||||
Emplaces a value constructed from the arguments into the set.
|
||||
|
||||
---
|
||||
|
||||
@ -493,9 +498,9 @@ operator !=
|
||||
|
||||
## Technical stuff
|
||||
|
||||
Flat maps are usually implemented internally as a sorted vector of key/value pairs. Whilst this makes searching fast, it can have a detrimental effect when items are inserted into a container that stores complex, non-trivial keys or values.
|
||||
Flat sets are usually implemented internally as a sorted vector of values. Whilst this makes searching fast, it can have a detrimental effect when items are inserted into a container that stores complex, non-trivial values.
|
||||
As inserting requires that all of the items to the right of the insert position must be shifted this can become an expensive operation for larger containers.
|
||||
|
||||
To improve insertion performance ETL flat maps are implemented as vectors of pointers to key/value pairs, sorted by key value. An insertion will involve a copy of a range of pointers; an operation that can be very fast.
|
||||
To improve insertion performance ETL flat sets are implemented as vectors of pointers to values, sorted by value. An insertion will involve a copy of a range of pointers; an operation that can be very fast.
|
||||
|
||||
The downside is that access to an item via an iterator will involve one indirection and the overhead of the container will be one pointer per item. A normal flat set implementation does not have this overhead.
|
||||
|
||||
@ -235,11 +235,10 @@ The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`)
|
||||
---
|
||||
|
||||
```cpp
|
||||
pair<iterator, bool> emplace((const_reference value))
|
||||
pair<iterator, bool> emplace(const key_type& key, const mapped_type& value)
|
||||
pair<iterator, bool> emplace(const_reference value)
|
||||
```
|
||||
**Description**
|
||||
Inserts key/value pairs into the set by constructing directly into storage.
|
||||
Inserts a value into the set by constructing directly into storage.
|
||||
The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`)
|
||||
|
||||
---
|
||||
@ -248,39 +247,48 @@ The return type is either `std::pair` (default) or `etl::pair` (`ETL_NO_STL`)
|
||||
The emplace functions differ from that of `std::set` due to C++03 not supporting 'perfect forwarding'.
|
||||
|
||||
```cpp
|
||||
template <typename T1>
|
||||
pair<iterator, bool> emplace(const key_type& key, const T1& value1)
|
||||
pair<iterator, bool> emplace()
|
||||
```
|
||||
**Description**
|
||||
|
||||
Emplaces a value constructed from `key` and 1 argument into the set.
|
||||
Emplaces a default constructed value into the set.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename T1>
|
||||
pair<iterator, bool> emplace(const T1& value1)
|
||||
```
|
||||
**Description**
|
||||
|
||||
Emplaces a value constructed from 1 argument into the set.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename T1, typename T2>
|
||||
pair<iterator, bool> emplace(const key_type& key, const T1& value1, const T2& value2)
|
||||
pair<iterator, bool> emplace(const T1& value1, const T2& value2)
|
||||
```
|
||||
**Description**
|
||||
Emplaces a value constructed from `key` and 2 arguments into the set.
|
||||
Emplaces a value constructed from 2 arguments into the set.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename T1, typename T2, typename T3>
|
||||
pair<iterator, bool> emplace(const key_type& key, const T1& value1, const T2& value2, const T3& value3)
|
||||
pair<iterator, bool> emplace(const T1& value1, const T2& value2, const T3& value3)
|
||||
```
|
||||
**Description**
|
||||
Emplaces a value constructed from `key` and 3 arguments into the set.
|
||||
Emplaces a value constructed from 3 arguments into the set.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
pair<iterator, bool> emplace(const key_type& key, const T1& value1, const T2& value2, const T3& value3, const T4& value4)
|
||||
pair<iterator, bool> emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
|
||||
```
|
||||
**Description**
|
||||
Emplaces a value constructed from `key` and 4 arguments into the set.
|
||||
Emplaces a value constructed from 4 arguments into the set.
|
||||
|
||||
---
|
||||
|
||||
@ -288,10 +296,10 @@ Emplaces a value constructed from `key` and 4 arguments into the set.
|
||||
|
||||
```cpp
|
||||
template <typename ... Args>
|
||||
pair<iterator, bool> emplace(const key_type& key, Args&& ... args)
|
||||
pair<iterator, bool> emplace(Args&& ... args)
|
||||
```
|
||||
**Description**
|
||||
Emplaces a value constructed from the `key` and arguments into the set.
|
||||
Emplaces a value constructed from the arguments into the set.
|
||||
|
||||
---
|
||||
|
||||
@ -509,9 +517,9 @@ operator !=
|
||||
|
||||
## Technical stuff
|
||||
|
||||
Flat maps are usually implemented internally as a sorted vector of key/value pairs. Whilst this makes searching fast, it can have a detrimental effect when items are inserted into a container that stores complex, non-trivial keys or values.
|
||||
Flat sets are usually implemented internally as a sorted vector of values. Whilst this makes searching fast, it can have a detrimental effect when items are inserted into a container that stores complex, non-trivial values.
|
||||
As inserting requires that all of the items to the right of the insert position must be shifted this can become an expensive operation for larger containers.
|
||||
|
||||
To improve insertion performance ETL flat maps are implemented as vectors of pointers to key/value pairs, sorted by key value. An insertion will involve a copy of a range of pointers; an operation that can be very fast.
|
||||
To improve insertion performance ETL flat sets are implemented as vectors of pointers to values, sorted by value. An insertion will involve a copy of a range of pointers; an operation that can be very fast.
|
||||
|
||||
The downside is that access to an item via an iterator will involve one indirection and the overhead of the container will be one pointer per item. A normal flat set implementation does not have this overhead.
|
||||
|
||||
@ -42,6 +42,26 @@ etl::indirect_vector data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
```
|
||||
Defines data as an `indirect_vector` of `int`, of length `10`, containing the supplied data.
|
||||
|
||||
## Make template
|
||||
**C++11 and above**
|
||||
```cpp
|
||||
template <typename T = void, typename... TValues>
|
||||
constexpr auto make_indirect_vector(TValues&&... values)
|
||||
-> etl::indirect_vector</*element-type*/, sizeof...(TValues)>
|
||||
```
|
||||
|
||||
The element type is `T` when supplied, otherwise the decayed common type of
|
||||
the arguments (the Library Fundamentals TS `make_array` design).
|
||||
|
||||
### Example
|
||||
```cpp
|
||||
// Deduced element type: etl::indirect_vector<int, 10>.
|
||||
auto data = etl::make_indirect_vector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
|
||||
// Explicit element type: etl::indirect_vector<char, 10>. Each argument is converted.
|
||||
auto chars = etl::make_indirect_vector<char>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
```
|
||||
|
||||
## Member types
|
||||
|
||||
```cpp
|
||||
|
||||
@ -54,6 +54,25 @@ etl::vector data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
|
||||
Defines data as an vector of int, of length 10, containing the supplied data.
|
||||
|
||||
## Make template
|
||||
**C++11 and above**
|
||||
```cpp
|
||||
template <typename T = void, typename... TValues>
|
||||
constexpr auto make_vector(TValues&&... values) -> etl::vector</*element-type*/, sizeof...(TValues)>
|
||||
```
|
||||
|
||||
The element type is `T` when supplied, otherwise the decayed common type of
|
||||
the arguments (the Library Fundamentals TS `make_array` design).
|
||||
|
||||
### Example
|
||||
```cpp
|
||||
// Deduced element type: etl::vector<int, 10>.
|
||||
auto data = etl::make_vector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
|
||||
// Explicit element type: etl::vector<char, 10>. Each argument is converted.
|
||||
auto chars = etl::make_vector<char>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
```
|
||||
|
||||
## Member types
|
||||
|
||||
```cpp
|
||||
|
||||
@ -133,6 +133,8 @@ ETL_CONSTEXPR17 typename std::iterator_traits<TIterator>::difference_type
|
||||
distance(TIterator first, TIterator last)
|
||||
```
|
||||
|
||||
See [Ranges](../../ranges/ranges) for the `etl::ranges` range access primitives, including `etl::ranges::distance`.
|
||||
|
||||
## iterator
|
||||
A base class provided to simplify definitions of the required types for iterators.
|
||||
https://en.cppreference.com/w/cpp/iterator/iterator
|
||||
|
||||
@ -119,6 +119,63 @@ Output:
|
||||
|
||||
This first filters the even numbers and then squares them. Each `|` passes the result of the previous stage as input to the next view adaptor.
|
||||
|
||||
## Range Access and Primitives
|
||||
|
||||
These are declared in the `etl::ranges` namespace in `iterator.h`, which is included by `ranges.h`.
|
||||
|
||||
### Range access
|
||||
|
||||
Function objects, equivalent to their `std::ranges` counterparts.
|
||||
|
||||
| Name | Description |
|
||||
|---|---|
|
||||
| `begin`, `end` | The iterator to the first element, and the sentinel. |
|
||||
| `cbegin`, `cend` | The const iterator to the first element, and the const sentinel. |
|
||||
| `rbegin`, `rend` | The reverse iterator to the last element in forward order, and the past-the-end reverse iterator. |
|
||||
| `crbegin`, `crend` | The const reverse iterator to the last element in forward order, and the const past-the-end reverse iterator. |
|
||||
| `size` | The number of elements, as a `size_t`. |
|
||||
| `ssize` | The number of elements, as a `ptrdiff_t`. |
|
||||
| `empty` | Whether the range has no elements. |
|
||||
| `data`, `cdata` | A pointer to the first element. |
|
||||
| `distance` | The number of elements between two iterators, or in a range. |
|
||||
| `advance` | Advances an iterator by a given distance and/or to a bound. |
|
||||
| `next`, `prev` | An iterator advanced forwards or backwards by a given distance and/or to a bound. |
|
||||
|
||||
`size` and `ssize` use the range's `size()` member if it has one; otherwise they count the elements by traversing the range, which requires at least a forward range.
|
||||
|
||||
#### distance
|
||||
|
||||
```cpp
|
||||
// Iterator and sentinel of the same type.
|
||||
template <typename I>
|
||||
constexpr etl::iter_difference_t<I> distance(I first, I last)
|
||||
|
||||
// Iterator and sentinel of different types.
|
||||
template <typename I, typename S>
|
||||
constexpr etl::iter_difference_t<I> distance(I first, S last)
|
||||
|
||||
// Range.
|
||||
template <typename R>
|
||||
constexpr etl::iter_difference_t<etl::ranges::iterator_t<R>> distance(R&& r)
|
||||
```
|
||||
|
||||
The range overload uses the range's `size()` member if it has one; otherwise it counts the elements by traversing from `begin()` to `end()`.
|
||||
|
||||
### Range primitives
|
||||
|
||||
Alias templates that give the associated types of a range.
|
||||
|
||||
| Name | Description |
|
||||
|---|---|
|
||||
| `iterator_t<R>` | The iterator type. |
|
||||
| `const_iterator_t<R>` | The const iterator type. |
|
||||
| `sentinel_t<R>` | The sentinel type. |
|
||||
| `const_sentinel_t<R>` | The const sentinel type. |
|
||||
| `range_size_t<R>` | The size type. |
|
||||
| `range_difference_t<R>` | The difference type. |
|
||||
| `range_value_t<R>` | The element value type. |
|
||||
| `range_reference_t<R>` | The element reference type. |
|
||||
|
||||
## Supported Views
|
||||
|
||||
All views are in the `etl::ranges` namespace. Corresponding range adaptor objects are available in `etl::ranges::views`.
|
||||
|
||||
@ -327,7 +327,7 @@ Inequality test for etl::to_arithmetic_result
|
||||
```cpp
|
||||
template <typename T, typename U>
|
||||
ETL_CONSTEXPR14 bool operator !=(const T& lhs,
|
||||
const etl::to_arithmetic_result<T>& rhs)
|
||||
const etl::to_arithmetic_result<U>& rhs)
|
||||
```
|
||||
Inequality test for etl::to_arithmetic_result
|
||||
|
||||
|
||||
@ -32,6 +32,28 @@ Not all traits have been defined as some rely on compiler intrinsics that are no
|
||||
`is_compound`
|
||||
`is_array`
|
||||
`is_pointer`
|
||||
`is_null_pointer`
|
||||
`is_scalar`
|
||||
`is_union`
|
||||
`is_empty`
|
||||
`is_polymorphic`
|
||||
`is_abstract`
|
||||
`is_final`
|
||||
`is_aggregate`
|
||||
`is_trivial`
|
||||
`is_standard_layout`
|
||||
`is_layout_compatible`
|
||||
`is_pointer_interconvertible_base_of`
|
||||
`is_destructible`
|
||||
`is_nothrow_destructible`
|
||||
`has_virtual_destructor`
|
||||
`has_unique_object_representations`
|
||||
`is_bounded_array`
|
||||
`is_unbounded_array`
|
||||
`is_swappable`
|
||||
`is_swappable_with`
|
||||
`is_nothrow_swappable`
|
||||
`is_nothrow_swappable_with`
|
||||
`is_reference`
|
||||
`is_base_of`
|
||||
`make_signed`
|
||||
@ -52,6 +74,7 @@ Not all traits have been defined as some rely on compiler intrinsics that are no
|
||||
`declvar` `20.28.0`
|
||||
`common_type`
|
||||
`is_enum` `20.30.0`
|
||||
`is_scoped_enum` `20.50.0`
|
||||
`underlying_type` `20.42.0`
|
||||
 Unless the ETL is set to use builtins, the user must specialise the template for their enumerations.
|
||||
|
||||
@ -67,8 +90,12 @@ The following will be defined according to the C++ standard and user defined mac
|
||||
`is_move_constructible`
|
||||
`is_trivially_constructible`
|
||||
`is_trivially_copy_constructible`
|
||||
`is_trivially_default_constructible`
|
||||
`is_trivially_move_constructible`
|
||||
`is_trivially_destructible`
|
||||
`is_trivially_assignable`
|
||||
`is_trivially_copy_assignable`
|
||||
`is_trivially_move_assignable`
|
||||
`is_trivially_copyable`
|
||||
|
||||
## Scenario 1
|
||||
@ -476,3 +503,499 @@ template <typename T>
|
||||
inline constexpr bool is_object_pointer_v = etl::is_object_pointer<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_pod
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_pod
|
||||
```
|
||||
Checks if `T` is a POD (Plain Old Data) type.
|
||||
The result is found in the member `value`.
|
||||
 When using the STL, this is defined as `is_standard_layout<T> && is_trivially_default_constructible<T> && is_trivially_copyable<T>`.
|
||||
 When not using the STL, this is conservatively defined as `is_fundamental<T> || is_pointer<T>`.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_pod_v = etl::is_pod<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_standard_layout
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_standard_layout
|
||||
```
|
||||
Checks if `T` is a standard-layout type.
|
||||
The result is found in the member `value`.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_standard_layout_v = etl::is_standard_layout<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_trivial
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_trivial
|
||||
```
|
||||
Checks if `T` is a trivial type; i.e. it is trivially copyable and has one or more
|
||||
default constructors, all of which are trivial.
|
||||
The result is found in the member `value`.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_trivial_v = etl::is_trivial<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
**Note:** When not using the STL, this trait requires compiler support (the `__is_trivial` intrinsic).
|
||||
If that is not available then the trait is not defined, as there is no portable way of
|
||||
determining whether a type is trivial.
|
||||
|
||||
## is_bounded_array
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_bounded_array
|
||||
```
|
||||
Checks if `T` is an array type of known bound.
|
||||
`T[N]` returns `true`, `T[]` and all other types return `false`.
|
||||
The result is found in the member `value`.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_bounded_array_v = etl::is_bounded_array<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_unbounded_array
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_unbounded_array
|
||||
```
|
||||
Checks if `T` is an array type of unknown bound.
|
||||
`T[]` returns `true`, `T[N]` and all other types return `false`.
|
||||
The result is found in the member `value`.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_unbounded_array_v = etl::is_unbounded_array<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_destructible
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_destructible
|
||||
```
|
||||
Checks if `T` is a destructible type; that is, an object type whose destructor is not deleted and is accessible, a reference type, or an array of a destructible type.
|
||||
Incomplete types, `void`, function types and arrays of unknown bound are not destructible.
|
||||
The result is found in the member `value`.
|
||||
 When not using the STL, the trait is detected by checking whether `declval<T&>().~T()` is a valid expression.
|
||||
 Requires either compiler support or C++11. When neither is available, this trait is not defined.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_destructible_v = etl::is_destructible<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_nothrow_destructible
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_nothrow_destructible
|
||||
```
|
||||
Checks if `T` is a destructible type whose destructor is known not to throw.
|
||||
Types that are not destructible are not nothrow destructible.
|
||||
The result is found in the member `value`.
|
||||
 When not using the STL, the trait is detected by checking `noexcept(declval<T&>().~T())` for destructible types.
|
||||
 Requires either compiler support or C++11. When neither is available, this trait is not defined.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_nothrow_destructible_v = etl::is_nothrow_destructible<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_swappable
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_swappable
|
||||
```
|
||||
Checks if `T` is a referenceable type and lvalues of type `T` can be swapped by an unqualified call to `swap`.
|
||||
The result is found in the member `value`.
|
||||
 When using the STL and C++17, this is defined as `std::is_swappable<T>`.
|
||||
 Otherwise the trait checks whether `swap(declval<T&>(), declval<T&>())` is a valid expression, where the `swap` considered is `etl::swap`, `std::swap` if it is available, and any `swap` found by argument dependent lookup.
|
||||
 Requires C++11. Without it there is no way of detecting the validity of an expression, so this trait is not defined.
|
||||
 Note that when using the STL with C++11 or C++14, the accuracy of this trait depends on `std::swap` being constrained by the standard library implementation. Standard libraries that only constrain `std::swap` from C++17 will cause this trait to report `true` for types that cannot actually be swapped.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_swappable_v = etl::is_swappable<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_swappable_with
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T, typename U>
|
||||
struct is_swappable_with
|
||||
```
|
||||
Checks if expressions of type `T` and `U` can be swapped by unqualified calls to `swap`, in both directions.
|
||||
The result is found in the member `value`.
|
||||
 When using the STL and C++17, this is defined as `std::is_swappable_with<T, U>`.
|
||||
 Otherwise the trait checks whether both `swap(declval<T>(), declval<U>())` and `swap(declval<U>(), declval<T>())` are valid expressions, where the `swap` considered is `etl::swap`, `std::swap` if it is available, and any `swap` found by argument dependent lookup.
|
||||
 Note that, unlike `is_swappable`, no references are added to `T` and `U`, so the value categories of the arguments are those of `T` and `U`. `is_swappable_with<int, int>::value` is `false`, whereas `is_swappable_with<int&, int&>::value` is `true`.
|
||||
 Requires C++11. Without it there is no way of detecting the validity of an expression, so this trait is not defined.
|
||||
 Note that when using the STL with C++11 or C++14, the accuracy of this trait depends on `std::swap` being constrained by the standard library implementation. Standard libraries that only constrain `std::swap` from C++17 will cause this trait to report `true` for types that cannot actually be swapped.
|
||||
|
||||
```cpp
|
||||
template <typename T, typename U>
|
||||
inline constexpr bool is_swappable_with_v = etl::is_swappable_with<T, U>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_nothrow_swappable
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_nothrow_swappable
|
||||
```
|
||||
Checks if `T` is a referenceable type and lvalues of type `T` can be swapped by an unqualified call to `swap`, and that the swap cannot throw.
|
||||
The result is found in the member `value`.
|
||||
 When using the STL and C++17, this is defined as `std::is_nothrow_swappable<T>`.
|
||||
 Otherwise the trait checks that `etl::is_swappable<T>::value` is `true` and that `swap(declval<T&>(), declval<T&>())` is `noexcept`.
|
||||
 Requires C++11. Without it there is no way of detecting the validity of an expression, so this trait is not defined.
|
||||
 Note that when neither the STL nor the type traits builtins are available, `etl::is_nothrow_move_constructible` and `etl::is_nothrow_move_assignable` are conservatively `false` for class types, so `etl::swap` is not `noexcept` for them and this trait is conservatively `false` too.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_nothrow_swappable_v = etl::is_nothrow_swappable<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_nothrow_swappable_with
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T, typename U>
|
||||
struct is_nothrow_swappable_with
|
||||
```
|
||||
Checks if expressions of type `T` and `U` can be swapped by unqualified calls to `swap`, in both directions, and that neither swap can throw.
|
||||
The result is found in the member `value`.
|
||||
 When using the STL and C++17, this is defined as `std::is_nothrow_swappable_with<T, U>`.
|
||||
 Otherwise the trait checks that `etl::is_swappable_with<T, U>::value` is `true` and that both `swap(declval<T>(), declval<U>())` and `swap(declval<U>(), declval<T>())` are `noexcept`.
|
||||
 Note that, as for `is_swappable_with`, no references are added to `T` and `U`, so the value categories of the arguments are those of `T` and `U`. `is_nothrow_swappable_with<int, int>::value` is `false`, whereas `is_nothrow_swappable_with<int&, int&>::value` is `true`.
|
||||
 Requires C++11. Without it there is no way of detecting the validity of an expression, so this trait is not defined.
|
||||
 Note that when neither the STL nor the type traits builtins are available, `etl::is_nothrow_move_constructible` and `etl::is_nothrow_move_assignable` are conservatively `false` for class types, so `etl::swap` is not `noexcept` for them and this trait is conservatively `false` too.
|
||||
|
||||
```cpp
|
||||
template <typename T, typename U>
|
||||
inline constexpr bool is_nothrow_swappable_with_v = etl::is_nothrow_swappable_with<T, U>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_union
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_union
|
||||
```
|
||||
Checks if `T` is a union type.
|
||||
The result is found in the member `value`.
|
||||
 When the compiler does not provide the required intrinsic, this trait conservatively reports `false` for every type.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_union_v = etl::is_union<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_empty
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_empty
|
||||
```
|
||||
Checks if `T` is an empty class type; that is, a non-union class type with no non-static data members other than zero-sized bit-fields, no virtual functions, no virtual base classes and no non-empty base classes.
|
||||
The result is found in the member `value`.
|
||||
 Requires compiler support. When the compiler does not provide the required intrinsic, this trait is not defined.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_empty_v = etl::is_empty<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_polymorphic
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_polymorphic
|
||||
```
|
||||
Checks if `T` is a polymorphic class type; that is, a class that declares or inherits at least one virtual function.
|
||||
The result is found in the member `value`.
|
||||
 Requires compiler support. When the compiler does not provide the required intrinsic, this trait is not defined.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_polymorphic_v = etl::is_polymorphic<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_abstract
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_abstract
|
||||
```
|
||||
Checks if `T` is an abstract class type; that is, a class that declares or inherits at least one pure virtual function.
|
||||
The result is found in the member `value`.
|
||||
 Requires compiler support. When the compiler does not provide the required intrinsic, this trait is not defined.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_abstract_v = etl::is_abstract<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_final
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_final
|
||||
```
|
||||
Checks if `T` is a class or union type marked `final`, optionally cv-qualified.
|
||||
The result is found in the member `value`.
|
||||
 When using the STL, this requires C++14 or above. Otherwise it requires compiler support. When neither is available, this trait is not defined.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_final_v = etl::is_final<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_aggregate
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_aggregate
|
||||
```
|
||||
Checks if `T` is an aggregate type, optionally cv-qualified.
|
||||
An aggregate is an array type or a class type that has no user-declared or inherited constructors, no private or protected non-static data members, no virtual functions and no virtual, private or protected base classes.
|
||||
The result is found in the member `value`.
|
||||
 When using the STL, this requires C++17 or above. Otherwise it requires compiler support. When neither is available, this trait is not defined.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_aggregate_v = etl::is_aggregate<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## has_virtual_destructor
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct has_virtual_destructor
|
||||
```
|
||||
Checks if `T` is a class type with a virtual destructor, optionally cv-qualified.
|
||||
The result is found in the member `value`.
|
||||
 When not using the STL, this requires compiler support. When it is not available, this trait is not defined.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool has_virtual_destructor_v = etl::has_virtual_destructor<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## has_unique_object_representations
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct has_unique_object_representations
|
||||
```
|
||||
Checks if `T` is trivially copyable and any two objects of type `T` with the same value have the same object representation; that is, the type has no padding bits and no two distinct object representations compare equal.
|
||||
Arrays and cv-qualifiers are ignored; the trait is applied to `etl::remove_all_extents<typename etl::remove_cv<T>::type>::type`.
|
||||
The result is found in the member `value`.
|
||||
 When using the STL, this requires C++17 or above. Otherwise it requires compiler support. When neither is available, this trait is not defined.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool has_unique_object_representations_v = etl::has_unique_object_representations<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_null_pointer
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_null_pointer
|
||||
```
|
||||
Checks if `T` is `etl::nullptr_t`, optionally cv-qualified.
|
||||
The result is found in the member `value`.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_null_pointer_v = etl::is_null_pointer<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_scalar
|
||||
From: `20.49.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_scalar
|
||||
```
|
||||
Checks if `T` is a scalar type; that is, an arithmetic, enumeration, pointer, pointer to member or `etl::nullptr_t` type, optionally cv-qualified.
|
||||
The result is found in the member `value`.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_scalar_v = etl::is_scalar<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_scoped_enum
|
||||
From: `20.50.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_scoped_enum
|
||||
```
|
||||
Checks if `T` is a scoped enumeration type; that is, an enumeration type that is not implicitly convertible to an integer.
|
||||
The result is found in the member `value`.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_scoped_enum_v = etl::is_scoped_enum<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_trivially_default_constructible
|
||||
From: `20.50.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_trivially_default_constructible
|
||||
```
|
||||
Checks if `T` is default constructible and the default construction is trivial.
|
||||
The result is found in the member `value`.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_trivially_default_constructible_v = etl::is_trivially_default_constructible<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_trivially_move_constructible
|
||||
From: `20.50.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_trivially_move_constructible
|
||||
```
|
||||
Checks if `T` is move constructible and the move construction is trivial.
|
||||
The result is found in the member `value`.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_trivially_move_constructible_v = etl::is_trivially_move_constructible<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_trivially_move_assignable
|
||||
From: `20.50.0`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_trivially_move_assignable
|
||||
```
|
||||
Checks if `T` is move assignable and the move assignment is trivial.
|
||||
The result is found in the member `value`.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
inline constexpr bool is_trivially_move_assignable_v = etl::is_trivially_move_assignable<T>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_trivially_assignable
|
||||
|
||||
```cpp
|
||||
template <typename T1, typename T2>
|
||||
struct is_trivially_assignable
|
||||
```
|
||||
Checks if an expression of type `T2` can be assigned to an lvalue expression of type `T1`, and that the assignment is trivial.
|
||||
The result is found in the member `value`.
|
||||
 See Scenarios 1 to 4 above for how this trait is defined when the STL or the compiler built-ins are unavailable.
|
||||
|
||||
```cpp
|
||||
template <typename T1, typename T2>
|
||||
inline constexpr bool is_trivially_assignable_v = etl::is_trivially_assignable<T1, T2>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_layout_compatible
|
||||
From: `20.50.0`
|
||||
|
||||
```cpp
|
||||
template <typename T, typename U>
|
||||
struct is_layout_compatible
|
||||
```
|
||||
Checks if `T` and `U` are layout-compatible types.
|
||||
The result is found in the member `value`.
|
||||
 When using the STL with C++20 or above, this is defined as `std::is_layout_compatible<T, U>`.
|
||||
 Otherwise it requires compiler support (the `__is_layout_compatible` intrinsic). When neither is available, this trait is not defined, as there is no portable way of determining layout compatibility.
|
||||
|
||||
```cpp
|
||||
template <typename T, typename U>
|
||||
inline constexpr bool is_layout_compatible_v = etl::is_layout_compatible<T, U>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
## is_pointer_interconvertible_base_of
|
||||
From: `20.50.0`
|
||||
|
||||
```cpp
|
||||
template <typename TBase, typename TDerived>
|
||||
struct is_pointer_interconvertible_base_of
|
||||
```
|
||||
Checks if `TBase` is a pointer-interconvertible base class of `TDerived`; that is, every object of type `TDerived` has its `TBase` base class subobject at the same address as the complete object.
|
||||
The result is found in the member `value`.
|
||||
 When using the STL with C++20 or above, this is defined as `std::is_pointer_interconvertible_base_of<TBase, TDerived>`.
|
||||
 Otherwise it requires compiler support (the `__is_pointer_interconvertible_base_of` intrinsic). When neither is available, this trait is not defined, as there is no portable way of determining pointer interconvertibility.
|
||||
 Note that, as required by the standard, the program is ill-formed if `TDerived` is a complete non-union class type and `TBase` is an incomplete class type. The trait cannot be used to probe possibly-incomplete types.
|
||||
|
||||
```cpp
|
||||
template <typename TBase, typename TDerived>
|
||||
inline constexpr bool is_pointer_interconvertible_base_of_v = etl::is_pointer_interconvertible_base_of<TBase, TDerived>::value;
|
||||
```
|
||||
C++17
|
||||
|
||||
@ -192,13 +192,13 @@ Swap with another etl::unexpected
|
||||
```cpp
|
||||
template <typename TValue, typename TError>
|
||||
class expected
|
||||
```cpp
|
||||
```
|
||||
|
||||
Specialisation for void value type.
|
||||
```cpp
|
||||
template <typename TError>
|
||||
class expected<void, TError>
|
||||
```cpp
|
||||
```
|
||||
|
||||
### Types
|
||||
|
||||
@ -421,6 +421,7 @@ value_type& value() const
|
||||
Get the value.
|
||||
Undefined if has_value() returns false.
|
||||
Not valid for void specialisation.
|
||||
Before: C++11
|
||||
|
||||
---
|
||||
|
||||
@ -536,13 +537,46 @@ Before: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename G>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
error_type error_or(G&& default_error) const&
|
||||
```
|
||||
**Description**
|
||||
Returns default_error if has_value() returns true; otherwise returns the stored error.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename G>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
error_type error_or(G&& default_error)&&
|
||||
```
|
||||
**Description**
|
||||
Returns default_error if has_value() returns true; otherwise returns the stored error.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename G>
|
||||
error_type error_or(const G& default_error) const
|
||||
```
|
||||
**Description**
|
||||
Returns default_error if has_value() returns true; otherwise returns the stored error.
|
||||
Before: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename... TArgs>
|
||||
ETL_CONSTEXPR14 value_type& emplace(TArgs&&... args) ETL_NOEXCEPT
|
||||
```
|
||||
**Description**
|
||||
Returns the error if has_value() returns false.
|
||||
Undefined if has_value() returns true.
|
||||
Create from arguments.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
@ -574,15 +608,411 @@ Const class member access operator.
|
||||
---
|
||||
|
||||
```cpp
|
||||
value_type& operator *()
|
||||
value_type& operator *() &
|
||||
```
|
||||
**Description**
|
||||
**Description**
|
||||
Dereference operator.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
const value_type& operator *() const
|
||||
const value_type& operator *() const&
|
||||
```
|
||||
**Description**
|
||||
**Description**
|
||||
Dereference operator.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
value_type&& operator *() &&
|
||||
```
|
||||
**Description**
|
||||
Dereference operator.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
const value_type&& operator *() const&&
|
||||
```
|
||||
**Description**
|
||||
Dereference operator.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
value_type* begin() ETL_NOEXCEPT
|
||||
```
|
||||
**Description**
|
||||
Returns a pointer to the value if has_value() returns true, otherwise returns nullptr.
|
||||
Allows expected to be used as a range of 0 or 1 elements. Not valid for void specialisation.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
const value_type* begin() const ETL_NOEXCEPT
|
||||
```
|
||||
**Description**
|
||||
Returns a pointer to the value if has_value() returns true, otherwise returns nullptr. Not valid for void specialisation.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
value_type* end() ETL_NOEXCEPT
|
||||
```
|
||||
**Description**
|
||||
Returns a pointer past the value if has_value() returns true, otherwise returns nullptr. Not valid for void specialisation.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
const value_type* end() const ETL_NOEXCEPT
|
||||
```
|
||||
**Description**
|
||||
Returns a pointer past the value if has_value() returns true, otherwise returns nullptr. Not valid for void specialisation.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TValue&>::type>::type>
|
||||
auto transform(F&& f) & -> expected<U, TError>
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it invokes f on the value and returns the result wrapped in an expected object; otherwise it returns an expected object that contains error(). For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
|
||||
auto transform(F&& f) & -> expected<U, TError>
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it invokes f and returns the result wrapped in an expected object; otherwise it returns an expected object that contains error().
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TValue&>::type>::type>
|
||||
auto transform(F&& f) const& -> expected<U, TError>
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it invokes f on the value and returns the result wrapped in an expected object; otherwise it returns an expected object that contains error(). For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
|
||||
auto transform(F&& f) const& -> expected<U, TError>
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it invokes f and returns the result wrapped in an expected object; otherwise it returns an expected object that contains error().
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TValue&&>::type>::type>
|
||||
auto transform(F&& f) && -> expected<U, TError>
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it invokes f on the value and returns the result wrapped in an expected object; otherwise it returns an expected object that contains error(). For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
|
||||
auto transform(F&& f) && -> expected<U, TError>
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it invokes f and returns the result wrapped in an expected object; otherwise it returns an expected object that contains error().
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TValue&&>::type>::type>
|
||||
auto transform(F&& f) const&& -> expected<U, TError>
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it invokes f and returns the result wrapped in an expected object; otherwise it returns an expected object that contains error(). For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
|
||||
auto transform(F&& f) const&& -> expected<U, TError>
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it invokes f and returns the result wrapped in an expected object; otherwise it returns an expected object that contains error().
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TValue&>::type>::type>
|
||||
auto and_then(F&& f) & -> U
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it invokes f on the value and returns the result; otherwise it returns an expected object that contains error(). For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>
|
||||
auto and_then(F&& f) & -> U
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it invokes f and returns the result; otherwise it returns an expected object that contains error().
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TValue&>::type>::type>
|
||||
auto and_then(F&& f) const& -> U
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it invokes f on the value and returns the result; otherwise it returns an expected object that contains error(). For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
|
||||
auto and_then(F&& f) const& -> U
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it invokes f and returns the result; otherwise it returns an expected object that contains error().
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TValue&&>::type>::type>
|
||||
auto and_then(F&& f) && -> U
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it invokes f on the value and returns the result; otherwise it returns an expected object that contains error(). For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
|
||||
auto and_then(F&& f) && -> U
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it invokes f and returns the result; otherwise it returns an expected object that contains error().
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TValue&&>::type>::type>
|
||||
auto and_then(F&& f) const&& -> U
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it invokes f on the value and returns the result; otherwise it returns an expected object that contains error(). For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template < typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void>::type>::type>
|
||||
auto and_then(F&& f) const&& -> U
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it invokes f and returns the result; otherwise it returns an expected object that contains error().
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&>::type>::type>
|
||||
auto or_else(F&& f) & -> U
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it returns an expected object that contains value(); otherwise it invokes f on error() and returns the result. For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&>::type>::type>
|
||||
auto or_else(F&& f) & -> U
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it returns a default constructed expected object of the appropriate type; otherwise it invokes f on error() and returns the result.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&>::type>::type>
|
||||
auto or_else(F&& f) const& -> U
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it returns an expected object that contains value(); otherwise it invokes f on error() and returns the result. For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&>::type>::type>
|
||||
auto or_else(F&& f) const& -> U
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it returns a default constructed expected object of the appropriate type; otherwise it invokes f on error() and returns the result.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&&>::type>::type>
|
||||
auto or_else(F&& f) && -> U
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it returns an expected object that contains value(); otherwise it invokes f on error() and returns the result. For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&&>::type>::type>
|
||||
auto or_else(F&& f) && -> U
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it returns a default constructed expected object of the appropriate type; otherwise it invokes f on error() and returns the result.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&&>::type>::type>
|
||||
auto or_else(F&& f) const&& -> U
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it returns an expected object that contains value(); otherwise it invokes f on error() and returns the result. For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&&>::type>::type>
|
||||
auto or_else(F&& f) const&& -> U
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it returns a default constructed expected object of the appropriate type; otherwise it invokes f on error() and returns the result.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&>::type>::type>
|
||||
auto transform_error(F&& f) & -> expected<TValue, U>
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it returns an expected that contains value(); otherwise it invokes f on error() and returns the result wrapped in an expected object. For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&>::type>::type>
|
||||
auto transform_error(F&& f) & -> expected<TValue, U>
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it returns a default constructed expected object of the appropriate type; otherwise it invokes f on error() and returns the result wrapped in an expected object.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&>::type>::type>
|
||||
auto transform_error(F&& f) const& -> expected<TValue, U>
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it returns an expected that contains value(); otherwise it invokes f on error() and returns the result wrapped in an expected object. For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&>::type>::type>
|
||||
auto transform_error(F&& f) const& -> expected<TValue, U>
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it returns a default constructed expected object of the appropriate type; otherwise it invokes f on error() and returns the result wrapped in an expected object.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&&>::type>::type>
|
||||
auto transform_error(F&& f) && -> expected<TValue, U>
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it returns an expected that contains value(); otherwise it invokes f on error() and returns the result wrapped in an expected object. For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, TError&&>::type>::type>
|
||||
auto transform_error(F&& f) && -> expected<TValue, U>
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it returns a default constructed expected object of the appropriate type; otherwise it invokes f on error() and returns the result wrapped in an expected object.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&&>::type>::type>
|
||||
auto transform_error(F&& f) const&& -> expected<TValue, U>
|
||||
```
|
||||
**Description**
|
||||
If has_value() returns true, it returns an expected that contains value(); otherwise it invokes f on error() and returns the result wrapped in an expected object. For void specialisation see below.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F, typename U = typename etl::remove_cvref< typename etl::invoke_result<F, void, const TError&&>::type>::type>
|
||||
auto transform_error(F&& f) const&& -> expected<TValue, U>
|
||||
```
|
||||
**Description**
|
||||
For void specialisation.
|
||||
If has_value() returns true, it returns a default constructed expected object of the appropriate type; otherwise it invokes f on error() and returns the result wrapped in an expected object.
|
||||
Since: C++11
|
||||
|
||||
|
||||
@ -222,6 +222,64 @@ bool has_value() const
|
||||
Checks whether *this is in a valid state, i.e. whether the contained value is initialised.
|
||||
Returns `true` if valid, otherwise `false`.
|
||||
|
||||
## Monadic operations
|
||||
C++11 and above.
|
||||
|
||||
Each operation is supplied as four reference qualified overloads (`&`, `const&`, `&&`, `const&&`),
|
||||
so that the contained value is passed to the supplied callable with the value category of `*this`.
|
||||
|
||||
```cpp
|
||||
template <typename F>
|
||||
etl::optional<U> transform(F&& f)
|
||||
```
|
||||
**Description**
|
||||
If `*this` contains a value, returns an `etl::optional<U>` containing the result of invoking `f`
|
||||
with the contained value, otherwise returns an empty `etl::optional<U>`.
|
||||
|
||||
`U` is the result type of `f`, with any reference and cv qualification removed.
|
||||
|
||||
### Note
|
||||
Unlike `std::optional::transform`, which only removes cv qualification, a callable returning a
|
||||
reference is accepted, and the referenced value is copied into the resulting optional.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F>
|
||||
U and_then(F&& f)
|
||||
```
|
||||
**Description**
|
||||
If `*this` contains a value, returns the result of invoking `f` with the contained value,
|
||||
otherwise returns an empty `U`.
|
||||
|
||||
`U` is the result type of `f`, with any reference and cv qualification removed, and must be an
|
||||
`etl::optional`. The overload takes no part in overload resolution otherwise.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename F>
|
||||
U or_else(F&& f)
|
||||
```
|
||||
**Description**
|
||||
If `*this` contains a value, returns a copy of `*this`, otherwise returns the result of invoking
|
||||
`f` with no arguments.
|
||||
|
||||
`U` is the result type of `f`, with any reference and cv qualification removed, and must be an
|
||||
`etl::optional` whose `value_type` is `T`. The overload takes no part in overload resolution
|
||||
otherwise.
|
||||
|
||||
### Example
|
||||
|
||||
```cpp
|
||||
etl::optional<int> opt = 6;
|
||||
|
||||
etl::optional<double> result = opt.and_then([](int i) { return i > 0 ? etl::optional<int>(i * 2) : etl::optional<int>(); })
|
||||
.or_else([]() { return etl::optional<int>(1); })
|
||||
.transform([](int i) { return double(i) / 2.0; });
|
||||
// result contains 6.0
|
||||
```
|
||||
|
||||
## Non-member functions
|
||||
|
||||
```cpp
|
||||
@ -269,3 +327,15 @@ operator >=
|
||||
```
|
||||
**Description**
|
||||
`true` if the contents of the lhs are lexicographically greater than or equal to the contents of the rhs, otherwise `false`.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct etl::is_optional;
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool etl::is_optional_v; // C++17 and above
|
||||
```
|
||||
**Description**
|
||||
`true` if `T` is an `etl::optional`, otherwise `false`. Any cv qualification on `T` is ignored.
|
||||
|
||||
@ -1052,17 +1052,18 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Make
|
||||
//*************************************************************************
|
||||
#if ETL_HAS_INITIALIZER_LIST
|
||||
template <typename T, typename... TValues>
|
||||
constexpr auto make_array(TValues&&... values) ETL_NOEXCEPT -> etl::array<T, sizeof...(TValues)>
|
||||
#if ETL_USING_CPP11
|
||||
template <typename T = void, typename... TValues>
|
||||
constexpr auto make_array(TValues&&... values) -> etl::array<etl::private_make::element_type_t<T, TValues...>, sizeof...(TValues)>
|
||||
{
|
||||
// Forward each argument as its own deduced type, then convert explicitly to T.
|
||||
// Forwarding as T (the old behaviour) made the call ill-formed for any const-qualified
|
||||
// lvalue of type T: forward<T> requires a non-const T&, and a T&& cannot bind to a
|
||||
// reference-related const lvalue. The explicit conversion also keeps narrowing
|
||||
// initialisers (e.g. make_array<char>(0, 1)) working, which plain forwarding into the
|
||||
// braced initialiser list would reject.
|
||||
return {static_cast<T>(etl::forward<TValues>(values))...};
|
||||
// Library Fundamentals TS make_array design: the element type is T when
|
||||
// supplied explicitly, otherwise the decayed common type of the arguments.
|
||||
// convert forwards arguments that already have the element type and
|
||||
// converts the rest with static_cast, so const-qualified lvalues,
|
||||
// narrowing initialisers such as make_array<char>(0, 1) and non-movable
|
||||
// element types all work.
|
||||
using TElement = etl::private_make::element_type_t<T, TValues...>;
|
||||
return {etl::private_make::convert<TElement>(etl::forward<TValues>(values))...};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -900,6 +900,53 @@ namespace etl
|
||||
return pbuffer[(out + index) % buffer_size];
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Assigns an iterator range to the circular buffer.
|
||||
//*************************************************************************
|
||||
void assign(iterator first, const iterator& last)
|
||||
{
|
||||
assign_range(first, last);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Assigns a const iterator range to the circular buffer.
|
||||
//*************************************************************************
|
||||
void assign(const_iterator first, const const_iterator& last)
|
||||
{
|
||||
assign_range(first, last);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Assigns a range to the circular buffer.
|
||||
//*************************************************************************
|
||||
template <typename TIterator>
|
||||
typename etl::enable_if<!etl::is_integral<TIterator>::value, void>::type assign(TIterator first, const TIterator& last)
|
||||
{
|
||||
clear();
|
||||
push(first, last);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Assigns 'n' copies of a value to the circular buffer.
|
||||
//*************************************************************************
|
||||
void assign(size_type n, const_reference value)
|
||||
{
|
||||
if (n == 0U)
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
const T value_copy(value);
|
||||
|
||||
clear();
|
||||
|
||||
while (n-- != 0U)
|
||||
{
|
||||
push(value_copy);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// push.
|
||||
/// Adds an item to the buffer.
|
||||
@ -1036,6 +1083,43 @@ namespace etl
|
||||
|
||||
protected:
|
||||
|
||||
//*************************************************************************
|
||||
/// Assigns a circular buffer iterator range.
|
||||
//*************************************************************************
|
||||
template <typename TIterator>
|
||||
void assign_range(TIterator first, const TIterator& last)
|
||||
{
|
||||
const bool is_self_range = (&first.container() == this) && (&last.container() == this);
|
||||
|
||||
if (!is_self_range)
|
||||
{
|
||||
clear();
|
||||
push(first, last);
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_type first_index = static_cast<size_type>(first.get_index());
|
||||
const size_type last_index = static_cast<size_type>(last.get_index());
|
||||
|
||||
while (out != first_index)
|
||||
{
|
||||
pop();
|
||||
}
|
||||
|
||||
while (in != last_index)
|
||||
{
|
||||
if (in == 0U)
|
||||
{
|
||||
in = buffer_size;
|
||||
}
|
||||
|
||||
--in;
|
||||
pbuffer[in].~T();
|
||||
ETL_DECREMENT_DEBUG_COUNT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Protected constructor.
|
||||
//*************************************************************************
|
||||
@ -1127,6 +1211,24 @@ namespace etl
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor, with size.
|
||||
//*************************************************************************
|
||||
explicit circular_buffer(size_t initial_size)
|
||||
: icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
|
||||
{
|
||||
this->assign(initial_size, T());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor, from initial size and value.
|
||||
//*************************************************************************
|
||||
circular_buffer(size_t initial_size, typename etl::icircular_buffer<T>::const_reference value)
|
||||
: icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
|
||||
{
|
||||
this->assign(initial_size, value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor.
|
||||
/// Constructs a buffer from an iterator range.
|
||||
@ -1274,6 +1376,24 @@ namespace etl
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor, with size.
|
||||
//*************************************************************************
|
||||
explicit circular_buffer_ext(size_t initial_size, void* buffer, size_t max_size)
|
||||
: icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
|
||||
{
|
||||
this->assign(initial_size, T());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor, from initial size and value.
|
||||
//*************************************************************************
|
||||
circular_buffer_ext(size_t initial_size, typename etl::icircular_buffer<T>::const_reference value, void* buffer, size_t max_size)
|
||||
: icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
|
||||
{
|
||||
this->assign(initial_size, value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor.
|
||||
/// Constructs a buffer from an iterator range.
|
||||
|
||||
@ -449,7 +449,6 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Constructor
|
||||
//*************************************************************************
|
||||
template <typename... TElements>
|
||||
ETL_CONSTEXPR14 explicit iconst_map(const value_type* element_list_, size_type size_, size_type max_elements_) ETL_NOEXCEPT
|
||||
: element_list(element_list_)
|
||||
, element_list_end{element_list_ + size_}
|
||||
|
||||
@ -398,7 +398,6 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Constructor
|
||||
//*************************************************************************
|
||||
template <typename... TElements>
|
||||
ETL_CONSTEXPR14 explicit iconst_multimap(const value_type* element_list_, size_type size_, size_type max_elements_) ETL_NOEXCEPT
|
||||
: element_list(element_list_)
|
||||
, element_list_end{element_list_ + size_}
|
||||
|
||||
@ -354,7 +354,6 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Constructor
|
||||
//*************************************************************************
|
||||
template <typename... TElements>
|
||||
ETL_CONSTEXPR14 explicit iconst_multiset(const value_type* element_list_, size_type size_, size_type max_elements_) ETL_NOEXCEPT
|
||||
: element_list(element_list_)
|
||||
, element_list_end{element_list_ + size_}
|
||||
|
||||
@ -345,7 +345,6 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Constructor
|
||||
//*************************************************************************
|
||||
template <typename... TElements>
|
||||
ETL_CONSTEXPR14 explicit iconst_set(const value_type* element_list_, size_type size_, size_type max_elements_) ETL_NOEXCEPT
|
||||
: element_list(element_list_)
|
||||
, element_list_end{element_list_ + size_}
|
||||
|
||||
@ -348,16 +348,7 @@ namespace etl
|
||||
}
|
||||
|
||||
//***************************************************
|
||||
reference operator[](size_t i)
|
||||
{
|
||||
iterator result(*this);
|
||||
result += i;
|
||||
|
||||
return *result;
|
||||
}
|
||||
|
||||
//***************************************************
|
||||
const_reference operator[](size_t i) const
|
||||
reference operator[](difference_type i) const
|
||||
{
|
||||
iterator result(*this);
|
||||
result += i;
|
||||
@ -607,10 +598,10 @@ namespace etl
|
||||
}
|
||||
|
||||
//***************************************************
|
||||
const_reference operator[](size_t i) const
|
||||
const_reference operator[](difference_type i) const
|
||||
{
|
||||
const_iterator result(*this);
|
||||
result += static_cast<difference_type>(i);
|
||||
result += i;
|
||||
|
||||
return *result;
|
||||
}
|
||||
@ -2532,16 +2523,17 @@ namespace etl
|
||||
/// Make
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
|
||||
template <typename T, typename... TValues>
|
||||
constexpr auto make_deque(TValues&&... values) -> etl::deque<T, sizeof...(TValues)>
|
||||
template <typename T = void, typename... TValues>
|
||||
constexpr auto make_deque(TValues&&... values) -> etl::deque<etl::private_make::element_type_t<T, TValues...>, sizeof...(TValues)>
|
||||
{
|
||||
// Forward each argument as its own deduced type, then convert explicitly to T.
|
||||
// Forwarding as T (the old behaviour) made the call ill-formed for any const-qualified
|
||||
// lvalue of type T: forward<T> requires a non-const T&, and a T&& cannot bind to a
|
||||
// reference-related const lvalue. The explicit conversion also keeps narrowing
|
||||
// initialisers (e.g. make_deque<char>(0, 1)) working, which plain forwarding into the
|
||||
// braced initialiser list would reject.
|
||||
return {static_cast<T>(etl::forward<TValues>(values))...};
|
||||
// Library Fundamentals TS make_array design: the element type is T when
|
||||
// supplied explicitly, otherwise the decayed common type of the arguments.
|
||||
// convert forwards arguments that already have the element type and
|
||||
// converts the rest with static_cast, so const-qualified lvalues,
|
||||
// narrowing initialisers such as make_deque<char>(0, 1) and non-movable
|
||||
// element types all work.
|
||||
using TElement = etl::private_make::element_type_t<T, TValues...>;
|
||||
return {etl::private_make::convert<TElement>(etl::forward<TValues>(values))...};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -1435,6 +1435,11 @@ namespace etl
|
||||
return lhs.error() == rhs.error();
|
||||
}
|
||||
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
//*******************************************
|
||||
// The error is only read when the expected does not have a value, in which
|
||||
// case it is always fully constructed. GCC can emit a false positive
|
||||
// -Wmaybe-uninitialized when these are inlined at high optimisation levels.
|
||||
//*******************************************
|
||||
template <typename TError, typename TError2>
|
||||
ETL_CONSTEXPR14 bool operator==(const etl::expected<void, TError>& lhs, const etl::expected<void, TError2>& rhs)
|
||||
@ -1460,6 +1465,7 @@ namespace etl
|
||||
}
|
||||
return lhs.error() == rhs.error();
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
//*******************************************
|
||||
template <typename TError, typename TError2>
|
||||
|
||||
@ -321,7 +321,6 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Emplaces a value to the set.
|
||||
//*************************************************************************
|
||||
template <typename T1>
|
||||
ETL_OR_STD::pair<iterator, bool> emplace(const_reference value)
|
||||
{
|
||||
return insert(value);
|
||||
|
||||
@ -1516,7 +1516,7 @@ namespace etl
|
||||
}
|
||||
|
||||
// for integers
|
||||
template <typename OutputIt, typename T, bool skip_last_zeros = false>
|
||||
template <typename OutputIt, typename T>
|
||||
void format_num(OutputIt& it, T value, const format_spec_t& spec)
|
||||
{
|
||||
size_t width = 0;
|
||||
|
||||
@ -1793,10 +1793,14 @@ namespace etl
|
||||
/// Make
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
|
||||
template <typename... T>
|
||||
constexpr auto make_forward_list(T&&... t) -> etl::forward_list<typename etl::common_type_t<T...>, sizeof...(T)>
|
||||
template <typename T = void, typename... TValues>
|
||||
constexpr auto make_forward_list(TValues&&... values) -> etl::forward_list<etl::private_make::element_type_t<T, TValues...>, sizeof...(TValues)>
|
||||
{
|
||||
return {etl::forward<T>(t)...};
|
||||
// Library Fundamentals TS make_array design: the element type is T when
|
||||
// supplied explicitly, otherwise the decayed common type of the arguments.
|
||||
// convert forwards same-type arguments and static_casts the rest.
|
||||
using TElement = etl::private_make::element_type_t<T, TValues...>;
|
||||
return {etl::private_make::convert<TElement>(etl::forward<TValues>(values))...};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -1551,10 +1551,15 @@ namespace etl
|
||||
/// Make
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
|
||||
template <typename... T>
|
||||
constexpr auto make_indirect_vector(T&&... t) -> etl::indirect_vector<typename etl::common_type_t<T...>, sizeof...(T)>
|
||||
template <typename T = void, typename... TValues>
|
||||
constexpr auto
|
||||
make_indirect_vector(TValues&&... values) -> etl::indirect_vector<etl::private_make::element_type_t<T, TValues...>, sizeof...(TValues)>
|
||||
{
|
||||
return {etl::forward<T>(t)...};
|
||||
// Library Fundamentals TS make_array design: the element type is T when
|
||||
// supplied explicitly, otherwise the decayed common type of the arguments.
|
||||
// convert forwards same-type arguments and static_casts the rest.
|
||||
using TElement = etl::private_make::element_type_t<T, TValues...>;
|
||||
return {etl::private_make::convert<TElement>(etl::forward<TValues>(values))...};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -1126,8 +1126,13 @@ namespace etl
|
||||
{
|
||||
}
|
||||
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
//*************************************************************************
|
||||
// clone_from
|
||||
//
|
||||
// GCC can emit a false positive -Wmaybe-uninitialized for the source
|
||||
// storage when this is inlined into a copy constructor at high
|
||||
// optimisation levels. The source object is always fully constructed.
|
||||
//*************************************************************************
|
||||
template <size_t Other_Object_Size, size_t Other_Object_Alignment>
|
||||
void clone_from(const etl::inplace_function<TReturn(TArgs...), Other_Object_Size, Other_Object_Alignment>& other)
|
||||
@ -1139,6 +1144,7 @@ namespace etl
|
||||
vtable->copy(&other.storage, &storage);
|
||||
}
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
//*************************************************************************
|
||||
// move_from
|
||||
|
||||
@ -39,6 +39,8 @@ SOFTWARE.
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
|
||||
#include "private/diagnostic_array_bounds_push.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//****************************************************************************
|
||||
@ -387,5 +389,7 @@ namespace etl
|
||||
#endif
|
||||
} // namespace etl
|
||||
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
#endif // ETL_USING_CPP11
|
||||
#endif // ETL_INVOKE_INCLUDED
|
||||
|
||||
@ -1656,6 +1656,22 @@ namespace etl
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
// Overload for ranges
|
||||
template <typename R, typename I = decltype(ETL_OR_STD::begin(etl::declval<R&>()))>
|
||||
constexpr etl::iter_difference_t<I> operator()(R&& r) const
|
||||
{
|
||||
using U = etl::remove_cvref_t<R>;
|
||||
|
||||
if constexpr (has_size_member<U>::value)
|
||||
{
|
||||
return static_cast<etl::iter_difference_t<I>>(r.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
return (*this)(ETL_OR_STD::begin(r), ETL_OR_STD::end(r));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct size
|
||||
|
||||
@ -2218,10 +2218,14 @@ namespace etl
|
||||
/// Make
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
|
||||
template <typename... T>
|
||||
constexpr auto make_list(T&&... t) -> etl::list<typename etl::common_type_t<T...>, sizeof...(T)>
|
||||
template <typename T = void, typename... TValues>
|
||||
constexpr auto make_list(TValues&&... values) -> etl::list<etl::private_make::element_type_t<T, TValues...>, sizeof...(TValues)>
|
||||
{
|
||||
return {etl::forward<T>(t)...};
|
||||
// Library Fundamentals TS make_array design: the element type is T when
|
||||
// supplied explicitly, otherwise the decayed common type of the arguments.
|
||||
// convert forwards same-type arguments and static_casts the rest.
|
||||
using TElement = etl::private_make::element_type_t<T, TValues...>;
|
||||
return {etl::private_make::convert<TElement>(etl::forward<TValues>(values))...};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -305,6 +305,7 @@ namespace etl
|
||||
(add_new_message_type<TMessageTypes>(etl::move(msg)) || ...);
|
||||
}
|
||||
|
||||
#include "private/diagnostic_array_bounds_push.h"
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
//********************************************
|
||||
/// Only enabled for types that are in the typelist.
|
||||
@ -318,6 +319,9 @@ namespace etl
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
#include "private/diagnostic_array_bounds_push.h"
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
//********************************************
|
||||
template <typename TType>
|
||||
@ -336,6 +340,9 @@ namespace etl
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
#include "private/diagnostic_array_bounds_push.h"
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
//********************************************
|
||||
template <typename TType>
|
||||
@ -352,6 +359,8 @@ namespace etl
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
|
||||
|
||||
@ -31,8 +31,26 @@ SOFTWARE.
|
||||
|
||||
#include "../platform.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include <semphr.h>
|
||||
#if defined(__has_include) // Compiler supports __has_include
|
||||
|
||||
#if __has_include(<FreeRTOS.h>) && __has_include(<semphr.h>) // Standard FreeRTOS include layout
|
||||
#include <FreeRTOS.h>
|
||||
#include <semphr.h>
|
||||
|
||||
#elif __has_include(<freertos/FreeRTOS.h>) && __has_include(<freertos/semphr.h>) // ESP-IDF style include layout
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
|
||||
#else // Neither include layout found
|
||||
#error "FreeRTOS.h and semphr.h not found. Please include path to FreeRTOS in your project settings"
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <semphr.h>
|
||||
|
||||
#endif
|
||||
|
||||
namespace etl
|
||||
{
|
||||
|
||||
@ -35,6 +35,7 @@ SOFTWARE.
|
||||
#include "error_handler.h"
|
||||
#include "exception.h"
|
||||
#include "memory.h"
|
||||
#include "nullptr.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
namespace etl
|
||||
@ -95,7 +96,16 @@ namespace etl
|
||||
ETL_CONSTEXPR14 explicit not_null(underlying_type ptr_)
|
||||
: ptr(ptr_)
|
||||
{
|
||||
ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null));
|
||||
if (etl::is_constant_evaluated())
|
||||
{
|
||||
// ETL_IS_FOLDED_NULL keeps the compile time rejection of null working
|
||||
// when the undefined behaviour sanitizer instruments the comparison.
|
||||
ETL_ASSERT(!ETL_IS_FOLDED_NULL(ptr_), ETL_ERROR(not_null_contains_null));
|
||||
}
|
||||
else
|
||||
{
|
||||
ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null));
|
||||
}
|
||||
}
|
||||
|
||||
//*********************************
|
||||
@ -112,7 +122,14 @@ namespace etl
|
||||
//*********************************
|
||||
ETL_CONSTEXPR14 not_null& operator=(underlying_type rhs)
|
||||
{
|
||||
ETL_ASSERT_OR_RETURN_VALUE(rhs != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this);
|
||||
if (etl::is_constant_evaluated())
|
||||
{
|
||||
ETL_ASSERT_OR_RETURN_VALUE(!ETL_IS_FOLDED_NULL(rhs), ETL_ERROR(not_null_contains_null), *this);
|
||||
}
|
||||
else
|
||||
{
|
||||
ETL_ASSERT_OR_RETURN_VALUE(rhs != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this);
|
||||
}
|
||||
|
||||
ptr = rhs;
|
||||
|
||||
|
||||
@ -78,4 +78,26 @@ namespace etl
|
||||
#endif
|
||||
} // namespace etl
|
||||
|
||||
//*****************************************************************************
|
||||
/// True when the compiler can fold the comparison at compile time and it yields
|
||||
/// null.
|
||||
///
|
||||
/// Normally the comparison folds for any pointer that is a constant expression,
|
||||
/// so this is equivalent to a plain null check. Under GCC's undefined behaviour
|
||||
/// sanitizer, however, the comparison is instrumented and only folds for a null
|
||||
/// pointer constant, not for the address of an object or function.
|
||||
/// __builtin_constant_p filters out the latter, which would otherwise make the
|
||||
/// enclosing expression non-constant and reject perfectly valid code.
|
||||
///
|
||||
/// Only meaningful during constant evaluation. At run time
|
||||
/// __builtin_constant_p is false for any pointer that is not a compile time
|
||||
/// constant, so this reports false for a genuine null pointer. Callers must
|
||||
/// use a plain comparison against ETL_NULLPTR on the run time path.
|
||||
//*****************************************************************************
|
||||
#if ETL_USING_BUILTIN_CONSTANT_P
|
||||
#define ETL_IS_FOLDED_NULL(p) (__builtin_constant_p((p) == ETL_NULLPTR) && ((p) == ETL_NULLPTR))
|
||||
#else
|
||||
#define ETL_IS_FOLDED_NULL(p) ((p) == ETL_NULLPTR)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -36,6 +36,7 @@ SOFTWARE.
|
||||
#include "error_handler.h"
|
||||
#include "exception.h"
|
||||
#include "initializer_list.h"
|
||||
#include "invoke.h"
|
||||
#include "memory.h"
|
||||
#include "placement_new.h"
|
||||
#include "type_traits.h"
|
||||
@ -49,6 +50,41 @@ namespace etl
|
||||
template <typename T>
|
||||
class optional;
|
||||
|
||||
//*****************************************************************************
|
||||
/// Determines if a type is an etl::optional.
|
||||
/// Ignores any cv qualification on the type being tested.
|
||||
///\ingroup utilities
|
||||
//*****************************************************************************
|
||||
template <typename T>
|
||||
struct is_optional : etl::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_optional<optional<T> > : etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_optional<const optional<T> > : etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_optional<volatile optional<T> > : etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_optional<const volatile optional<T> > : etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
template <typename T>
|
||||
inline constexpr bool is_optional_v = etl::is_optional<T>::value;
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
/// A null option type.
|
||||
///\ingroup utilities
|
||||
@ -174,10 +210,9 @@ namespace etl
|
||||
/// Constructs T in-place from U&&, without requiring T to be
|
||||
/// copy/move constructible.
|
||||
//***************************************************************************
|
||||
template <typename U,
|
||||
typename etl::enable_if< etl::is_constructible<T, U&&>::value && !etl::is_same<typename etl::decay<U>::type, etl::in_place_t>::value
|
||||
&& !etl::is_same<typename etl::decay<U>::type, optional_impl>::value,
|
||||
int>::type = 0>
|
||||
template <typename U, etl::enable_if_t< etl::is_constructible<T, U&&>::value && !etl::is_same<etl::decay_t<U>, etl::in_place_t>::value
|
||||
&& !etl::is_same<etl::decay_t<U>, optional_impl>::value,
|
||||
int> = 0>
|
||||
ETL_CONSTEXPR20_STL optional_impl(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, U&&>::value))
|
||||
{
|
||||
storage.construct(etl::forward<U>(value_));
|
||||
@ -276,9 +311,7 @@ namespace etl
|
||||
/// Assignment operator from value type.
|
||||
//***************************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
template <typename U,
|
||||
typename etl::enable_if< etl::is_constructible<T, U&&>::value && !etl::is_same<typename etl::decay<U>::type, optional_impl>::value,
|
||||
int>::type = 0>
|
||||
template <typename U, etl::enable_if_t< etl::is_constructible<T, U&&>::value && !etl::is_same<etl::decay_t<U>, optional_impl>::value, int> = 0>
|
||||
ETL_CONSTEXPR20_STL optional_impl& operator=(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, U&&>::value))
|
||||
{
|
||||
storage.construct(etl::forward<U>(value_));
|
||||
@ -511,8 +544,7 @@ namespace etl
|
||||
//*******************************************
|
||||
/// Emplaces a value from initializer_list and arbitrary constructor arguments.
|
||||
//*******************************************
|
||||
template <typename U, typename... Args,
|
||||
typename etl::enable_if< etl::is_constructible<T, std::initializer_list<U>&, Args...>::value, int>::type = 0 >
|
||||
template <typename U, typename... Args, etl::enable_if_t< etl::is_constructible<T, std::initializer_list<U>&, Args...>::value, int> = 0 >
|
||||
ETL_CONSTEXPR20_STL T& emplace(std::initializer_list<U> ilist, Args&&... args)
|
||||
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, std::initializer_list<U>&, Args...>::value))
|
||||
{
|
||||
@ -671,6 +703,11 @@ namespace etl
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
//*******************************
|
||||
// GCC may warn that 'valid' is used uninitialised when the storage of a
|
||||
// nested optional is inspected through an inlined destructor chain.
|
||||
// The flag is always initialised by the constructors, so this is a false positive.
|
||||
//*******************************
|
||||
ETL_CONSTEXPR20_STL
|
||||
void destroy()
|
||||
@ -681,6 +718,7 @@ namespace etl
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
//*******************************
|
||||
union union_type
|
||||
@ -1217,8 +1255,8 @@ namespace etl
|
||||
};
|
||||
} // namespace private_optional
|
||||
|
||||
#define ETL_OPTIONAL_ENABLE_CPP14 typename etl::enable_if< etl::is_pod<typename etl::remove_cv<U>::type>::value, int>::type = 0
|
||||
#define ETL_OPTIONAL_ENABLE_CPP20_STL typename etl::enable_if< !etl::is_pod<typename etl::remove_cv<U>::type>::value, int>::type = 0
|
||||
#define ETL_OPTIONAL_ENABLE_CPP14 etl::enable_if_t< etl::is_pod<typename etl::remove_cv<U>::type>::value, int> = 0
|
||||
#define ETL_OPTIONAL_ENABLE_CPP20_STL etl::enable_if_t< !etl::is_pod<typename etl::remove_cv<U>::type>::value, int> = 0
|
||||
|
||||
#define ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 \
|
||||
ETL_CONSTEXPR14 typename etl::enable_if< etl::is_pod<typename etl::remove_cv<T>::type>::value, bool>::type
|
||||
@ -1319,12 +1357,10 @@ namespace etl
|
||||
/// Constructs T in-place from U&&, without requiring T to be
|
||||
/// copy/move constructible.
|
||||
//***************************************************************************
|
||||
template < typename U,
|
||||
typename etl::enable_if< etl::is_constructible<T, U&&>::value && !etl::is_same<typename etl::decay<U>::type, etl::optional<T>>::value
|
||||
&& !etl::is_same<typename etl::decay<U>::type, etl::in_place_t>::value
|
||||
&& !etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value
|
||||
&& etl::is_pod<typename etl::remove_cv<T>::type>::value,
|
||||
int>::type = 0>
|
||||
template < typename U, etl::enable_if_t< etl::is_constructible<T, U&&>::value && !etl::is_same<etl::decay_t<U>, etl::optional<T>>::value
|
||||
&& !etl::is_same<etl::decay_t<U>, etl::in_place_t>::value
|
||||
&& !etl::is_same<etl::decay_t<U>, etl::nullopt_t>::value && etl::is_pod<etl::remove_cvref_t<T>>::value,
|
||||
int> = 0>
|
||||
ETL_CONSTEXPR14 optional(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, U&&>::value))
|
||||
: impl_t(etl::forward<U>(value_))
|
||||
{
|
||||
@ -1334,11 +1370,10 @@ namespace etl
|
||||
/// Converting constructor from value type.
|
||||
//***************************************************************************
|
||||
template < typename U,
|
||||
typename etl::enable_if< etl::is_constructible<T, U&&>::value && !etl::is_same<typename etl::decay<U>::type, etl::optional<T>>::value
|
||||
&& !etl::is_same<typename etl::decay<U>::type, etl::in_place_t>::value
|
||||
&& !etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value
|
||||
&& !etl::is_pod<typename etl::remove_cv<T>::type>::value,
|
||||
int>::type = 0>
|
||||
etl::enable_if_t< etl::is_constructible<T, U&&>::value && !etl::is_same<etl::decay_t<U>, etl::optional<T>>::value
|
||||
&& !etl::is_same<etl::decay_t<U>, etl::in_place_t>::value && !etl::is_same<etl::decay_t<U>, etl::nullopt_t>::value
|
||||
&& !etl::is_pod<etl::remove_cvref_t<T>>::value,
|
||||
int> = 0>
|
||||
ETL_CONSTEXPR20_STL optional(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, U&&>::value))
|
||||
: impl_t(etl::forward<U>(value_))
|
||||
{
|
||||
@ -1446,11 +1481,9 @@ namespace etl
|
||||
//***************************************************************************
|
||||
/// Converting assignment operator from value type.
|
||||
//***************************************************************************
|
||||
template < typename U,
|
||||
typename etl::enable_if< etl::is_constructible<T, U&&>::value && !etl::is_same<typename etl::decay<U>::type, etl::optional<T>>::value
|
||||
&& !etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value
|
||||
&& etl::is_pod<typename etl::remove_cv<T>::type>::value,
|
||||
int>::type = 0>
|
||||
template < typename U, etl::enable_if_t< etl::is_constructible<T, U&&>::value && !etl::is_same<etl::decay_t<U>, etl::optional<T>>::value
|
||||
&& !etl::is_same<etl::decay_t<U>, etl::nullopt_t>::value && etl::is_pod<etl::remove_cvref_t<T>>::value,
|
||||
int> = 0>
|
||||
ETL_CONSTEXPR14 optional& operator=(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, U&&>::value))
|
||||
{
|
||||
impl_t::operator=(etl::forward<U>(value_));
|
||||
@ -1462,10 +1495,9 @@ namespace etl
|
||||
/// Converting assignment operator from value type.
|
||||
//***************************************************************************
|
||||
template < typename U,
|
||||
typename etl::enable_if< etl::is_constructible<T, U&&>::value && !etl::is_same<typename etl::decay<U>::type, etl::optional<T>>::value
|
||||
&& !etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value
|
||||
&& !etl::is_pod<typename etl::remove_cv<T>::type>::value,
|
||||
int>::type = 0>
|
||||
etl::enable_if_t< etl::is_constructible<T, U&&>::value && !etl::is_same<etl::decay_t<U>, etl::optional<T>>::value
|
||||
&& !etl::is_same<etl::decay_t<U>, etl::nullopt_t>::value && !etl::is_pod<etl::remove_cvref_t<T>>::value,
|
||||
int> = 0>
|
||||
ETL_CONSTEXPR20_STL optional& operator=(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, U&&>::value))
|
||||
{
|
||||
impl_t::operator=(etl::forward<U>(value_));
|
||||
@ -1519,6 +1551,124 @@ namespace etl
|
||||
{
|
||||
return this->has_value() ? this->operator->() + 1 : ETL_NULLPTR;
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <typename F, typename U = etl::remove_cvref_t<etl::invoke_result_t<F, T&>>, etl::enable_if_t<!etl::is_void<U>::value, int> = 0>
|
||||
auto transform(F&& f) & -> etl::optional<U>
|
||||
{
|
||||
return transform_impl<F, optional&, U, T&>(etl::forward<F>(f), *this);
|
||||
}
|
||||
|
||||
template <typename F, typename U = etl::remove_cvref_t<etl::invoke_result_t<F, const T&>>, etl::enable_if_t<!etl::is_void<U>::value, int> = 0>
|
||||
auto transform(F&& f) const& -> etl::optional<U>
|
||||
{
|
||||
return transform_impl<F, const optional&, U, const T&>(etl::forward<F>(f), *this);
|
||||
}
|
||||
|
||||
template <typename F, typename U = etl::remove_cvref_t<etl::invoke_result_t<F, T&&>>, etl::enable_if_t<!etl::is_void<U>::value, int> = 0>
|
||||
auto transform(F&& f) && -> etl::optional<U>
|
||||
{
|
||||
return transform_impl<F, optional&&, U, T&&>(etl::forward<F>(f), etl::move(*this));
|
||||
}
|
||||
|
||||
template <typename F, typename U = etl::remove_cvref_t<etl::invoke_result_t<F, const T&&>>, etl::enable_if_t<!etl::is_void<U>::value, int> = 0>
|
||||
auto transform(F&& f) const&& -> etl::optional<U>
|
||||
{
|
||||
return transform_impl<F, const optional&&, U, const T&&>(etl::forward<F>(f), etl::move(*this));
|
||||
}
|
||||
|
||||
template <typename F, typename U = etl::remove_cvref_t< etl::invoke_result_t<F, T&>>>
|
||||
auto and_then(F&& f) & -> U
|
||||
{
|
||||
return and_then_impl<F, optional&, U, T&>(etl::forward<F>(f), *this);
|
||||
}
|
||||
|
||||
template < typename F, typename U = etl::remove_cvref_t< etl::invoke_result_t<F, const T&>>>
|
||||
auto and_then(F&& f) const& -> U
|
||||
{
|
||||
return and_then_impl<F, const optional&, U, const T&>(etl::forward<F>(f), *this);
|
||||
}
|
||||
|
||||
template <typename F, typename U = etl::remove_cvref_t< etl::invoke_result_t<F, T&&>>>
|
||||
auto and_then(F&& f) && -> U
|
||||
{
|
||||
return and_then_impl<F, optional&&, U, T&&>(etl::forward<F>(f), etl::move(*this));
|
||||
}
|
||||
|
||||
template < typename F, typename U = etl::remove_cvref_t< etl::invoke_result_t<F, const T&&>>>
|
||||
auto and_then(F&& f) const&& -> U
|
||||
{
|
||||
return and_then_impl<F, const optional&&, U, const T&&>(etl::forward<F>(f), etl::move(*this));
|
||||
}
|
||||
|
||||
template <typename F, typename U = etl::remove_cvref_t<etl::invoke_result_t<F>>>
|
||||
auto or_else(F&& f) & -> U
|
||||
{
|
||||
return or_else_impl<F, optional&, U>(etl::forward<F>(f), *this);
|
||||
}
|
||||
|
||||
template < typename F, typename U = etl::remove_cvref_t<etl::invoke_result_t<F>>>
|
||||
auto or_else(F&& f) const& -> U
|
||||
{
|
||||
return or_else_impl<F, const optional&, U>(etl::forward<F>(f), *this);
|
||||
}
|
||||
|
||||
template <typename F, typename U = etl::remove_cvref_t< etl::invoke_result_t<F>>>
|
||||
auto or_else(F&& f) && -> U
|
||||
{
|
||||
return or_else_impl<F, optional&&, U>(etl::forward<F>(f), etl::move(*this));
|
||||
}
|
||||
|
||||
template < typename F, typename U = etl::remove_cvref_t< etl::invoke_result_t<F>>>
|
||||
auto or_else(F&& f) const&& -> U
|
||||
{
|
||||
return or_else_impl<F, const optional&&, U>(etl::forward<F>(f), etl::move(*this));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template < typename F, typename TOpt, typename TRet, typename TValueRef, typename = etl::enable_if_t<!etl::is_void<TRet>::value>>
|
||||
auto transform_impl(F&& f, TOpt&& opt) const -> etl::optional<TRet>
|
||||
{
|
||||
if (opt.has_value())
|
||||
{
|
||||
return etl::optional<TRet>(etl::invoke(etl::forward<F>(f), etl::forward<TValueRef>(*opt)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return etl::optional<TRet>();
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F, typename TOpt, typename TRet, typename TValueRef,
|
||||
typename = etl::enable_if_t<!etl::is_void<TRet>::value && etl::is_optional<TRet>::value>>
|
||||
auto and_then_impl(F&& f, TOpt&& opt) const -> TRet
|
||||
{
|
||||
if (opt.has_value())
|
||||
{
|
||||
return etl::invoke(etl::forward<F>(f), etl::forward<TValueRef>(*opt));
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRet();
|
||||
}
|
||||
}
|
||||
|
||||
template <
|
||||
typename F, typename TOpt, typename TRet,
|
||||
typename = etl::enable_if_t< !etl::is_void<TRet>::value && etl::is_optional<TRet>::value && etl::is_same<typename TRet::value_type, T>::value>>
|
||||
auto or_else_impl(F&& f, TOpt&& opt) const -> TRet
|
||||
{
|
||||
if (opt.has_value())
|
||||
{
|
||||
return TRet(etl::forward<TOpt>(opt));
|
||||
}
|
||||
else
|
||||
{
|
||||
return etl::invoke(etl::forward<F>(f));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
@ -2132,17 +2282,17 @@ namespace etl
|
||||
/// This overload participates in overload resolution only if
|
||||
/// `etl::is_constructible_v<T, Args...>` is true.
|
||||
//***************************************************************************
|
||||
template <typename T, typename... Args, //
|
||||
typename etl::enable_if< etl::is_constructible<T, Args...>::value, int>::type = 0, //
|
||||
template <typename T, typename... Args, //
|
||||
etl::enable_if_t< etl::is_constructible<T, Args...>::value, int> = 0, //
|
||||
typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
|
||||
ETL_CONSTEXPR14 etl::optional<T> make_optional(Args&&... args) //
|
||||
ETL_CONSTEXPR14 etl::optional<T> make_optional(Args&&... args) //
|
||||
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, Args...>::value))
|
||||
{
|
||||
return etl::optional<T>(etl::in_place_t{}, etl::forward<Args>(args)...);
|
||||
}
|
||||
template <typename T, typename... Args, //
|
||||
typename etl::enable_if< etl::is_constructible<T, Args...>::value, int>::type = 0, //
|
||||
typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
template <typename T, typename... Args, //
|
||||
etl::enable_if_t< etl::is_constructible<T, Args...>::value, int> = 0, //
|
||||
typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
ETL_CONSTEXPR20_STL etl::optional<T> make_optional(Args&&... args) //
|
||||
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, Args...>::value))
|
||||
{
|
||||
@ -2156,17 +2306,17 @@ namespace etl
|
||||
/// This overload participates in overload resolution only if
|
||||
/// `etl::is_constructible_v<T, std::initializer_list<U>&, Args...>` is true.
|
||||
//***************************************************************************
|
||||
template <typename T, typename TL, typename... Args, //
|
||||
typename etl::enable_if< etl::is_constructible<T, std::initializer_list<TL>&, Args...>::value, int>::type = 0, //
|
||||
template <typename T, typename TL, typename... Args, //
|
||||
etl::enable_if_t< etl::is_constructible<T, std::initializer_list<TL>&, Args...>::value, int> = 0, //
|
||||
typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
|
||||
ETL_CONSTEXPR14 etl::optional<T> make_optional(std::initializer_list<TL> ilist, Args&&... args)
|
||||
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, std::initializer_list<TL>&, Args...>::value))
|
||||
{
|
||||
return etl::optional<T>(etl::in_place_t{}, ilist, etl::forward<Args>(args)...);
|
||||
}
|
||||
template <typename T, typename TL, typename... Args, //
|
||||
typename etl::enable_if< etl::is_constructible<T, std::initializer_list<TL>&, Args...>::value, int>::type = 0, //
|
||||
typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
template <typename T, typename TL, typename... Args, //
|
||||
etl::enable_if_t< etl::is_constructible<T, std::initializer_list<TL>&, Args...>::value, int> = 0, //
|
||||
typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
ETL_CONSTEXPR20_STL etl::optional<T> make_optional(std::initializer_list<TL> ilist, Args&&... args)
|
||||
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, std::initializer_list<TL>&, Args...>::value))
|
||||
{
|
||||
|
||||
@ -77,6 +77,7 @@ namespace etl
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef TBase* pointer;
|
||||
typedef TBase& reference;
|
||||
typedef const TBase& const_reference;
|
||||
typedef ETL_OR_STD::random_access_iterator_tag iterator_category;
|
||||
|
||||
//*****************************************
|
||||
@ -114,6 +115,15 @@ namespace etl
|
||||
return ptr;
|
||||
}
|
||||
|
||||
//***************************************************
|
||||
reference operator[](difference_type i) const
|
||||
{
|
||||
iterator result(*this);
|
||||
result += i;
|
||||
|
||||
return *result;
|
||||
}
|
||||
|
||||
//*****************************************
|
||||
iterator& operator++()
|
||||
{
|
||||
|
||||
@ -492,7 +492,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Assignment
|
||||
//*************************************************************************
|
||||
delegate& operator=(const delegate& rhs) = default;
|
||||
ETL_CONSTEXPR14 delegate& operator=(const delegate& rhs) = default;
|
||||
|
||||
//*************************************************************************
|
||||
/// Create from Lambda or Functor.
|
||||
|
||||
@ -94,6 +94,15 @@ namespace etl
|
||||
template <size_t Index, typename THead, typename... TRest>
|
||||
struct variant_operations<Index, THead, TRest...>
|
||||
{
|
||||
#include "diagnostic_uninitialized_push.h"
|
||||
//*************************************************************************
|
||||
// destroy
|
||||
//
|
||||
// GCC can emit a false positive -Wmaybe-uninitialized when this is inlined
|
||||
// into a variant destructor at high optimisation levels, as it cannot
|
||||
// prove that the branch for an inactive alternative is never taken.
|
||||
// The alternative identified by type_id is always fully constructed.
|
||||
//*************************************************************************
|
||||
static void destroy(char* data, size_t type_id)
|
||||
{
|
||||
if (type_id == Index)
|
||||
@ -105,6 +114,7 @@ namespace etl
|
||||
variant_operations<Index + 1, TRest...>::destroy(data, type_id);
|
||||
}
|
||||
}
|
||||
#include "diagnostic_pop.h"
|
||||
|
||||
static void copy(char* dst, const char* src, size_t type_id)
|
||||
{
|
||||
@ -156,6 +166,14 @@ namespace etl
|
||||
|
||||
private:
|
||||
|
||||
#include "diagnostic_uninitialized_push.h"
|
||||
//*************************************************************************
|
||||
// The *_impl functions below read the alternative identified by type_id,
|
||||
// which is always fully constructed. GCC can emit a false positive
|
||||
// -Wmaybe-uninitialized when these are inlined at high optimisation
|
||||
// levels, as it cannot prove that the branch for an inactive alternative
|
||||
// is never taken.
|
||||
//*************************************************************************
|
||||
static void copy_impl(char* dst, const char* src, etl::true_type)
|
||||
{
|
||||
::new (dst) THead(*reinterpret_cast<const THead*>(src));
|
||||
@ -183,6 +201,7 @@ namespace etl
|
||||
}
|
||||
|
||||
static void move_assign_impl(char*, const char*, etl::false_type) {}
|
||||
#include "diagnostic_pop.h"
|
||||
};
|
||||
|
||||
//*******************************************
|
||||
@ -555,113 +574,94 @@ namespace etl
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// variant_base specialisation for trivially destructible types.
|
||||
/// Uses variadic_union storage. Destructor is trivial (defaulted), making
|
||||
/// the variant a literal type eligible for constexpr / ROM placement.
|
||||
/// No operation function pointer is needed since destroy/copy/move are
|
||||
/// all handled without indirection for trivially destructible types.
|
||||
//***************************************************************************
|
||||
//*******************************************
|
||||
/// Trait: are all types trivially copyable?
|
||||
//*******************************************
|
||||
template <typename... TTypes>
|
||||
struct variant_base<true, TTypes...>
|
||||
struct are_all_trivially_copyable : etl::conjunction<etl::is_trivially_copyable<TTypes>...>
|
||||
{
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Storage and copy/move operations used by the trivially destructible
|
||||
/// variant_base specialisation.
|
||||
/// The general case defines the copy and move operations in terms of the
|
||||
/// operations of the currently active alternative.
|
||||
//***************************************************************************
|
||||
template <bool IsAllTriviallyCopyable, typename... TTypes>
|
||||
struct variant_trivially_destructible_base
|
||||
{
|
||||
variadic_union<TTypes...> data;
|
||||
size_t type_id;
|
||||
|
||||
constexpr variant_base() noexcept
|
||||
constexpr variant_trivially_destructible_base() noexcept
|
||||
: data()
|
||||
, type_id(variant_npos)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr variant_base(size_t id) noexcept
|
||||
constexpr variant_trivially_destructible_base(size_t id) noexcept
|
||||
: data()
|
||||
, type_id(id)
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t Index, typename T>
|
||||
constexpr variant_base(etl::in_place_index_t<Index>, T&& value,
|
||||
size_t id) noexcept(etl::is_nothrow_constructible<etl::nth_type_t<Index, TTypes...>, T>::value)
|
||||
constexpr variant_trivially_destructible_base(etl::in_place_index_t<Index>, T&& value,
|
||||
size_t id) noexcept(etl::is_nothrow_constructible<etl::nth_type_t<Index, TTypes...>, T>::value)
|
||||
: data(etl::in_place_index_t<Index>{}, etl::forward<T>(value))
|
||||
, type_id(id)
|
||||
{
|
||||
}
|
||||
|
||||
variant_base(const variant_base& other) noexcept(etl::conjunction<etl::is_nothrow_copy_constructible<TTypes>...>::value)
|
||||
variant_trivially_destructible_base(const variant_trivially_destructible_base& other) noexcept(
|
||||
etl::conjunction<etl::is_nothrow_copy_constructible<TTypes>...>::value)
|
||||
: data()
|
||||
, type_id(other.type_id)
|
||||
{
|
||||
copy_construct_from(other, is_all_trivially_copyable{});
|
||||
copy_construct_from(other);
|
||||
}
|
||||
|
||||
variant_base(variant_base&& other) noexcept(etl::conjunction<etl::is_nothrow_move_constructible<TTypes>...>::value)
|
||||
variant_trivially_destructible_base(variant_trivially_destructible_base&& other) noexcept(
|
||||
etl::conjunction<etl::is_nothrow_move_constructible<TTypes>...>::value)
|
||||
: data()
|
||||
, type_id(other.type_id)
|
||||
{
|
||||
move_construct_from(other, is_all_trivially_copyable{});
|
||||
move_construct_from(other);
|
||||
}
|
||||
|
||||
variant_base& operator=(const variant_base& other) noexcept(etl::conjunction<etl::is_nothrow_copy_constructible<TTypes>...>::value
|
||||
&& etl::conjunction<etl::is_nothrow_copy_assignable<TTypes>...>::value)
|
||||
variant_trivially_destructible_base&
|
||||
operator=(const variant_trivially_destructible_base& other) noexcept(etl::conjunction<etl::is_nothrow_copy_constructible<TTypes>...>::value
|
||||
&& etl::conjunction<etl::is_nothrow_copy_assignable<TTypes>...>::value)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
copy_assign_from(other, is_all_trivially_copyable{});
|
||||
copy_assign_from(other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
variant_base& operator=(variant_base&& other) noexcept(etl::conjunction<etl::is_nothrow_move_constructible<TTypes>...>::value
|
||||
&& etl::conjunction<etl::is_nothrow_move_assignable<TTypes>...>::value)
|
||||
variant_trivially_destructible_base&
|
||||
operator=(variant_trivially_destructible_base&& other) noexcept(etl::conjunction<etl::is_nothrow_move_constructible<TTypes>...>::value
|
||||
&& etl::conjunction<etl::is_nothrow_move_assignable<TTypes>...>::value)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
move_assign_from(other, is_all_trivially_copyable{});
|
||||
move_assign_from(other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~variant_base() = default;
|
||||
~variant_trivially_destructible_base() = default;
|
||||
|
||||
private:
|
||||
|
||||
// All alternatives trivially copyable => a raw-byte copy correctly
|
||||
// reproduces both copy and move construction.
|
||||
typedef etl::integral_constant<bool, etl::conjunction<etl::is_trivially_copyable<TTypes>...>::value> is_all_trivially_copyable;
|
||||
|
||||
//*******************************************
|
||||
// Trivially copyable fast path: raw-byte copy.
|
||||
// Dispatch to the active alternative's own copy/move operations.
|
||||
// The active union member shares its address with the union, so the
|
||||
// raw-pointer dispatch places the new object in the correct storage.
|
||||
//*******************************************
|
||||
void copy_construct_from(const variant_base& other, etl::true_type) noexcept
|
||||
{
|
||||
memcpy(static_cast<void*>(&data), static_cast<const void*>(&other.data), sizeof(data));
|
||||
}
|
||||
|
||||
void move_construct_from(const variant_base& other, etl::true_type) noexcept
|
||||
{
|
||||
memcpy(static_cast<void*>(&data), static_cast<const void*>(&other.data), sizeof(data));
|
||||
}
|
||||
|
||||
void copy_assign_from(const variant_base& other, etl::true_type) noexcept
|
||||
{
|
||||
type_id = other.type_id;
|
||||
memcpy(static_cast<void*>(&data), static_cast<const void*>(&other.data), sizeof(data));
|
||||
}
|
||||
|
||||
void move_assign_from(const variant_base& other, etl::true_type) noexcept
|
||||
{
|
||||
type_id = other.type_id;
|
||||
memcpy(static_cast<void*>(&data), static_cast<const void*>(&other.data), sizeof(data));
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
// Non-trivial path: dispatch to the active alternative's own
|
||||
// copy/move constructor. The active union member shares its address
|
||||
// with the union, so the raw-pointer dispatch places the new object
|
||||
// in the correct storage.
|
||||
//*******************************************
|
||||
void copy_construct_from(const variant_base& other, etl::false_type)
|
||||
void copy_construct_from(const variant_trivially_destructible_base& other)
|
||||
{
|
||||
if (other.type_id != variant_npos)
|
||||
{
|
||||
@ -669,7 +669,7 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
void move_construct_from(variant_base& other, etl::false_type)
|
||||
void move_construct_from(variant_trivially_destructible_base& other)
|
||||
{
|
||||
if (other.type_id != variant_npos)
|
||||
{
|
||||
@ -677,7 +677,7 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
void copy_assign_from(const variant_base& other, etl::false_type)
|
||||
void copy_assign_from(const variant_trivially_destructible_base& other)
|
||||
{
|
||||
if ((type_id != variant_npos) && (type_id == other.type_id))
|
||||
{
|
||||
@ -698,7 +698,7 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
void move_assign_from(variant_base& other, etl::false_type)
|
||||
void move_assign_from(variant_trivially_destructible_base& other)
|
||||
{
|
||||
if ((type_id != variant_npos) && (type_id == other.type_id))
|
||||
{
|
||||
@ -720,6 +720,76 @@ namespace etl
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Specialisation for when all of the types are trivially copyable.
|
||||
/// All of the copy and move operations are defaulted, so that they are
|
||||
/// trivial and the variant itself is trivially copyable. See P0602R4.
|
||||
//***************************************************************************
|
||||
template <typename... TTypes>
|
||||
struct variant_trivially_destructible_base<true, TTypes...>
|
||||
{
|
||||
variadic_union<TTypes...> data;
|
||||
size_t type_id;
|
||||
|
||||
constexpr variant_trivially_destructible_base() noexcept
|
||||
: data()
|
||||
, type_id(variant_npos)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr variant_trivially_destructible_base(size_t id) noexcept
|
||||
: data()
|
||||
, type_id(id)
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t Index, typename T>
|
||||
constexpr variant_trivially_destructible_base(etl::in_place_index_t<Index>, T&& value,
|
||||
size_t id) noexcept(etl::is_nothrow_constructible<etl::nth_type_t<Index, TTypes...>, T>::value)
|
||||
: data(etl::in_place_index_t<Index>{}, etl::forward<T>(value))
|
||||
, type_id(id)
|
||||
{
|
||||
}
|
||||
|
||||
variant_trivially_destructible_base(const variant_trivially_destructible_base&) = default;
|
||||
variant_trivially_destructible_base(variant_trivially_destructible_base&&) = default;
|
||||
variant_trivially_destructible_base& operator=(const variant_trivially_destructible_base&) = default;
|
||||
variant_trivially_destructible_base& operator=(variant_trivially_destructible_base&&) = default;
|
||||
~variant_trivially_destructible_base() = default;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// variant_base specialisation for trivially destructible types.
|
||||
/// Uses variadic_union storage. Destructor is trivial (defaulted), making
|
||||
/// the variant a literal type eligible for constexpr / ROM placement.
|
||||
/// No operation function pointer is needed since destroy/copy/move are
|
||||
/// all handled without indirection for trivially destructible types.
|
||||
/// The copy and move operations are inherited so that they are trivial
|
||||
/// when every alternative is trivially copyable.
|
||||
//***************************************************************************
|
||||
template <typename... TTypes>
|
||||
struct variant_base<true, TTypes...> : public variant_trivially_destructible_base<are_all_trivially_copyable<TTypes...>::value, TTypes...>
|
||||
{
|
||||
typedef variant_trivially_destructible_base<are_all_trivially_copyable<TTypes...>::value, TTypes...> base_t;
|
||||
|
||||
constexpr variant_base() noexcept
|
||||
: base_t()
|
||||
{
|
||||
}
|
||||
|
||||
constexpr variant_base(size_t id) noexcept
|
||||
: base_t(id)
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t Index, typename T>
|
||||
constexpr variant_base(etl::in_place_index_t<Index>, T&& value,
|
||||
size_t id) noexcept(etl::is_nothrow_constructible<etl::nth_type_t<Index, TTypes...>, T>::value)
|
||||
: base_t(etl::in_place_index_t<Index>{}, etl::forward<T>(value), id)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//*******************************************
|
||||
/// Trait: are all types copy constructible?
|
||||
//*******************************************
|
||||
|
||||
@ -53,14 +53,74 @@ SOFTWARE.
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE)
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE)
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_DESTRUCTIBLE)
|
||||
#define ETL_USING_BUILTIN_IS_DESTRUCTIBLE 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_NOTHROW_DESTRUCTIBLE)
|
||||
#define ETL_USING_BUILTIN_IS_NOTHROW_DESTRUCTIBLE 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE)
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_STANDARD_LAYOUT)
|
||||
#define ETL_USING_BUILTIN_IS_STANDARD_LAYOUT 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_TRIVIAL)
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIAL 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE)
|
||||
#define ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF)
|
||||
#define ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_UNION)
|
||||
#define ETL_USING_BUILTIN_IS_UNION 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_EMPTY)
|
||||
#define ETL_USING_BUILTIN_IS_EMPTY 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_POLYMORPHIC)
|
||||
#define ETL_USING_BUILTIN_IS_POLYMORPHIC 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_ABSTRACT)
|
||||
#define ETL_USING_BUILTIN_IS_ABSTRACT 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_FINAL)
|
||||
#define ETL_USING_BUILTIN_IS_FINAL 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_AGGREGATE)
|
||||
#define ETL_USING_BUILTIN_IS_AGGREGATE 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR)
|
||||
#define ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS)
|
||||
#define ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_UNDERLYING_TYPE)
|
||||
#define ETL_USING_BUILTIN_UNDERLYING_TYPE 1
|
||||
#endif
|
||||
@ -120,14 +180,74 @@ SOFTWARE.
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE (__has_builtin(__has_trivial_constructor) || __has_builtin(__is_trivially_constructible))
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE)
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE __has_builtin(__is_trivially_assignable)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE)
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE (__has_builtin(__has_trivial_destructor) || __has_builtin(__is_trivially_destructible))
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_DESTRUCTIBLE)
|
||||
#define ETL_USING_BUILTIN_IS_DESTRUCTIBLE __has_builtin(__is_destructible)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_NOTHROW_DESTRUCTIBLE)
|
||||
#define ETL_USING_BUILTIN_IS_NOTHROW_DESTRUCTIBLE __has_builtin(__is_nothrow_destructible)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE)
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE (__has_builtin(__has_trivial_copy) || __has_builtin(__is_trivially_copyable))
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_STANDARD_LAYOUT)
|
||||
#define ETL_USING_BUILTIN_IS_STANDARD_LAYOUT __has_builtin(__is_standard_layout)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_TRIVIAL)
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIAL __has_builtin(__is_trivial)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE)
|
||||
#define ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE __has_builtin(__is_layout_compatible)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF)
|
||||
#define ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF __has_builtin(__is_pointer_interconvertible_base_of)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_UNION)
|
||||
#define ETL_USING_BUILTIN_IS_UNION __has_builtin(__is_union)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_EMPTY)
|
||||
#define ETL_USING_BUILTIN_IS_EMPTY __has_builtin(__is_empty)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_POLYMORPHIC)
|
||||
#define ETL_USING_BUILTIN_IS_POLYMORPHIC __has_builtin(__is_polymorphic)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_ABSTRACT)
|
||||
#define ETL_USING_BUILTIN_IS_ABSTRACT __has_builtin(__is_abstract)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_FINAL)
|
||||
#define ETL_USING_BUILTIN_IS_FINAL __has_builtin(__is_final)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_AGGREGATE)
|
||||
#define ETL_USING_BUILTIN_IS_AGGREGATE __has_builtin(__is_aggregate)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR)
|
||||
#define ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR __has_builtin(__has_virtual_destructor)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS)
|
||||
#define ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS __has_builtin(__has_unique_object_representations)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_UNDERLYING_TYPE)
|
||||
#define ETL_USING_BUILTIN_UNDERLYING_TYPE __has_builtin(__underlying_type)
|
||||
#endif
|
||||
@ -136,6 +256,10 @@ SOFTWARE.
|
||||
#define ETL_USING_BUILTIN_IS_CONSTANT_EVALUATED __has_builtin(__builtin_is_constant_evaluated)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_CONSTANT_P)
|
||||
#define ETL_USING_BUILTIN_CONSTANT_P __has_builtin(__builtin_constant_p)
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_BIT_CAST)
|
||||
#define ETL_USING_BUILTIN_BIT_CAST __has_builtin(__builtin_bit_cast)
|
||||
#endif
|
||||
@ -183,6 +307,50 @@ SOFTWARE.
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE)
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_STANDARD_LAYOUT)
|
||||
#define ETL_USING_BUILTIN_IS_STANDARD_LAYOUT 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_TRIVIAL)
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIAL 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_UNION)
|
||||
#define ETL_USING_BUILTIN_IS_UNION 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_EMPTY)
|
||||
#define ETL_USING_BUILTIN_IS_EMPTY 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_POLYMORPHIC)
|
||||
#define ETL_USING_BUILTIN_IS_POLYMORPHIC 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_ABSTRACT)
|
||||
#define ETL_USING_BUILTIN_IS_ABSTRACT 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_FINAL)
|
||||
#define ETL_USING_BUILTIN_IS_FINAL 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_AGGREGATE)
|
||||
#define ETL_USING_BUILTIN_IS_AGGREGATE 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR)
|
||||
#define ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS)
|
||||
#define ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS 1
|
||||
#endif
|
||||
|
||||
// MSVC has supported __builtin_bit_cast since VS2019 16.6. __has_builtin is not
|
||||
// used for Microsoft (see above) to avoid a VS2022 intellisense issue, so the
|
||||
// intrinsic is enabled here directly for the no-STL configuration.
|
||||
@ -212,14 +380,74 @@ SOFTWARE.
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE)
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE)
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_DESTRUCTIBLE)
|
||||
#define ETL_USING_BUILTIN_IS_DESTRUCTIBLE 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_NOTHROW_DESTRUCTIBLE)
|
||||
#define ETL_USING_BUILTIN_IS_NOTHROW_DESTRUCTIBLE 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE)
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_STANDARD_LAYOUT)
|
||||
#define ETL_USING_BUILTIN_IS_STANDARD_LAYOUT 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_TRIVIAL)
|
||||
#define ETL_USING_BUILTIN_IS_TRIVIAL 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE)
|
||||
#define ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF)
|
||||
#define ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_UNION)
|
||||
#define ETL_USING_BUILTIN_IS_UNION 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_EMPTY)
|
||||
#define ETL_USING_BUILTIN_IS_EMPTY 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_POLYMORPHIC)
|
||||
#define ETL_USING_BUILTIN_IS_POLYMORPHIC 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_ABSTRACT)
|
||||
#define ETL_USING_BUILTIN_IS_ABSTRACT 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_FINAL)
|
||||
#define ETL_USING_BUILTIN_IS_FINAL 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_IS_AGGREGATE)
|
||||
#define ETL_USING_BUILTIN_IS_AGGREGATE 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR)
|
||||
#define ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS)
|
||||
#define ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_UNDERLYING_TYPE)
|
||||
#define ETL_USING_BUILTIN_UNDERLYING_TYPE 0
|
||||
#endif
|
||||
@ -260,6 +488,16 @@ SOFTWARE.
|
||||
#define ETL_USING_BUILTIN_BUILTIN_IS_CPP_TRIVIALLY_RELOCATABLE 0
|
||||
#endif
|
||||
|
||||
// __builtin_constant_p predates __has_builtin on GCC and Clang, so enable it for
|
||||
// those compilers when __has_builtin was not available to detect it.
|
||||
#if !defined(ETL_USING_BUILTIN_CONSTANT_P) && (defined(__GNUC__) || defined(__clang__))
|
||||
#define ETL_USING_BUILTIN_CONSTANT_P 1
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_CONSTANT_P)
|
||||
#define ETL_USING_BUILTIN_CONSTANT_P 0
|
||||
#endif
|
||||
|
||||
#if !defined(ETL_USING_BUILTIN_BIT_CAST)
|
||||
#define ETL_USING_BUILTIN_BIT_CAST 0
|
||||
#endif
|
||||
@ -282,10 +520,12 @@ namespace etl
|
||||
static ETL_CONSTANT bool using_builtin_is_nothrow_constructible = (ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE == 1);
|
||||
static ETL_CONSTANT bool using_builtin_is_nothrow_assignable = (ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE == 1);
|
||||
static ETL_CONSTANT bool using_builtin_is_trivially_constructible = (ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE == 1);
|
||||
static ETL_CONSTANT bool using_builtin_is_trivially_assignable = (ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE == 1);
|
||||
static ETL_CONSTANT bool using_builtin_is_trivially_destructible = (ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE == 1);
|
||||
static ETL_CONSTANT bool using_builtin_is_trivially_copyable = (ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE == 1);
|
||||
static ETL_CONSTANT bool using_builtin_underlying_type = (ETL_USING_BUILTIN_UNDERLYING_TYPE == 1);
|
||||
static ETL_CONSTANT bool using_builtin_is_constant_evaluated = (ETL_USING_BUILTIN_IS_CONSTANT_EVALUATED == 1);
|
||||
static ETL_CONSTANT bool using_builtin_constant_p = (ETL_USING_BUILTIN_CONSTANT_P == 1);
|
||||
static ETL_CONSTANT bool using_builtin_memcpy = (ETL_USING_BUILTIN_MEMCPY == 1);
|
||||
static ETL_CONSTANT bool using_builtin_memmove = (ETL_USING_BUILTIN_MEMMOVE == 1);
|
||||
static ETL_CONSTANT bool using_builtin_memset = (ETL_USING_BUILTIN_MEMSET == 1);
|
||||
|
||||
@ -384,7 +384,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// For a delegate slot type.
|
||||
//*************************************************************************
|
||||
template <typename TSlotType, typename... TArgs>
|
||||
template <typename TSlotType>
|
||||
static typename etl::enable_if_t<etl::is_delegate<TSlotType>::value, bool> slot_is_valid(const TSlotType& s) ETL_NOEXCEPT
|
||||
{
|
||||
return s.is_valid();
|
||||
@ -393,7 +393,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// For a non-delegate slot type.
|
||||
//*************************************************************************
|
||||
template <typename TSlotType, typename... TArgs>
|
||||
template <typename TSlotType>
|
||||
static typename etl::enable_if_t<!etl::is_delegate<TSlotType>::value, bool> slot_is_valid(const TSlotType&) ETL_NOEXCEPT
|
||||
{
|
||||
return true;
|
||||
|
||||
@ -425,18 +425,28 @@ namespace etl
|
||||
|
||||
//*************************************************************************
|
||||
/// Shrinks the view by moving its start forward.
|
||||
/// When n >= size(), the view is set to empty.
|
||||
//*************************************************************************
|
||||
ETL_CONSTEXPR14 void remove_prefix(size_type n) ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR14 void remove_prefix(size_type n)
|
||||
{
|
||||
mbegin += n;
|
||||
ETL_ASSERT(n <= size(), ETL_ERROR(string_view_bounds));
|
||||
if (n < size())
|
||||
mbegin += n;
|
||||
else
|
||||
mbegin = mend;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Shrinks the view by moving its end backward.
|
||||
/// When n >= size(), the view is set to empty.
|
||||
//*************************************************************************
|
||||
ETL_CONSTEXPR14 void remove_suffix(size_type n) ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR14 void remove_suffix(size_type n)
|
||||
{
|
||||
mend -= n;
|
||||
ETL_ASSERT(n <= size(), ETL_ERROR(string_view_bounds));
|
||||
if (n < size())
|
||||
mend -= n;
|
||||
else
|
||||
mend = mbegin;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
@ -713,7 +713,9 @@ namespace etl
|
||||
const uvalue_t uvalue = static_cast<uvalue_t>(accumulator_result.value());
|
||||
|
||||
// Convert from the accumulator type to the desired type.
|
||||
result = (is_negative ? static_cast<TValue>(static_cast<TValue>(0) - static_cast<TValue>(uvalue)) : etl::bit_cast<TValue>(uvalue));
|
||||
// The negation is performed on the unsigned type to avoid signed overflow
|
||||
// when the value is the most negative value for the type.
|
||||
result = (is_negative ? etl::bit_cast<TValue>(static_cast<uvalue_t>(static_cast<uvalue_t>(0) - uvalue)) : etl::bit_cast<TValue>(uvalue));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -908,7 +910,7 @@ ETL_CONSTEXPR14 bool operator==(const etl::to_arithmetic_result<T>& lhs, const e
|
||||
}
|
||||
else
|
||||
{
|
||||
return (lhs.status() == rhs.status());
|
||||
return (lhs.error() == rhs.error());
|
||||
}
|
||||
}
|
||||
|
||||
@ -952,7 +954,7 @@ ETL_CONSTEXPR14 bool operator!=(const etl::to_arithmetic_result<T>& lhs, const U
|
||||
/// Inequality test for etl::to_arithmetic_result
|
||||
//***************************************************************************
|
||||
template <typename T, typename U>
|
||||
ETL_CONSTEXPR14 bool operator!=(const T& lhs, const etl::to_arithmetic_result<T>& rhs)
|
||||
ETL_CONSTEXPR14 bool operator!=(const T& lhs, const etl::to_arithmetic_result<U>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -340,7 +340,31 @@ namespace etl
|
||||
// We can't have std::swap and etl::swap templates coexisting in the unit
|
||||
// tests as the compiler will be unable to decide which one to use, due to
|
||||
// ADL.
|
||||
// These are declared in type_traits.h, so that etl::is_swappable can find
|
||||
// them, and defined here.
|
||||
#if ETL_NOT_USING_STL && !defined(ETL_IN_UNIT_TEST)
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
// swap
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14 typename etl::enable_if<etl::is_move_constructible<T>::value && etl::is_move_assignable<T>::value>::type swap(T& a, T& b)
|
||||
ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value&& etl::is_nothrow_move_assignable<T>::value)
|
||||
{
|
||||
T temp(ETL_MOVE(a));
|
||||
a = ETL_MOVE(b);
|
||||
b = ETL_MOVE(temp);
|
||||
}
|
||||
|
||||
template <typename T, size_t Size>
|
||||
ETL_CONSTEXPR14 typename etl::enable_if<private_type_traits::is_swappable_helper<T>::value>::type swap(T (&a)[Size], T (&b)[Size])
|
||||
ETL_NOEXCEPT_IF(private_type_traits::is_nothrow_swappable_helper<T>::value)
|
||||
{
|
||||
for (size_t i = 0UL; i < Size; ++i)
|
||||
{
|
||||
swap(a[i], b[i]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
//***************************************************************************
|
||||
// swap
|
||||
template <typename T>
|
||||
@ -351,7 +375,7 @@ namespace etl
|
||||
b = ETL_MOVE(temp);
|
||||
}
|
||||
|
||||
template < class T, size_t Size >
|
||||
template <typename T, size_t Size>
|
||||
ETL_CONSTEXPR14 void swap(T (&a)[Size], T (&b)[Size]) ETL_NOEXCEPT
|
||||
{
|
||||
for (size_t i = 0UL; i < Size; ++i)
|
||||
@ -359,6 +383,7 @@ namespace etl
|
||||
swap(a[i], b[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
@ -1999,10 +1999,14 @@ namespace etl
|
||||
/// Make
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
|
||||
template <typename... T>
|
||||
constexpr auto make_vector(T&&... t) -> etl::vector<typename etl::common_type_t<T...>, sizeof...(T)>
|
||||
template <typename T = void, typename... TValues>
|
||||
constexpr auto make_vector(TValues&&... values) -> etl::vector<etl::private_make::element_type_t<T, TValues...>, sizeof...(TValues)>
|
||||
{
|
||||
return {etl::forward<T>(t)...};
|
||||
// Library Fundamentals TS make_array design: the element type is T when
|
||||
// supplied explicitly, otherwise the decayed common type of the arguments.
|
||||
// convert forwards same-type arguments and static_casts the rest.
|
||||
using TElement = etl::private_make::element_type_t<T, TValues...>;
|
||||
return {etl::private_make::convert<TElement>(etl::forward<TValues>(values))...};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -77,7 +77,7 @@ namespace
|
||||
CHECK_EQUAL(data.max_size(), 0);
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST && !defined(ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED)
|
||||
#if ETL_USING_CPP17 && !defined(ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED)
|
||||
//*************************************************************************
|
||||
TEST(test_cpp17_deduced_constructor)
|
||||
{
|
||||
@ -861,7 +861,7 @@ namespace
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST && !defined(ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED)
|
||||
#if ETL_USING_CPP17 && !defined(ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED)
|
||||
TEST(test_array_template_deduction)
|
||||
{
|
||||
etl::array data{char(0), short(1), 2, long(3), 4, 5, 6, 7, 8, 9};
|
||||
@ -883,7 +883,7 @@ namespace
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST
|
||||
#if ETL_USING_CPP17
|
||||
TEST(test_array_template_deduction_for_movable)
|
||||
{
|
||||
etl::array data{Moveable(0), Moveable(1), Moveable(2), Moveable(3), Moveable(4),
|
||||
@ -906,7 +906,7 @@ namespace
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_HAS_INITIALIZER_LIST
|
||||
#if ETL_USING_CPP11
|
||||
TEST(test_make_array)
|
||||
{
|
||||
auto data = etl::make_array<char>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
@ -928,7 +928,7 @@ namespace
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_HAS_INITIALIZER_LIST
|
||||
#if ETL_USING_CPP11
|
||||
TEST(test_make_array_for_movable)
|
||||
{
|
||||
auto data = etl::make_array<Moveable>(Moveable(0), Moveable(1), Moveable(2), Moveable(3), Moveable(4), Moveable(5), Moveable(6), Moveable(7),
|
||||
@ -951,7 +951,7 @@ namespace
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_HAS_INITIALIZER_LIST
|
||||
#if ETL_USING_CPP11
|
||||
// Arguments that are const-qualified lvalues of the element type used to be rejected:
|
||||
// the old implementation forwarded each argument as T, and forward<T> cannot accept a
|
||||
// const T lvalue (it requires a non-const T&, and T&& cannot bind to a reference-related
|
||||
@ -974,7 +974,7 @@ namespace
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_HAS_INITIALIZER_LIST
|
||||
#if ETL_USING_CPP11
|
||||
// The arguments are converted to the element type with static_cast, so narrowing
|
||||
// initialisers (int literals and int lvalues narrowed to char) must keep working.
|
||||
// Plain forwarding into the braced initialiser list would reject them.
|
||||
@ -998,7 +998,74 @@ namespace
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_HAS_INITIALIZER_LIST && ETL_USING_CPP14
|
||||
#if ETL_USING_CPP11
|
||||
// With no explicit element type, the element type is deduced as the
|
||||
// decayed common type of the arguments (Library Fundamentals TS
|
||||
// make_array design).
|
||||
TEST(test_make_array_deduced_element_type)
|
||||
{
|
||||
static const int static_const_lvalue = 1;
|
||||
|
||||
auto data = etl::make_array(static_const_lvalue, 2L, 3);
|
||||
|
||||
CHECK((std::is_same<etl::array<long, 3U>, decltype(data)>::value));
|
||||
|
||||
CHECK_EQUAL(1L, data[0]);
|
||||
CHECK_EQUAL(2L, data[1]);
|
||||
CHECK_EQUAL(3L, data[2]);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
// An empty array requires the element type to be supplied explicitly.
|
||||
// etl::make_array() with no element type and no arguments is ill-formed,
|
||||
// as in the Library Fundamentals TS: there is nothing to deduce the
|
||||
// element type from.
|
||||
TEST(test_make_array_empty)
|
||||
{
|
||||
auto data = etl::make_array<int>();
|
||||
|
||||
CHECK((std::is_same<etl::array<int, 0U>, decltype(data)>::value));
|
||||
CHECK_TRUE(data.empty());
|
||||
CHECK_EQUAL(0U, data.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
// Arguments that already have the element type are forwarded rather than
|
||||
// cast. Casting created a prvalue that, before C++17, had to be
|
||||
// materialised through the move constructor, so a copyable type with a
|
||||
// deleted move constructor was rejected.
|
||||
TEST(test_make_array_for_copyable_non_movable)
|
||||
{
|
||||
struct NonMovable
|
||||
{
|
||||
explicit NonMovable(int v_)
|
||||
: v(v_)
|
||||
{
|
||||
}
|
||||
NonMovable(const NonMovable&) = default;
|
||||
NonMovable(NonMovable&&) = delete;
|
||||
int v;
|
||||
};
|
||||
|
||||
NonMovable mutable_lvalue(1);
|
||||
const NonMovable const_lvalue(2);
|
||||
|
||||
auto data = etl::make_array<NonMovable>(mutable_lvalue, const_lvalue);
|
||||
|
||||
using Type = etl::remove_reference_t<decltype(data[0])>;
|
||||
CHECK((std::is_same<NonMovable, Type>::value));
|
||||
|
||||
CHECK_EQUAL(1, data[0].v);
|
||||
CHECK_EQUAL(2, data[1].v);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP14
|
||||
TEST(test_make_array_is_constexpr)
|
||||
{
|
||||
static constexpr unsigned char constexpr_value = 0x18U;
|
||||
|
||||
@ -67,6 +67,123 @@ namespace
|
||||
CHECK(data.crbegin() == data.crend());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constructor_with_size)
|
||||
{
|
||||
etl::circular_buffer<int, SIZE> data(5U);
|
||||
|
||||
CHECK_EQUAL(5U, data.size());
|
||||
CHECK(std::all_of(data.begin(), data.end(), [](int value) { return value == 0; }));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constructor_with_excess_size)
|
||||
{
|
||||
etl::circular_buffer<int, SIZE> data(SIZE + 3U);
|
||||
|
||||
CHECK(data.full());
|
||||
CHECK_EQUAL(SIZE, data.size());
|
||||
CHECK(std::all_of(data.begin(), data.end(), [](int value) { return value == 0; }));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constructor_with_size_and_value)
|
||||
{
|
||||
const Ndc value("value");
|
||||
Data data(5U, value);
|
||||
|
||||
CHECK_EQUAL(5U, data.size());
|
||||
CHECK(std::all_of(data.begin(), data.end(), [&value](const Ndc& item) { return item == value; }));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constructor_with_excess_size_and_value)
|
||||
{
|
||||
const Ndc value("value");
|
||||
Data data(SIZE + 3U, value);
|
||||
|
||||
CHECK(data.full());
|
||||
CHECK_EQUAL(SIZE, data.size());
|
||||
CHECK(std::all_of(data.begin(), data.end(), [&value](const Ndc& item) { return item == value; }));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_assign_size_and_value)
|
||||
{
|
||||
Data data;
|
||||
data.push(Ndc("old"));
|
||||
|
||||
const Ndc value("value");
|
||||
data.assign(5U, value);
|
||||
|
||||
CHECK_EQUAL(5U, data.size());
|
||||
CHECK(std::all_of(data.begin(), data.end(), [&value](const Ndc& item) { return item == value; }));
|
||||
|
||||
data.assign(0U, value);
|
||||
CHECK(data.empty());
|
||||
|
||||
data.assign(SIZE + 3U, value);
|
||||
CHECK(data.full());
|
||||
CHECK_EQUAL(SIZE, data.size());
|
||||
CHECK(std::all_of(data.begin(), data.end(), [&value](const Ndc& item) { return item == value; }));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_assign_range)
|
||||
{
|
||||
Compare input{Ndc("0"), Ndc("1"), Ndc("2"), Ndc("3"), Ndc("4"), Ndc("5"), Ndc("6"),
|
||||
Ndc("7"), Ndc("8"), Ndc("9"), Ndc("10"), Ndc("11"), Ndc("12")};
|
||||
Compare expected(input.end() - SIZE, input.end());
|
||||
Data data;
|
||||
data.push(Ndc("old"));
|
||||
|
||||
data.assign(input.begin(), input.end());
|
||||
|
||||
CHECK(data.full());
|
||||
CHECK_EQUAL(expected.size(), data.size());
|
||||
CHECK(std::equal(expected.begin(), expected.end(), data.begin()));
|
||||
|
||||
data.assign(input.begin(), input.begin());
|
||||
CHECK(data.empty());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_assign_self_range)
|
||||
{
|
||||
Compare input{Ndc("0"), Ndc("1"), Ndc("2"), Ndc("3"), Ndc("4"), Ndc("5"), Ndc("6"),
|
||||
Ndc("7"), Ndc("8"), Ndc("9"), Ndc("10"), Ndc("11"), Ndc("12")};
|
||||
Compare expected(input.end() - SIZE, input.end());
|
||||
Data data(input.begin(), input.end());
|
||||
|
||||
data.assign(data.begin(), data.end());
|
||||
|
||||
CHECK(data.full());
|
||||
CHECK_EQUAL(expected.size(), data.size());
|
||||
CHECK(std::equal(expected.begin(), expected.end(), data.begin()));
|
||||
|
||||
Data::const_iterator first = data.cbegin() + 2;
|
||||
Data::const_iterator last = data.cend() - 2;
|
||||
Compare partial_expected(expected.begin() + 2, expected.end() - 2);
|
||||
|
||||
data.assign(first, last);
|
||||
|
||||
CHECK_EQUAL(partial_expected.size(), data.size());
|
||||
CHECK(std::equal(partial_expected.begin(), partial_expected.end(), data.begin()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_assign_aliased_value)
|
||||
{
|
||||
Compare input{Ndc("0"), Ndc("1"), Ndc("2"), Ndc("3"), Ndc("4")};
|
||||
Data data(input.begin(), input.end());
|
||||
|
||||
const Ndc expected(data.front());
|
||||
data.assign(7U, data.front());
|
||||
|
||||
CHECK_EQUAL(7U, data.size());
|
||||
CHECK(std::all_of(data.begin(), data.end(), [&expected](const Ndc& item) { return item == expected; }));
|
||||
}
|
||||
|
||||
#if ETL_HAS_INITIALIZER_LIST
|
||||
//*************************************************************************
|
||||
TEST(test_constructor_from_literal)
|
||||
|
||||
@ -78,6 +78,131 @@ namespace
|
||||
CHECK(data.crbegin() == data.crend());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constructor_with_size)
|
||||
{
|
||||
etl::uninitialized_buffer_of<int, SIZE + 1> buffer1;
|
||||
etl::circular_buffer_ext<int> data(5U, buffer1.raw, SIZE);
|
||||
|
||||
CHECK_EQUAL(5U, data.size());
|
||||
CHECK(std::all_of(data.begin(), data.end(), [](int value) { return value == 0; }));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constructor_with_excess_size)
|
||||
{
|
||||
etl::uninitialized_buffer_of<int, SIZE + 1> buffer1;
|
||||
etl::circular_buffer_ext<int> data(SIZE + 3U, buffer1.raw, SIZE);
|
||||
|
||||
CHECK(data.full());
|
||||
CHECK_EQUAL(SIZE, data.size());
|
||||
CHECK(std::all_of(data.begin(), data.end(), [](int value) { return value == 0; }));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constructor_with_size_and_value)
|
||||
{
|
||||
Buffer_t buffer1;
|
||||
const Ndc value("value");
|
||||
Data data(5U, value, buffer1.raw, SIZE);
|
||||
|
||||
CHECK_EQUAL(5U, data.size());
|
||||
CHECK(std::all_of(data.begin(), data.end(), [&value](const Ndc& item) { return item == value; }));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constructor_with_excess_size_and_value)
|
||||
{
|
||||
Buffer_t buffer1;
|
||||
const Ndc value("value");
|
||||
Data data(SIZE + 3U, value, buffer1.raw, SIZE);
|
||||
|
||||
CHECK(data.full());
|
||||
CHECK_EQUAL(SIZE, data.size());
|
||||
CHECK(std::all_of(data.begin(), data.end(), [&value](const Ndc& item) { return item == value; }));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_assign_size_and_value)
|
||||
{
|
||||
Buffer_t buffer1;
|
||||
Data data(buffer1.raw, SIZE);
|
||||
data.push(Ndc("old"));
|
||||
|
||||
const Ndc value("value");
|
||||
data.assign(5U, value);
|
||||
|
||||
CHECK_EQUAL(5U, data.size());
|
||||
CHECK(std::all_of(data.begin(), data.end(), [&value](const Ndc& item) { return item == value; }));
|
||||
|
||||
data.assign(0U, value);
|
||||
CHECK(data.empty());
|
||||
|
||||
data.assign(SIZE + 3U, value);
|
||||
CHECK(data.full());
|
||||
CHECK_EQUAL(SIZE, data.size());
|
||||
CHECK(std::all_of(data.begin(), data.end(), [&value](const Ndc& item) { return item == value; }));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_assign_range)
|
||||
{
|
||||
Buffer_t buffer1;
|
||||
Compare input{Ndc("0"), Ndc("1"), Ndc("2"), Ndc("3"), Ndc("4"), Ndc("5"), Ndc("6"),
|
||||
Ndc("7"), Ndc("8"), Ndc("9"), Ndc("10"), Ndc("11"), Ndc("12")};
|
||||
Compare expected(input.end() - SIZE, input.end());
|
||||
Data data(buffer1.raw, SIZE);
|
||||
data.push(Ndc("old"));
|
||||
|
||||
data.assign(input.begin(), input.end());
|
||||
|
||||
CHECK(data.full());
|
||||
CHECK_EQUAL(expected.size(), data.size());
|
||||
CHECK(std::equal(expected.begin(), expected.end(), data.begin()));
|
||||
|
||||
data.assign(input.begin(), input.begin());
|
||||
CHECK(data.empty());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_assign_self_range)
|
||||
{
|
||||
Buffer_t buffer1;
|
||||
Compare input{Ndc("0"), Ndc("1"), Ndc("2"), Ndc("3"), Ndc("4"), Ndc("5"), Ndc("6"),
|
||||
Ndc("7"), Ndc("8"), Ndc("9"), Ndc("10"), Ndc("11"), Ndc("12")};
|
||||
Compare expected(input.end() - SIZE, input.end());
|
||||
Data data(input.begin(), input.end(), buffer1.raw, SIZE);
|
||||
|
||||
data.assign(data.begin(), data.end());
|
||||
|
||||
CHECK(data.full());
|
||||
CHECK_EQUAL(expected.size(), data.size());
|
||||
CHECK(std::equal(expected.begin(), expected.end(), data.begin()));
|
||||
|
||||
Data::const_iterator first = data.cbegin() + 2;
|
||||
Data::const_iterator last = data.cend() - 2;
|
||||
Compare partial_expected(expected.begin() + 2, expected.end() - 2);
|
||||
|
||||
data.assign(first, last);
|
||||
|
||||
CHECK_EQUAL(partial_expected.size(), data.size());
|
||||
CHECK(std::equal(partial_expected.begin(), partial_expected.end(), data.begin()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_assign_aliased_value)
|
||||
{
|
||||
Buffer_t buffer1;
|
||||
Compare input{Ndc("0"), Ndc("1"), Ndc("2"), Ndc("3"), Ndc("4")};
|
||||
Data data(input.begin(), input.end(), buffer1.raw, SIZE);
|
||||
|
||||
const Ndc expected(data.front());
|
||||
data.assign(7U, data.front());
|
||||
|
||||
CHECK_EQUAL(7U, data.size());
|
||||
CHECK(std::all_of(data.begin(), data.end(), [&expected](const Ndc& item) { return item == expected; }));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_set_buffer_after_default_constructor)
|
||||
{
|
||||
|
||||
@ -2183,6 +2183,65 @@ namespace
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
//*************************************************************************
|
||||
// Verify that copy assigning a delegate, and comparing against a default
|
||||
// constructed one, are usable in a constant expression.
|
||||
//*************************************************************************
|
||||
TEST(test_constexpr_copy_assignment_and_clear)
|
||||
{
|
||||
using delegate_type = etl::delegate<void(void)>;
|
||||
|
||||
// Copy assignment from a bound delegate.
|
||||
constexpr auto copy_assigned = []() constexpr
|
||||
{
|
||||
const delegate_type source(&free_void);
|
||||
delegate_type d;
|
||||
d = source;
|
||||
return d;
|
||||
};
|
||||
|
||||
constexpr delegate_type d1 = copy_assigned();
|
||||
|
||||
static_assert(d1.is_valid(), "a copy assigned delegate should be valid");
|
||||
static_assert(d1 == delegate_type(&free_void), "a copy assigned delegate should compare equal to its source");
|
||||
|
||||
// Copy assignment from a default constructed delegate, and comparing an
|
||||
// unbound delegate against another one. Neither may inspect the null stub
|
||||
// pointer, which the undefined behaviour sanitizer makes non-constant.
|
||||
constexpr auto cleared = []() constexpr
|
||||
{
|
||||
delegate_type d(&free_void);
|
||||
d = delegate_type();
|
||||
return d;
|
||||
};
|
||||
|
||||
constexpr delegate_type d2 = cleared();
|
||||
|
||||
static_assert(!d2.is_valid(), "a delegate assigned from a default constructed one should be invalid");
|
||||
static_assert(d2 == delegate_type(), "an unbound delegate should compare equal to a default constructed one");
|
||||
static_assert(d2 != d1, "an unbound delegate should not compare equal to a bound one");
|
||||
|
||||
// The same operations must still behave identically at run time.
|
||||
delegate_type d3;
|
||||
d3 = d1;
|
||||
CHECK_TRUE(d3.is_valid());
|
||||
CHECK(d3 == d1);
|
||||
|
||||
d3 = delegate_type();
|
||||
CHECK_FALSE(d3.is_valid());
|
||||
CHECK(d3 == delegate_type());
|
||||
|
||||
// Assigning a null function pointer clears the delegate at run time.
|
||||
// This is deliberately not checked in a constant expression: the null
|
||||
// test cannot be folded there when the sanitizer instruments it.
|
||||
delegate_type d4(&free_void);
|
||||
d4 = static_cast<void (*)()>(ETL_NULLPTR);
|
||||
CHECK_FALSE(d4.is_valid());
|
||||
CHECK(d4 == delegate_type());
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(test_delegate_clear_equals_default_constructed)
|
||||
{
|
||||
using delegate_type = etl::delegate<void(int, int)>;
|
||||
|
||||
@ -2346,6 +2346,25 @@ namespace
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
|
||||
// With no explicit element type, the element type is deduced as the
|
||||
// decayed common type of the arguments (Library Fundamentals TS
|
||||
// make_array design).
|
||||
TEST(test_make_deque_deduced_element_type)
|
||||
{
|
||||
static const int static_const_lvalue = 1;
|
||||
|
||||
auto data = etl::make_deque(static_const_lvalue, 2L, 3);
|
||||
|
||||
CHECK((std::is_same<etl::deque<long, 3U>, decltype(data)>::value));
|
||||
|
||||
CHECK_EQUAL(1L, data[0]);
|
||||
CHECK_EQUAL(2L, data[1]);
|
||||
CHECK_EQUAL(3L, data[2]);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_fill)
|
||||
{
|
||||
@ -2370,9 +2389,10 @@ namespace
|
||||
|
||||
#include "etl/private/diagnostic_uninitialized_push.h"
|
||||
// Verify operator[] returns values matching sequential access
|
||||
for (size_t i = 0; i < cdata.size(); ++i)
|
||||
DataNDC::difference_type it_idx = 0;
|
||||
for (size_t i = 0; i < cdata.size(); ++i, ++it_idx)
|
||||
{
|
||||
CHECK(cit[i] == cdata[i]);
|
||||
CHECK(cit[it_idx] == cdata[i]);
|
||||
}
|
||||
|
||||
// Verify const_iterator operator[] returns const_reference
|
||||
|
||||
@ -1556,6 +1556,30 @@ namespace
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_HAS_INITIALIZER_LIST
|
||||
// An explicit element type selects the element type and converts every
|
||||
// argument (Library Fundamentals TS make_array design), accepting
|
||||
// const-qualified lvalues and narrowing initialisers.
|
||||
TEST(test_make_forward_list_explicit_element_type)
|
||||
{
|
||||
static const char static_const_lvalue = 42;
|
||||
const char local_const_lvalue = 43;
|
||||
char mutable_lvalue = 44;
|
||||
|
||||
auto data = etl::make_forward_list<char>(static_const_lvalue, local_const_lvalue, mutable_lvalue, 45, 46);
|
||||
|
||||
CHECK((std::is_same<etl::forward_list<char, 5U>, decltype(data)>::value));
|
||||
|
||||
auto itr = data.begin();
|
||||
CHECK_EQUAL(42, *itr++);
|
||||
CHECK_EQUAL(43, *itr++);
|
||||
CHECK_EQUAL(44, *itr++);
|
||||
CHECK_EQUAL(45, *itr++);
|
||||
CHECK_EQUAL(46, *itr++);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_forward_list_exception_types)
|
||||
{
|
||||
|
||||
@ -1644,5 +1644,28 @@ namespace
|
||||
CHECK_EQUAL(44, data[2]);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
|
||||
// An explicit element type selects the element type and converts every
|
||||
// argument (Library Fundamentals TS make_array design), accepting
|
||||
// const-qualified lvalues and narrowing initialisers.
|
||||
TEST(test_make_indirect_vector_explicit_element_type)
|
||||
{
|
||||
static const char static_const_lvalue = 42;
|
||||
const char local_const_lvalue = 43;
|
||||
char mutable_lvalue = 44;
|
||||
|
||||
auto data = etl::make_indirect_vector<char>(static_const_lvalue, local_const_lvalue, mutable_lvalue, 45, 46);
|
||||
|
||||
CHECK((std::is_same<etl::indirect_vector<char, 5U>, decltype(data)>::value));
|
||||
|
||||
CHECK_EQUAL(42, data[0]);
|
||||
CHECK_EQUAL(43, data[1]);
|
||||
CHECK_EQUAL(44, data[2]);
|
||||
CHECK_EQUAL(45, data[3]);
|
||||
CHECK_EQUAL(46, data[4]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -29,6 +29,7 @@ SOFTWARE.
|
||||
#include "unit_test_framework.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <forward_list>
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
@ -1420,6 +1421,55 @@ namespace
|
||||
CHECK_EQUAL(1, *result);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
// etl::ranges::distance(first, last)
|
||||
//*************************************************************************
|
||||
TEST(ranges_distance_iterator_sentinel)
|
||||
{
|
||||
int data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
|
||||
CHECK_EQUAL(10, etl::ranges::distance(&data[0], &data[10]));
|
||||
CHECK_EQUAL(4, etl::ranges::distance(&data[3], &data[7]));
|
||||
CHECK_EQUAL(0, etl::ranges::distance(&data[3], &data[3]));
|
||||
|
||||
non_random_iterator<int> first(&data[0]);
|
||||
non_random_sentinel<int> last(&data[6]);
|
||||
CHECK_EQUAL(6, etl::ranges::distance(first, last));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
// etl::ranges::distance(range)
|
||||
//*************************************************************************
|
||||
TEST(ranges_distance_range_with_size_member)
|
||||
{
|
||||
std::vector<int> data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
|
||||
CHECK_EQUAL(10, etl::ranges::distance(data));
|
||||
|
||||
const std::vector<int>& cdata = data;
|
||||
CHECK_EQUAL(10, etl::ranges::distance(cdata));
|
||||
|
||||
std::vector<int> empty_data;
|
||||
CHECK_EQUAL(0, etl::ranges::distance(empty_data));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(ranges_distance_c_array)
|
||||
{
|
||||
int data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
|
||||
CHECK_EQUAL(10, etl::ranges::distance(data));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(ranges_distance_range_without_size_member)
|
||||
{
|
||||
std::forward_list<int> data = {0, 1, 2, 3, 4};
|
||||
|
||||
CHECK_EQUAL(5, etl::ranges::distance(data));
|
||||
CHECK_EQUAL(etl::ranges::distance(data.begin(), data.end()), etl::ranges::distance(data));
|
||||
}
|
||||
|
||||
TEST(test_is_range)
|
||||
{
|
||||
std::vector<int> vec;
|
||||
|
||||
@ -2377,5 +2377,29 @@ namespace
|
||||
CHECK_EQUAL(3, data2.begin()->value);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_HAS_INITIALIZER_LIST
|
||||
// An explicit element type selects the element type and converts every
|
||||
// argument (Library Fundamentals TS make_array design), accepting
|
||||
// const-qualified lvalues and narrowing initialisers.
|
||||
TEST(test_make_list_explicit_element_type)
|
||||
{
|
||||
static const char static_const_lvalue = 42;
|
||||
const char local_const_lvalue = 43;
|
||||
char mutable_lvalue = 44;
|
||||
|
||||
auto data = etl::make_list<char>(static_const_lvalue, local_const_lvalue, mutable_lvalue, 45, 46);
|
||||
|
||||
CHECK((std::is_same<etl::list<char, 5U>, decltype(data)>::value));
|
||||
|
||||
auto itr = data.begin();
|
||||
CHECK_EQUAL(42, *itr++);
|
||||
CHECK_EQUAL(43, *itr++);
|
||||
CHECK_EQUAL(44, *itr++);
|
||||
CHECK_EQUAL(45, *itr++);
|
||||
CHECK_EQUAL(46, *itr++);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -103,6 +103,34 @@ namespace
|
||||
|
||||
return true;
|
||||
}
|
||||
template <typename R1, typename R2>
|
||||
bool Check_Equal(R1 range1, R2 range2)
|
||||
{
|
||||
while (range1.first != range1.second)
|
||||
{
|
||||
if (range2.first == range2.second)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto& pair1 = *range1.first;
|
||||
auto& pair2 = *range2.first;
|
||||
if ((pair1.first != pair2.first) || (pair1.second != pair2.second))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
++range1.first;
|
||||
++range2.first;
|
||||
}
|
||||
|
||||
return range2.first == range2.second;
|
||||
}
|
||||
template <typename T1, typename T2>
|
||||
bool Check_ContainsPair(T1 begin, T1 end, const T2& pair)
|
||||
{
|
||||
return std::find_if(begin, end, [&pair](typename T1::reference item) { return (item.first == pair.first) && (item.second == pair.second); })
|
||||
!= end;
|
||||
}
|
||||
#include "etl/private/diagnostic_null_dereference_push.h"
|
||||
|
||||
//*************************************************************************
|
||||
@ -694,13 +722,7 @@ namespace
|
||||
ETL_OR_STD::pair<Compare_Data::iterator, Compare_Data::iterator> compare_result = compare_data.equal_range("1");
|
||||
|
||||
// Check that both return the same return results
|
||||
CHECK(compare_result.first->first == data_result.first->first);
|
||||
CHECK(compare_result.first->second == data_result.first->second);
|
||||
CHECK(compare_result.second->first == data_result.second->first);
|
||||
CHECK(compare_result.second->second == data_result.second->second);
|
||||
|
||||
bool isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
const bool isEqual = Check_Equal(data_result, compare_result);
|
||||
CHECK(isEqual);
|
||||
}
|
||||
|
||||
@ -718,13 +740,7 @@ namespace
|
||||
ETL_OR_STD::pair<CMap::iterator, CMap::iterator> compare_result = compare_data.equal_range("1");
|
||||
|
||||
// Check that both return the same return results
|
||||
CHECK(compare_result.first->first == data_result.first->first);
|
||||
CHECK(compare_result.first->second == data_result.first->second);
|
||||
CHECK(compare_result.second->first == data_result.second->first);
|
||||
CHECK(compare_result.second->second == data_result.second->second);
|
||||
|
||||
bool isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
const bool isEqual = Check_Equal(data_result, compare_result);
|
||||
CHECK(isEqual);
|
||||
}
|
||||
|
||||
@ -739,13 +755,7 @@ namespace
|
||||
ETL_OR_STD::pair<Compare_Data::const_iterator, Compare_Data::const_iterator> compare_result = compare_data.equal_range("2");
|
||||
|
||||
// Check that both return the same return results
|
||||
CHECK(compare_result.first->first == data_result.first->first);
|
||||
CHECK(compare_result.first->second == data_result.first->second);
|
||||
CHECK(compare_result.second->first == data_result.second->first);
|
||||
CHECK(compare_result.second->second == data_result.second->second);
|
||||
|
||||
bool isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
const bool isEqual = Check_Equal(data_result, compare_result);
|
||||
CHECK(isEqual);
|
||||
}
|
||||
|
||||
@ -763,13 +773,7 @@ namespace
|
||||
ETL_OR_STD::pair<CMap::const_iterator, CMap::const_iterator> compare_result = compare_data.equal_range("2");
|
||||
|
||||
// Check that both return the same return results
|
||||
CHECK(compare_result.first->first == data_result.first->first);
|
||||
CHECK(compare_result.first->second == data_result.first->second);
|
||||
CHECK(compare_result.second->first == data_result.second->first);
|
||||
CHECK(compare_result.second->second == data_result.second->second);
|
||||
|
||||
bool isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
const bool isEqual = Check_Equal(data_result, compare_result);
|
||||
CHECK(isEqual);
|
||||
}
|
||||
|
||||
@ -1022,47 +1026,47 @@ namespace
|
||||
Compare_Data compare_data(initial_data.begin(), initial_data.end());
|
||||
Data data(initial_data.begin(), initial_data.end());
|
||||
|
||||
Data::iterator i_data = data.find("0");
|
||||
Compare_Data::iterator i_compare = compare_data.find("0");
|
||||
Data::iterator i_data = data.find("0");
|
||||
auto i_compare = compare_data.equal_range("0");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find("1");
|
||||
i_compare = compare_data.find("1");
|
||||
i_compare = compare_data.equal_range("1");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find("2");
|
||||
i_compare = compare_data.find("2");
|
||||
i_compare = compare_data.equal_range("2");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find("3");
|
||||
i_compare = compare_data.find("3");
|
||||
i_compare = compare_data.equal_range("3");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find(".");
|
||||
i_compare = compare_data.find(".");
|
||||
i_compare = compare_data.equal_range(".");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(data.end() == i_data);
|
||||
CHECK(compare_data.end() == i_compare);
|
||||
CHECK(i_data == data.end());
|
||||
CHECK(i_compare.first == i_compare.second);
|
||||
|
||||
i_data = data.find("A");
|
||||
i_compare = compare_data.find("A");
|
||||
i_compare = compare_data.equal_range("A");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(data.end() == i_data);
|
||||
CHECK(compare_data.end() == i_compare);
|
||||
CHECK(i_data == data.end());
|
||||
CHECK(i_compare.first == i_compare.second);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -1075,46 +1079,46 @@ namespace
|
||||
CMap compare_data(initial_data.begin(), initial_data.end());
|
||||
|
||||
EMap::iterator i_data = data.find(Key("0"));
|
||||
CMap::iterator i_compare = compare_data.find("0");
|
||||
auto i_compare = compare_data.equal_range("0");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find(Key("1"));
|
||||
i_compare = compare_data.find("1");
|
||||
i_compare = compare_data.equal_range("1");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find(Key("2"));
|
||||
i_compare = compare_data.find("2");
|
||||
i_compare = compare_data.equal_range("2");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find(Key("3"));
|
||||
i_compare = compare_data.find("3");
|
||||
i_compare = compare_data.equal_range("3");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find(Key("."));
|
||||
i_compare = compare_data.find(".");
|
||||
i_compare = compare_data.equal_range(".");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(data.end() == i_data);
|
||||
CHECK(compare_data.end() == i_compare);
|
||||
CHECK(i_data == data.end());
|
||||
CHECK(i_compare.first == i_compare.second);
|
||||
|
||||
i_data = data.find(Key("A"));
|
||||
i_compare = compare_data.find("A");
|
||||
i_compare = compare_data.equal_range("A");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(data.end() == i_data);
|
||||
CHECK(compare_data.end() == i_compare);
|
||||
CHECK(i_data == data.end());
|
||||
CHECK(i_compare.first == i_compare.second);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -1123,47 +1127,47 @@ namespace
|
||||
const Compare_Data compare_data(initial_data.begin(), initial_data.end());
|
||||
const Data data(initial_data.begin(), initial_data.end());
|
||||
|
||||
Data::const_iterator i_data = data.find("0");
|
||||
Compare_Data::const_iterator i_compare = compare_data.find("0");
|
||||
Data::const_iterator i_data = data.find("0");
|
||||
auto i_compare = compare_data.equal_range("0");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find("1");
|
||||
i_compare = compare_data.find("1");
|
||||
i_compare = compare_data.equal_range("1");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find("2");
|
||||
i_compare = compare_data.find("2");
|
||||
i_compare = compare_data.equal_range("2");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find("3");
|
||||
i_compare = compare_data.find("3");
|
||||
i_compare = compare_data.equal_range("3");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find(".");
|
||||
i_compare = compare_data.find(".");
|
||||
i_compare = compare_data.equal_range(".");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(data.end() == i_data);
|
||||
CHECK(compare_data.end() == i_compare);
|
||||
CHECK(i_data == data.end());
|
||||
CHECK(i_compare.first == i_compare.second);
|
||||
|
||||
i_data = data.find("A");
|
||||
i_compare = compare_data.find("A");
|
||||
i_compare = compare_data.equal_range("A");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(data.end() == i_data);
|
||||
CHECK(compare_data.end() == i_compare);
|
||||
CHECK(i_data == data.end());
|
||||
CHECK(i_compare.first == i_compare.second);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -1176,46 +1180,46 @@ namespace
|
||||
const CMap compare_data(initial_data.begin(), initial_data.end());
|
||||
|
||||
EMap::const_iterator i_data = data.find(Key("0"));
|
||||
CMap::const_iterator i_compare = compare_data.find("0");
|
||||
auto i_compare = compare_data.equal_range("0");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find(Key("1"));
|
||||
i_compare = compare_data.find("1");
|
||||
i_compare = compare_data.equal_range("1");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find(Key("2"));
|
||||
i_compare = compare_data.find("2");
|
||||
i_compare = compare_data.equal_range("2");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find(Key("3"));
|
||||
i_compare = compare_data.find("3");
|
||||
i_compare = compare_data.equal_range("3");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(i_compare->first == i_data->first);
|
||||
CHECK(i_compare->second == i_data->second);
|
||||
CHECK(i_data != data.end());
|
||||
CHECK(Check_ContainsPair(i_compare.first, i_compare.second, *i_data));
|
||||
|
||||
i_data = data.find(Key("."));
|
||||
i_compare = compare_data.find(".");
|
||||
i_compare = compare_data.equal_range(".");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(data.end() == i_data);
|
||||
CHECK(compare_data.end() == i_compare);
|
||||
CHECK(i_data == data.end());
|
||||
CHECK(i_compare.first == i_compare.second);
|
||||
|
||||
i_data = data.find(Key("A"));
|
||||
i_compare = compare_data.find("A");
|
||||
i_compare = compare_data.equal_range("A");
|
||||
|
||||
// Check that both return successful return results
|
||||
CHECK(data.end() == i_data);
|
||||
CHECK(compare_data.end() == i_compare);
|
||||
CHECK(i_data == data.end());
|
||||
CHECK(i_compare.first == i_compare.second);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
@ -35,6 +35,12 @@ SOFTWARE.
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
// GCC can emit false positive -Wmaybe-uninitialized warnings inside the test data
|
||||
// types when optional's storage is inspected through inlined, never-taken branches.
|
||||
// The diagnostic is raised late (after inlining), so the suppression has to cover the
|
||||
// whole translation unit. It is popped at the end of the file.
|
||||
#include "etl/private/diagnostic_uninitialized_push.h"
|
||||
|
||||
#include "data.h"
|
||||
#include "etl/algorithm.h"
|
||||
#include "etl/optional.h"
|
||||
@ -1603,5 +1609,351 @@ namespace
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*************************************************************************
|
||||
TEST(test_transform)
|
||||
{
|
||||
etl::optional<int> engaged(42);
|
||||
etl::optional<int> empty;
|
||||
|
||||
etl::optional<int> doubled = engaged.transform([](int i) { return i * 2; });
|
||||
CHECK_TRUE(doubled.has_value());
|
||||
CHECK_EQUAL(84, doubled.value());
|
||||
|
||||
etl::optional<int> from_empty = empty.transform([](int i) { return i * 2; });
|
||||
CHECK_FALSE(from_empty.has_value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_transform_const)
|
||||
{
|
||||
const etl::optional<int> engaged(42);
|
||||
const etl::optional<int> empty;
|
||||
|
||||
etl::optional<int> doubled = engaged.transform([](int i) { return i * 2; });
|
||||
CHECK_TRUE(doubled.has_value());
|
||||
CHECK_EQUAL(84, doubled.value());
|
||||
|
||||
etl::optional<int> from_empty = empty.transform([](int i) { return i * 2; });
|
||||
CHECK_FALSE(from_empty.has_value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_transform_change_type)
|
||||
{
|
||||
etl::optional<int> engaged(42);
|
||||
etl::optional<int> empty;
|
||||
|
||||
etl::optional<std::string> text = engaged.transform([](int) { return std::string("forty two"); });
|
||||
CHECK_TRUE(text.has_value());
|
||||
CHECK_EQUAL("forty two", text.value());
|
||||
|
||||
etl::optional<std::string> text_from_empty = empty.transform([](int) { return std::string("forty two"); });
|
||||
CHECK_FALSE(text_from_empty.has_value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_transform_non_pod)
|
||||
{
|
||||
etl::optional<Data> engaged(Data("transform"));
|
||||
etl::optional<Data> empty;
|
||||
|
||||
etl::optional<size_t> length = engaged.transform([](const Data& d) { return d.value.size(); });
|
||||
CHECK_TRUE(length.has_value());
|
||||
CHECK_EQUAL(9U, length.value());
|
||||
|
||||
etl::optional<size_t> length_from_empty = empty.transform([](const Data& d) { return d.value.size(); });
|
||||
CHECK_FALSE(length_from_empty.has_value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_transform_move)
|
||||
{
|
||||
etl::optional<DataM> engaged(DataM(42U));
|
||||
|
||||
etl::optional<DataM> moved = etl::move(engaged).transform([](DataM&& d) { return DataM(etl::move(d)); });
|
||||
CHECK_TRUE(moved.has_value());
|
||||
CHECK_TRUE(moved.value().valid);
|
||||
CHECK_EQUAL(42U, moved.value().value);
|
||||
CHECK_FALSE(engaged.value().valid);
|
||||
|
||||
etl::optional<DataM> empty;
|
||||
etl::optional<DataM> from_empty = etl::move(empty).transform([](DataM&& d) { return DataM(etl::move(d)); });
|
||||
CHECK_FALSE(from_empty.has_value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_and_then)
|
||||
{
|
||||
etl::optional<int> engaged(42);
|
||||
etl::optional<int> empty;
|
||||
|
||||
etl::optional<int> incremented = engaged.and_then([](int i) { return etl::optional<int>(i + 1); });
|
||||
CHECK_TRUE(incremented.has_value());
|
||||
CHECK_EQUAL(43, incremented.value());
|
||||
|
||||
etl::optional<int> from_empty = empty.and_then([](int i) { return etl::optional<int>(i + 1); });
|
||||
CHECK_FALSE(from_empty.has_value());
|
||||
|
||||
etl::optional<int> rejected = engaged.and_then([](int) { return etl::optional<int>(); });
|
||||
CHECK_FALSE(rejected.has_value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_and_then_const)
|
||||
{
|
||||
const etl::optional<int> engaged(42);
|
||||
const etl::optional<int> empty;
|
||||
|
||||
etl::optional<int> incremented = engaged.and_then([](int i) { return etl::optional<int>(i + 1); });
|
||||
CHECK_TRUE(incremented.has_value());
|
||||
CHECK_EQUAL(43, incremented.value());
|
||||
|
||||
etl::optional<int> from_empty = empty.and_then([](int i) { return etl::optional<int>(i + 1); });
|
||||
CHECK_FALSE(from_empty.has_value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_and_then_change_type)
|
||||
{
|
||||
etl::optional<int> engaged(42);
|
||||
etl::optional<int> empty;
|
||||
|
||||
etl::optional<std::string> text = engaged.and_then([](int) { return etl::optional<std::string>("forty two"); });
|
||||
CHECK_TRUE(text.has_value());
|
||||
CHECK_EQUAL("forty two", text.value());
|
||||
|
||||
etl::optional<std::string> text_from_empty = empty.and_then([](int) { return etl::optional<std::string>("forty two"); });
|
||||
CHECK_FALSE(text_from_empty.has_value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_and_then_move)
|
||||
{
|
||||
etl::optional<DataM> engaged(DataM(42U));
|
||||
|
||||
etl::optional<uint32_t> value = etl::move(engaged).and_then([](DataM&& d) { return etl::optional<uint32_t>(d.value); });
|
||||
CHECK_TRUE(value.has_value());
|
||||
CHECK_EQUAL(42U, value.value());
|
||||
|
||||
etl::optional<DataM> empty;
|
||||
etl::optional<uint32_t> from_empty = etl::move(empty).and_then([](DataM&& d) { return etl::optional<uint32_t>(d.value); });
|
||||
CHECK_FALSE(from_empty.has_value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_or_else)
|
||||
{
|
||||
etl::optional<int> engaged(42);
|
||||
etl::optional<int> empty;
|
||||
bool called = false;
|
||||
|
||||
etl::optional<int> from_engaged = engaged.or_else(
|
||||
[&called]()
|
||||
{
|
||||
called = true;
|
||||
return etl::optional<int>(99);
|
||||
});
|
||||
CHECK_TRUE(from_engaged.has_value());
|
||||
CHECK_EQUAL(42, from_engaged.value());
|
||||
CHECK_FALSE(called);
|
||||
|
||||
etl::optional<int> from_empty = empty.or_else(
|
||||
[&called]()
|
||||
{
|
||||
called = true;
|
||||
return etl::optional<int>(99);
|
||||
});
|
||||
CHECK_TRUE(from_empty.has_value());
|
||||
CHECK_EQUAL(99, from_empty.value());
|
||||
CHECK_TRUE(called);
|
||||
|
||||
etl::optional<int> still_empty = empty.or_else([]() { return etl::optional<int>(); });
|
||||
CHECK_FALSE(still_empty.has_value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_or_else_const)
|
||||
{
|
||||
const etl::optional<int> engaged(42);
|
||||
const etl::optional<int> empty;
|
||||
|
||||
etl::optional<int> from_engaged = engaged.or_else([]() { return etl::optional<int>(99); });
|
||||
CHECK_TRUE(from_engaged.has_value());
|
||||
CHECK_EQUAL(42, from_engaged.value());
|
||||
|
||||
etl::optional<int> from_empty = empty.or_else([]() { return etl::optional<int>(99); });
|
||||
CHECK_TRUE(from_empty.has_value());
|
||||
CHECK_EQUAL(99, from_empty.value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_or_else_move)
|
||||
{
|
||||
etl::optional<DataM> engaged(DataM(42U));
|
||||
|
||||
etl::optional<DataM> from_engaged = etl::move(engaged).or_else([]() { return etl::optional<DataM>(DataM(99U)); });
|
||||
CHECK_TRUE(from_engaged.has_value());
|
||||
CHECK_EQUAL(42U, from_engaged.value().value);
|
||||
|
||||
etl::optional<DataM> empty;
|
||||
etl::optional<DataM> from_empty = etl::move(empty).or_else([]() { return etl::optional<DataM>(DataM(99U)); });
|
||||
CHECK_TRUE(from_empty.has_value());
|
||||
CHECK_EQUAL(99U, from_empty.value().value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_monadic_chaining)
|
||||
{
|
||||
etl::optional<int> engaged(8);
|
||||
etl::optional<int> empty;
|
||||
|
||||
etl::optional<int> result = engaged.transform([](int i) { return i * 2; })
|
||||
.and_then([](int i) { return etl::optional<int>(i + 1); })
|
||||
.or_else([]() { return etl::optional<int>(0); });
|
||||
CHECK_TRUE(result.has_value());
|
||||
CHECK_EQUAL(17, result.value());
|
||||
|
||||
etl::optional<int> result_from_empty = empty.transform([](int i) { return i * 2; })
|
||||
.and_then([](int i) { return etl::optional<int>(i + 1); })
|
||||
.or_else([]() { return etl::optional<int>(123); });
|
||||
CHECK_TRUE(result_from_empty.has_value());
|
||||
CHECK_EQUAL(123, result_from_empty.value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_is_optional)
|
||||
{
|
||||
CHECK_TRUE((etl::is_optional<etl::optional<int>>::value));
|
||||
CHECK_TRUE((etl::is_optional<const etl::optional<int>>::value));
|
||||
CHECK_TRUE((etl::is_optional<volatile etl::optional<int>>::value));
|
||||
CHECK_TRUE((etl::is_optional<const volatile etl::optional<int>>::value));
|
||||
CHECK_TRUE((etl::is_optional<etl::optional<Data>>::value));
|
||||
|
||||
CHECK_FALSE((etl::is_optional<int>::value));
|
||||
CHECK_FALSE((etl::is_optional<Data>::value));
|
||||
CHECK_FALSE((etl::is_optional<etl::optional<int>*>::value));
|
||||
CHECK_FALSE((etl::is_optional<etl::optional<int>&>::value));
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
CHECK_TRUE((etl::is_optional_v<etl::optional<int>>));
|
||||
CHECK_TRUE((etl::is_optional_v<const etl::optional<int>>));
|
||||
CHECK_FALSE((etl::is_optional_v<int>));
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_transform_const_rvalue)
|
||||
{
|
||||
const etl::optional<int> engaged(42);
|
||||
const etl::optional<int> empty;
|
||||
|
||||
etl::optional<int> doubled = etl::move(engaged).transform([](const int&& i) { return i * 2; });
|
||||
CHECK_TRUE(doubled.has_value());
|
||||
CHECK_EQUAL(84, doubled.value());
|
||||
CHECK_TRUE(engaged.has_value());
|
||||
CHECK_EQUAL(42, engaged.value());
|
||||
|
||||
etl::optional<int> from_empty = etl::move(empty).transform([](const int&& i) { return i * 2; });
|
||||
CHECK_FALSE(from_empty.has_value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_and_then_const_rvalue)
|
||||
{
|
||||
const etl::optional<int> engaged(42);
|
||||
const etl::optional<int> empty;
|
||||
|
||||
etl::optional<int> incremented = etl::move(engaged).and_then([](const int&& i) { return etl::optional<int>(i + 1); });
|
||||
CHECK_TRUE(incremented.has_value());
|
||||
CHECK_EQUAL(43, incremented.value());
|
||||
|
||||
etl::optional<int> from_empty = etl::move(empty).and_then([](const int&& i) { return etl::optional<int>(i + 1); });
|
||||
CHECK_FALSE(from_empty.has_value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_or_else_const_rvalue)
|
||||
{
|
||||
const etl::optional<int> engaged(42);
|
||||
const etl::optional<int> empty;
|
||||
|
||||
etl::optional<int> from_engaged = etl::move(engaged).or_else([]() { return etl::optional<int>(99); });
|
||||
CHECK_TRUE(from_engaged.has_value());
|
||||
CHECK_EQUAL(42, from_engaged.value());
|
||||
|
||||
etl::optional<int> from_empty = etl::move(empty).or_else([]() { return etl::optional<int>(99); });
|
||||
CHECK_TRUE(from_empty.has_value());
|
||||
CHECK_EQUAL(99, from_empty.value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Unlike std::optional, a callable returning a reference is accepted.
|
||||
/// The reference is stripped from the result type and the value is copied.
|
||||
//*************************************************************************
|
||||
TEST(test_transform_callable_returning_reference)
|
||||
{
|
||||
etl::optional<int> engaged(42);
|
||||
|
||||
auto result = engaged.transform([](int& i) -> int& { return i; });
|
||||
|
||||
CHECK_TRUE((etl::is_same<etl::optional<int>, decltype(result)>::value));
|
||||
CHECK_TRUE(result.has_value());
|
||||
CHECK_EQUAL(42, result.value());
|
||||
|
||||
// The result is a copy, not an alias of the source.
|
||||
result.value() = 1;
|
||||
CHECK_EQUAL(42, engaged.value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_and_then_callable_returning_reference)
|
||||
{
|
||||
etl::optional<int> engaged(42);
|
||||
etl::optional<int> empty;
|
||||
|
||||
auto f = [](int i) -> etl::optional<int>&
|
||||
{
|
||||
static etl::optional<int> shared;
|
||||
shared = i + 1;
|
||||
return shared;
|
||||
};
|
||||
|
||||
auto result = engaged.and_then(f);
|
||||
|
||||
CHECK_TRUE((etl::is_same<etl::optional<int>, decltype(result)>::value));
|
||||
CHECK_TRUE(result.has_value());
|
||||
CHECK_EQUAL(43, result.value());
|
||||
|
||||
auto from_empty = empty.and_then(f);
|
||||
CHECK_FALSE(from_empty.has_value());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_or_else_callable_returning_reference)
|
||||
{
|
||||
etl::optional<int> engaged(42);
|
||||
etl::optional<int> empty;
|
||||
|
||||
auto f = []() -> etl::optional<int>&
|
||||
{
|
||||
static etl::optional<int> shared(99);
|
||||
return shared;
|
||||
};
|
||||
|
||||
auto from_engaged = engaged.or_else(f);
|
||||
|
||||
CHECK_TRUE((etl::is_same<etl::optional<int>, decltype(from_engaged)>::value));
|
||||
CHECK_TRUE(from_engaged.has_value());
|
||||
CHECK_EQUAL(42, from_engaged.value());
|
||||
|
||||
auto from_empty = empty.or_else(f);
|
||||
CHECK_TRUE(from_empty.has_value());
|
||||
CHECK_EQUAL(99, from_empty.value());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
#include "etl/private/diagnostic_pop.h"
|
||||
|
||||
@ -542,6 +542,50 @@ namespace
|
||||
CHECK(isEqual);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_remove_prefix_empty)
|
||||
{
|
||||
std::string original = "Hello World";
|
||||
View view(original.c_str());
|
||||
|
||||
// remove n == size() should result in an empty view
|
||||
view.remove_prefix(original.size());
|
||||
CHECK_EQUAL(view.begin(), view.end());
|
||||
CHECK(view.empty());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_remove_prefix_assert)
|
||||
{
|
||||
std::string original = "Hello World";
|
||||
View view(original.c_str());
|
||||
|
||||
// remove n > size() should trigger ETL_ASSERT
|
||||
CHECK_THROW(view.remove_prefix(original.size() + 1), etl::string_view_bounds);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_remove_suffix_empty)
|
||||
{
|
||||
std::string original = "Hello World";
|
||||
View view(original.c_str());
|
||||
|
||||
// remove n == size() should result in an empty view
|
||||
view.remove_suffix(original.size());
|
||||
CHECK_EQUAL(view.begin(), view.end());
|
||||
CHECK(view.empty());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_remove_suffix_assert)
|
||||
{
|
||||
std::string original = "Hello World";
|
||||
View view(original.c_str());
|
||||
|
||||
// remove n > size() should trigger ETL_ASSERT
|
||||
CHECK_THROW(view.remove_suffix(original.size() + 1), etl::string_view_bounds);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_copy)
|
||||
{
|
||||
|
||||
@ -1039,6 +1039,71 @@ namespace
|
||||
CHECK_EQUAL(83, int(etl::to_arithmetic<int8_t>(ETLText(text.c_str(), text.size()), etl::radix::decimal).value()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_comparison_operators)
|
||||
{
|
||||
const Text text(STR("123"));
|
||||
const Text bad_text(STR("1X3"));
|
||||
const Text other_bad_text(STR("2X3"));
|
||||
const Text overflow_text(STR("99999999999999999999"));
|
||||
|
||||
const etl::to_arithmetic_result<int> result = etl::to_arithmetic<int>(text.c_str(), text.size());
|
||||
const etl::to_arithmetic_result<int> same = etl::to_arithmetic<int>(text.c_str(), text.size());
|
||||
const etl::to_arithmetic_result<int> bad_result = etl::to_arithmetic<int>(bad_text.c_str(), bad_text.size());
|
||||
const etl::to_arithmetic_result<int> same_bad_result = etl::to_arithmetic<int>(other_bad_text.c_str(), other_bad_text.size());
|
||||
const etl::to_arithmetic_result<int> overflow_result = etl::to_arithmetic<int>(overflow_text.c_str(), overflow_text.size());
|
||||
|
||||
// result <-> result
|
||||
CHECK_TRUE(result == same);
|
||||
CHECK_FALSE(result != same);
|
||||
CHECK_TRUE(result != bad_result);
|
||||
CHECK_FALSE(result == bad_result);
|
||||
|
||||
// Two errored results with the same status compare equal.
|
||||
CHECK_EQUAL(bad_result.error(), same_bad_result.error());
|
||||
CHECK_TRUE(bad_result == same_bad_result);
|
||||
CHECK_FALSE(bad_result != same_bad_result);
|
||||
|
||||
// Two errored results with different statuses do not compare equal.
|
||||
CHECK(bad_result.error() != overflow_result.error());
|
||||
CHECK_TRUE(bad_result != overflow_result);
|
||||
CHECK_FALSE(bad_result == overflow_result);
|
||||
|
||||
// result <-> value
|
||||
CHECK_TRUE(result == 123);
|
||||
CHECK_FALSE(result != 123);
|
||||
CHECK_TRUE(result != 124);
|
||||
CHECK_FALSE(result == 124);
|
||||
|
||||
// value <-> result
|
||||
CHECK_TRUE(123 == result);
|
||||
CHECK_FALSE(123 != result);
|
||||
CHECK_TRUE(124 != result);
|
||||
CHECK_FALSE(124 == result);
|
||||
|
||||
// An errored result never compares equal to a value.
|
||||
CHECK_FALSE(bad_result == 123);
|
||||
CHECK_TRUE(bad_result != 123);
|
||||
CHECK_FALSE(123 == bad_result);
|
||||
CHECK_TRUE(123 != bad_result);
|
||||
|
||||
// Heterogeneous result <-> value, using a different result value type.
|
||||
const etl::to_arithmetic_result<long> long_result = etl::to_arithmetic<long>(text.c_str(), text.size());
|
||||
const etl::to_arithmetic_result<int8_t> small_result = etl::to_arithmetic<int8_t>(text.c_str(), text.size());
|
||||
|
||||
CHECK_TRUE(long_result == 123);
|
||||
CHECK_FALSE(long_result != 123);
|
||||
CHECK_TRUE(123 == long_result);
|
||||
CHECK_TRUE(long_result != 124);
|
||||
CHECK_FALSE(123 != long_result);
|
||||
CHECK_TRUE(124 != long_result);
|
||||
|
||||
CHECK_TRUE(small_result == 123);
|
||||
CHECK_FALSE(small_result != 123);
|
||||
CHECK_TRUE(123 == small_result);
|
||||
CHECK_TRUE(small_result != 124);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP14
|
||||
TEST(test_constexpr_integral)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1324,6 +1324,35 @@ namespace
|
||||
CHECK(etl::get<TrivialAssignTracker>(variant_1).move_assigned);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
// Issue #1567: the variant propagates trivial copyability from its
|
||||
// alternatives, as required by P0602R4.
|
||||
TEST(test_trivially_copyable)
|
||||
{
|
||||
// Fundamental types are trivially copyable in every ETL configuration.
|
||||
CHECK((std::is_trivially_copyable<etl::variant<char, int, double> >::value));
|
||||
CHECK((std::is_trivially_copy_constructible<etl::variant<char, int, double> >::value));
|
||||
CHECK((std::is_trivially_move_constructible<etl::variant<char, int, double> >::value));
|
||||
CHECK((std::is_trivially_copy_assignable<etl::variant<char, int, double> >::value));
|
||||
CHECK((std::is_trivially_move_assignable<etl::variant<char, int, double> >::value));
|
||||
|
||||
// An alternative that is not trivially copyable prevents propagation.
|
||||
CHECK((!std::is_trivially_copyable<etl::variant<int, AssignTracker> >::value));
|
||||
|
||||
// The variant still copies and moves correctly.
|
||||
typedef etl::variant<char, int, double> trivial_variant;
|
||||
|
||||
trivial_variant variant_1(1.5);
|
||||
trivial_variant variant_2(variant_1);
|
||||
CHECK_EQUAL(2U, variant_2.index());
|
||||
CHECK_EQUAL(1.5, etl::get<double>(variant_2));
|
||||
|
||||
trivial_variant variant_3;
|
||||
variant_3 = variant_2;
|
||||
CHECK_EQUAL(2U, variant_3.index());
|
||||
CHECK_EQUAL(1.5, etl::get<double>(variant_3));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
// Issue #1512: even though the copy operations are disabled at compile
|
||||
// time, a move-only variant must still move construct / move assign
|
||||
|
||||
@ -1531,8 +1531,12 @@ namespace
|
||||
{
|
||||
auto data = etl::make_vector<char>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
|
||||
// The explicit element type now selects the element type for all
|
||||
// arguments (Library Fundamentals TS make_array design). Previously it
|
||||
// pinned only the first argument's deduced type, and the element type
|
||||
// was still the common type of the arguments - int for this call.
|
||||
using Type = typename std::remove_reference<decltype(data[0])>::type;
|
||||
CHECK((std::is_same<int, Type>::value));
|
||||
CHECK((std::is_same<char, Type>::value));
|
||||
|
||||
CHECK_EQUAL(0, data[0]);
|
||||
CHECK_EQUAL(1, data[1]);
|
||||
@ -1590,6 +1594,29 @@ namespace
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_HAS_INITIALIZER_LIST
|
||||
// An explicit element type selects the element type and converts every
|
||||
// argument (Library Fundamentals TS make_array design), accepting
|
||||
// const-qualified lvalues and narrowing initialisers.
|
||||
TEST(test_make_vector_explicit_element_type)
|
||||
{
|
||||
static const char static_const_lvalue = 42;
|
||||
const char local_const_lvalue = 43;
|
||||
char mutable_lvalue = 44;
|
||||
|
||||
auto data = etl::make_vector<char>(static_const_lvalue, local_const_lvalue, mutable_lvalue, 45, 46);
|
||||
|
||||
CHECK((std::is_same<etl::vector<char, 5U>, decltype(data)>::value));
|
||||
|
||||
CHECK_EQUAL(42, data[0]);
|
||||
CHECK_EQUAL(43, data[1]);
|
||||
CHECK_EQUAL(44, data[2]);
|
||||
CHECK_EQUAL(45, data[3]);
|
||||
CHECK_EQUAL(46, data[4]);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_fill)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user