From afa17c5042e463c70c5707c517ad1e7fc43ea568 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 11 Jul 2026 13:02:42 +0100 Subject: [PATCH] Squashed commit of the following: commit c5dc331004b4d9611ab996935bedada203676c71 Author: John Wellbelove Date: Sat Jul 11 12:32:20 2026 +0100 Updated release notes commit 4bf6ed6ce8d79857658d763e368ee56617542b2c Author: vcoselev <145198867+vcoselev@users.noreply.github.com> Date: Sat Jul 11 12:05:39 2026 +0100 Fix for 1405: etl::exchange doesn't work with unique_ptr (#1477) * Separate bit order and endianness in bit_stream.h (#1495) * Factor out ranges tests from test_algorithm.cpp to test_algorithm_ranges.cpp (#1497) * Fix exchange to use forwarding reference (U&&) and move - etl::exchange was using the copy constructor. Changed for etl::move. - The assignment to the new object is now done with forward. - Added a test with unique_ptr. --------- Co-authored-by: Roland Reichwein Co-authored-by: John Wellbelove commit 2ed9019df04d470530c41c1f27d35adc30b9a32d Author: Moritz Pflanzer Date: Fri Jul 10 11:42:32 2026 +0200 Update operator[] docs for map class (#1499) * Separate bit order and endianness in bit_stream.h (#1495) * Update operator[] docs for map class No const variant is implemented for the operator[]. --------- Co-authored-by: Roland Reichwein commit 423e18d96dc645f1c733cb0d8ae6b675b9eb7e83 Author: Roland Reichwein Date: Fri Jul 10 11:14:08 2026 +0200 Factor out ranges tests from test_algorithm.cpp to test_algorithm_ranges.cpp (#1497) commit 338bfdbb1f4df3c5c08a68a9038f13b8dae1c28b Author: John Wellbelove Date: Fri Jul 10 10:12:04 2026 +0100 Add coverage report to docs (#1498) * Updated release notes * Added link to coverage report --------- Co-authored-by: John Wellbelove commit 269025424f4c6f61cebac090f4df82985fb3b239 Merge: c004cc9d faa4c15b Author: John Wellbelove Date: Thu Jul 9 14:18:32 2026 +0100 Merge branch 'development' of https://github.com/ETLCPP/etl into development commit c004cc9d508efcf398630758a47aae95b37a7eb8 Author: John Wellbelove Date: Thu Jul 9 10:06:17 2026 +0100 Updated release notes commit faa4c15b49c8ad15475c83ae23e00f5a46f803ca Author: John Wellbelove Date: Thu Jul 9 10:06:17 2026 +0100 Updated release notes commit 1523e63e35a15cfd1fa72d230a3c79efa7b9c3e0 Author: Roland Reichwein Date: Wed Jul 8 20:48:33 2026 +0200 Support non-assignable alternatives in variant (#1496) commit 878a0ba5a28f6b0dcae9f472a6a6a1f107de0a74 Author: John Wellbelove Date: Wed Jul 8 11:07:01 2026 +0100 Updated version and release notes commit 5287fe4b3b9f58330881d2a62abf6ce8e1159b8d Author: John Wellbelove Date: Wed Jul 8 09:06:50 2026 +0100 Allow etl::vector to store pointers to functions and member functions (#1492) * Refactored vector.h Deleted ivectorpointer.h * Minor changes * Fixed code incompatible with C++03 * Clang-format changes * Removed redundant double-qualified name * Fixed is_is_object_pointer_v to is_object_pointer_v * Added new test files to meson.build * Added overflow checks to vector_ext copy and move constructors and assignments Added assert throw tests. * Added diagnostic pushes to eliminate GCC warning false positives * Changed the GCC C++23 Github action to use GCC14 * Applied clang-format * Added guard to pop_heap * Added guard to adjust_heap * Attempt to fix GCC diagnostic * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * clang-format * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Missing newline at end of file * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Attempt to fix GCC diagnostic * clang-format * Changed gcc --version to gcc-14 --version --------- Co-authored-by: John Wellbelove Co-authored-by: Roland Reichwein commit 40dddd7f9601985ae7350e60a404af9028bc9fe9 Author: Roland Reichwein Date: Tue Jul 7 23:41:17 2026 +0200 Add optional etl_profile label_flag for Bazel profile injection (#1491) Co-authored-by: John Wellbelove commit 84fca4cd62f72c382c062376ca934803116a20d5 Author: Roland Reichwein Date: Tue Jul 7 21:45:47 2026 +0200 Add missing memory functions, according the standard (#1490) Adding: - etl::align - etl::assume_aligned - etl::is_sufficiently_aligned - etl::launder - etl::pointer_traits - etl::start_lifetime_as Co-authored-by: John Wellbelove commit dca6653b3759b2cdc79307fec7425589feea478d Author: Roland Reichwein Date: Tue Jul 7 21:00:09 2026 +0200 Add missing interfaces to etl::chrono (#1489) Co-authored-by: John Wellbelove commit c52b2ac7b1f675e6b1d34052239423b7f3634033 Author: Roland Reichwein Date: Tue Jul 7 18:06:05 2026 +0200 Fix etl::mem_cast cross-size copy constructor and assignment (#1488) The templated cross-size copy constructor and assignment operator were broken in two ways: - They accessed other.buffer / rhs.buffer, which is private in a different mem_cast instantiation, so the cross-size overloads failed to compile whenever they were actually instantiated. - They copied Size_ (the destination size) bytes from a source buffer that is only Other_Size bytes large, reading past the end of the source when the destination was larger. Use the public data() accessor and copy Other_Size bytes. The existing static_assert(Size >= Other_Size) guarantees the destination is big enough. Add test_mem_cast_copy_and_assign_from_smaller regression test. Co-authored-by: John Wellbelove commit 165674cb23dda1fd4f7e5a1182f49554a796bfe8 Author: Roland Reichwein Date: Tue Jul 7 16:41:50 2026 +0200 Fix etl::pearson::reset() not resetting the first-byte flag (#1487) reset() cleared the hash array but left the `first` flag false, so a calculator reused after reset() took the XOR update path on its next add() instead of the initialisation path. This produced an incorrect hash for any pearson object that was reset and reused. Reset `first` to true in reset() so a reset calculator behaves like a freshly constructed one. Add test_pearson_reset regression test. Co-authored-by: John Wellbelove commit 032ec4cc80f1c0f1baa0383bdbc5f9239b68f268 Author: Roland Reichwein Date: Tue Jul 7 13:40:04 2026 +0200 Fix etl::bitset single-element from_string shift on empty string (#1486) The single-element from_string overloads (char, wchar_t, char16_t, char32_t) computed element_type(1) << (string_length - 1U) before the copy loop. For an empty string, or when active_bits is 0, string_length is 0, so the shift count underflows to SIZE_MAX. Shifting by more than the element width is undefined behaviour, which also breaks constexpr evaluation. Guard the mask with a zero-length check so the shift is only performed when string_length > 0. The multi-element from_string overloads were already safe. Add test_construct_from_empty_string regression test. Co-authored-by: John Wellbelove commit 98cb365d4c28e7b72f8547b734a03a4068acd3f5 Author: Roland Reichwein Date: Tue Jul 7 12:32:56 2026 +0200 Fix etl::histogram copy/move not preserving start_index (#1485) The run-time-offset specialization of etl::histogram stores a start_index member used to map keys to bins (accumulator[key - start_index]). Its copy constructor, move constructor, copy assignment, and move assignment copied only the accumulator and left start_index uninitialized, so a copied or moved histogram indexed the wrong bin in operator[]/add(), causing out-of-bounds access (undefined behavior). All four special member functions now also copy start_index. The compile-time-offset specialization is unaffected, as its start index is a template constant rather than a data member. Add regression tests covering copy/move construction and assignment. Co-authored-by: John Wellbelove commit 5cd2f28cd54e4019f7be126bcf7394a6a8318eb9 Author: Drew Rife Date: Tue Jul 7 03:14:48 2026 -0400 Refactor variant::emplace to perfect forward args instead of copy/move construct (#1494) * refactor: emplace logic to use do_emplace for in-place construction with forwarded arguments #1493 * Add test for variant_variadic --------- Co-authored-by: Roland Reichwein commit a47c0aae81b886259918961d5fcee20faa06fdd0 Author: Roland Reichwein Date: Mon Jul 6 17:32:26 2026 +0200 Fix etl::message_timer firing following timers early on unregister (#1484) active_list.remove(id, has_expired) adjusts the next timer's delta only when has_expired is false. When unregistering an active, non-expired timer, unregister_timer() incorrectly passed true, skipping that adjustment, so every timer after the removed one in the active list fired early by the removed timer's delta. Pass false instead, matching the etl::callback_timer family. tick() still passes true, since the timer has genuinely expired there. The bug affected all four variants: message_timer, message_timer_interrupt, message_timer_atomic and message_timer_locked. Existing tests missed it because they only ever unregistered the tail timer, where the delta adjustment is a no-op. Add a regression test that unregisters a non-tail active timer and checks the following timer still fires at its original absolute time. --- .github/workflows/gcc-c++23.yml | 32 +- BUILD.bazel | 27 + arduino/library-arduino.json | 2 +- arduino/library-arduino.properties | 2 +- docs/_index.md | 5 +- docs/chrono/hh_mm_ss.md | 47 +- docs/chrono/time_point.md | 94 ++ docs/containers/maps/map.md | 3 +- docs/releases/_index.md | 18 + docs/source/bazel.md | 34 + docs/types/type-traits.md | 19 +- hugo/assets/version.txt | 2 +- include/etl/algorithm.h | 19 +- include/etl/histogram.h | 4 + include/etl/intrusive_avl_tree.h | 2 + include/etl/mem_cast.h | 4 +- include/etl/memory.h | 317 ++++ include/etl/message_timer.h | 2 +- include/etl/message_timer_atomic.h | 2 +- include/etl/message_timer_interrupt.h | 2 +- include/etl/message_timer_locked.h | 2 +- include/etl/pearson.h | 1 + include/etl/private/bitset_new.h | 20 + include/etl/private/chrono/hh_mm_ss.h | 59 + include/etl/private/chrono/time_point.h | 95 ++ include/etl/private/ivectorpointer.h | 1140 -------------- include/etl/private/variant_variadic.h | 42 +- .../etl/profiles/determine_builtin_support.h | 9 + include/etl/span.h | 10 +- include/etl/type_traits.h | 93 +- include/etl/utility.h | 26 +- include/etl/vector.h | 902 +++++++---- include/etl/version.h | 2 +- library.json | 2 +- library.properties | 2 +- support/Release notes.txt | 17 + test/CMakeLists.txt | 4 + test/meson.build | 4 + ...itset_new_explicit_single_element_type.cpp | 16 + test/test_chrono_hh_mm_ss.cpp | 81 + test/test_chrono_time_point.cpp | 93 ++ test/test_circular_iterator.cpp | 2 + test/test_deque.cpp | 4 + test/test_histogram.cpp | 62 + test/test_map.cpp | 4 + test/test_mem_cast.cpp | 18 + test/test_memory.cpp | 178 +++ test/test_message_timer.cpp | 46 + test/test_pearson.cpp | 19 + test/test_utility.cpp | 27 + test/test_variant_variadic.cpp | 313 +++- test/test_vector.cpp | 30 +- test/test_vector_external_buffer.cpp | 18 + test/test_vector_function_pointer.cpp | 1321 ++++++++++++++++ ...ector_function_pointer_external_buffer.cpp | 1301 ++++++++++++++++ test/test_vector_member_function_pointer.cpp | 1330 +++++++++++++++++ ...ember_function_pointer_external_buffer.cpp | 1329 ++++++++++++++++ test/vs2022/etl.vcxproj | 18 +- test/vs2022/etl.vcxproj.filters | 57 +- version.txt | 2 +- 60 files changed, 7767 insertions(+), 1569 deletions(-) delete mode 100644 include/etl/private/ivectorpointer.h create mode 100644 test/test_vector_function_pointer.cpp create mode 100644 test/test_vector_function_pointer_external_buffer.cpp create mode 100644 test/test_vector_member_function_pointer.cpp create mode 100644 test/test_vector_member_function_pointer_external_buffer.cpp diff --git a/.github/workflows/gcc-c++23.yml b/.github/workflows/gcc-c++23.yml index 9ca6baf0..842b6152 100644 --- a/.github/workflows/gcc-c++23.yml +++ b/.github/workflows/gcc-c++23.yml @@ -21,12 +21,12 @@ jobs: - name: Build run: | export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - export CC=gcc - export CXX=g++ + 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 ./ - gcc --version + gcc-14 --version make -j "$(getconf _NPROCESSORS_ONLN)" - + - name: Run tests run: ./test/etl_tests -v @@ -43,12 +43,12 @@ jobs: - name: Build run: | export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - export CC=gcc - export CXX=g++ + 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 ./ - gcc --version + gcc-14 --version make -j "$(getconf _NPROCESSORS_ONLN)" - + - name: Run tests run: ./test/etl_tests -v @@ -65,10 +65,10 @@ jobs: - name: Build run: | export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - export CC=gcc - export CXX=g++ + 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 ./ - gcc --version + gcc-14 --version make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests @@ -87,11 +87,11 @@ jobs: - name: Build run: | export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - export CC=gcc - export CXX=g++ + 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 ./ - gcc --version + gcc-14 --version make -j "$(getconf _NPROCESSORS_ONLN)" - + - name: Run tests - run: ./test/etl_tests -v \ No newline at end of file + run: ./test/etl_tests -v diff --git a/BUILD.bazel b/BUILD.bazel index 3bdb072e..59ea5184 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -2,8 +2,35 @@ load("@rules_cc//cc:defs.bzl", "cc_library") package(default_visibility = ["//visibility:public"]) +# ETL can be tailored to a project through an `etl_profile.h` header (see +# `include/etl/platform.h`). When no such header is on the include path, ETL +# falls back to its built-in defaults via `ETL_NO_PROFILE_HEADER`. +# +# This label_flag lets a consumer inject that profile as a Bazel target, without +# patching this BUILD file: +# +# bazel build @etl//:etl --@etl//:etl_profile=//path/to:my_etl_profile +# +# The injected target is a cc_library that exposes a single `etl_profile.h` on +# its include path, for example: +# +# cc_library( +# name = "my_etl_profile", +# hdrs = ["etl_profile.h"], +# strip_include_prefix = ".", +# ) +# +# The default is empty, so ETL's built-in defaults are used unless overridden. +label_flag( + name = "etl_profile", + build_setting_default = ":no_profile", +) + +cc_library(name = "no_profile") + cc_library( name = "etl", hdrs = glob(["include/**/*.h"]), includes = ["include"], + deps = [":etl_profile"], ) diff --git a/arduino/library-arduino.json b/arduino/library-arduino.json index 920e19f3..8bdb2a1b 100644 --- a/arduino/library-arduino.json +++ b/arduino/library-arduino.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library ETL", - "version": "20.48.0", + "version": "20.48.1", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/arduino/library-arduino.properties b/arduino/library-arduino.properties index b33108b3..55f4e119 100644 --- a/arduino/library-arduino.properties +++ b/arduino/library-arduino.properties @@ -1,5 +1,5 @@ name=Embedded Template Library ETL -version=20.48.0 +version=20.48.1 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/docs/_index.md b/docs/_index.md index e6f75a2e..4fbb737c 100644 --- a/docs/_index.md +++ b/docs/_index.md @@ -39,14 +39,13 @@ type: hextra-home
- coverage + coverage Codacy
- +
Sponsor
- ## Version diff --git a/docs/chrono/hh_mm_ss.md b/docs/chrono/hh_mm_ss.md index f7744ff1..583e2cba 100644 --- a/docs/chrono/hh_mm_ss.md +++ b/docs/chrono/hh_mm_ss.md @@ -135,4 +135,49 @@ ETL_NOEXCEPT ``` A specialisation of absolute for `etl::chrono::duration`. **Return** -The absolute duration value. \ No newline at end of file +The absolute duration value. + +## 12/24 hour functions +```cpp +ETL_NODISCARD +inline ETL_CONSTEXPR14 +bool is_am(const etl::chrono::hours& h) +ETL_NOEXCEPT +``` +**Description** +Returns `true` if `h` is in the range [0h, 11h] (an am hour). + +--- + +```cpp +ETL_NODISCARD +inline ETL_CONSTEXPR14 +bool is_pm(const etl::chrono::hours& h) +ETL_NOEXCEPT +``` +**Description** +Returns `true` if `h` is in the range [12h, 23h] (a pm hour). + +--- + +```cpp +ETL_NODISCARD +inline ETL_CONSTEXPR14 +etl::chrono::hours make12(const etl::chrono::hours& h) +ETL_NOEXCEPT +``` +**Description** +Returns the 12-hour equivalent of `h` in the range [1h, 12h]. +If `h` is not in the range [0h, 23h], the value returned is unspecified. + +--- + +```cpp +ETL_NODISCARD +inline ETL_CONSTEXPR14 +etl::chrono::hours make24(const etl::chrono::hours& h, bool is_pm) +ETL_NOEXCEPT +``` +**Description** +Returns the 24-hour equivalent of `h`, which is assumed to represent the hour with the indicated am/pm. +If `h` is not in the range [1h, 12h], the value returned is unspecified. \ No newline at end of file diff --git a/docs/chrono/time_point.md b/docs/chrono/time_point.md index dd0bd674..4b9680f8 100644 --- a/docs/chrono/time_point.md +++ b/docs/chrono/time_point.md @@ -100,6 +100,41 @@ ETL_NOEXCEPT **Description** Subtracts a duration. +## Increment/decrement +```cpp +ETL_CONSTEXPR14 time_point& operator ++() +ETL_NOEXCEPT +``` +**Description** +Pre-increments the stored duration by one tick. + +--- + +```cpp +ETL_CONSTEXPR14 time_point operator ++(int) +ETL_NOEXCEPT +``` +**Description** +Post-increments the stored duration by one tick. + +--- + +```cpp +ETL_CONSTEXPR14 time_point& operator --() +ETL_NOEXCEPT +``` +**Description** +Pre-decrements the stored duration by one tick. + +--- + +```cpp +ETL_CONSTEXPR14 time_point operator --(int) +ETL_NOEXCEPT +``` +**Description** +Post-decrements the stored duration by one tick. + ## Constants ```cpp ETL_NODISCARD @@ -180,6 +215,65 @@ If time_point < other, returns -1 else if time_point > other, returns 1 else returns 0 +## Non-member mathematical operators +```cpp +template +ETL_CONSTEXPR14 +etl::chrono::time_point >::type> + operator +(const time_point& lhs, + const etl::chrono::duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Adds a duration to a time_point. +**Return** +A time_point whose duration is the common type of the two. + +--- + +```cpp +template +ETL_CONSTEXPR14 +etl::chrono::time_point, TDuration2>::type> + operator +(const etl::chrono::duration& lhs, + const time_point& rhs) +ETL_NOEXCEPT +``` +**Description** +Adds a duration to a time_point. +**Return** +A time_point whose duration is the common type of the two. + +--- + +```cpp +template +ETL_CONSTEXPR14 +etl::chrono::time_point >::type> + operator -(const time_point& lhs, + const etl::chrono::duration& rhs) +ETL_NOEXCEPT +``` +**Description** +Subtracts a duration from a time_point. +**Return** +A time_point whose duration is the common type of the two. + +--- + +```cpp +template +ETL_CONSTEXPR14 +typename etl::common_type::type + operator -(const time_point& lhs, + const time_point& rhs) +ETL_NOEXCEPT +``` +**Description** +Subtracts one time_point from another. +**Return** +The duration between them as the common type of the two durations. + ## Non-member comparison operators ```cpp template diff --git a/docs/containers/maps/map.md b/docs/containers/maps/map.md index d212ce5e..c2c26396 100644 --- a/docs/containers/maps/map.md +++ b/docs/containers/maps/map.md @@ -96,10 +96,9 @@ If assert or exceptions are not enabled then undefined behaviour occurs. ```cpp TMapped& operator[](key_parameter_t key) -const TMapped& operator[](key_parameter_t key) const ``` **Description** -Returns a reference or const reference to the indexed element. +Returns a reference to the indexed element. If the key does not exist then one is created using the default constructor. If the map is full then asserts an `etl::map_full`. If asserts or exceptions are not enabled then undefined behaviour occurs. diff --git a/docs/releases/_index.md b/docs/releases/_index.md index dcfab765..15553d90 100644 --- a/docs/releases/_index.md +++ b/docs/releases/_index.md @@ -5,6 +5,24 @@ weight: 2002 Click on the links to see the original Github page. +## 20.48.1 + +**Pull requests:** + +[#1477](https://github.com/ETLCPP/etl/pull/1477) Fix for 1405: etl::exchange doesn't work with unique_ptr +[#1484](https://github.com/ETLCPP/etl/pull/1484) Fix `etl::message_timer` firing following timers early on unregister +[#1485](https://github.com/ETLCPP/etl/pull/1485) Fix `etl::histogram` copy/move not preserving start_index +[#1486](https://github.com/ETLCPP/etl/pull/1486) Fix `etl::bitset` single-element `from_string` shift on empty string +[#1487](https://github.com/ETLCPP/etl/pull/1487) Fix `etl::pearson::reset()` not resetting the first-byte flag +[#1488](https://github.com/ETLCPP/etl/pull/1488) Fix `etl::mem_cast` cross-size copy constructor and assignment +[#1489](https://github.com/ETLCPP/etl/pull/1489) Add missing interfaces to `etl::chrono` +[#1490](https://github.com/ETLCPP/etl/pull/1490) Add missing memory functions, according the standard +[#1491](https://github.com/ETLCPP/etl/pull/1491) Add optional `etl_profile` `label_flag` for Bazel profile injection +[#1492](https://github.com/ETLCPP/etl/pull/1492) Allow `etl::vector` to store pointers to functions and member functions +[#1494](https://github.com/ETLCPP/etl/pull/1494) Refactor `variant::emplace` to perfect forward args instead of copy/move construct +[#1495](https://github.com/ETLCPP/etl/pull/1495) Separate bit order and endianness in `bit_stream.h` +[#1496](https://github.com/ETLCPP/etl/pull/1496) Fix non-assignable alternatives in variant + ## 20.48.0 **Pull requests:** diff --git a/docs/source/bazel.md b/docs/source/bazel.md index 501883b5..3554f960 100644 --- a/docs/source/bazel.md +++ b/docs/source/bazel.md @@ -296,3 +296,37 @@ Then use them with `--config`: ```sh bazel test //test:etl_tests --config=clang --config=c++20 --config=release ``` + +### Injecting a Custom Profile Header + +Instead of passing many individual `--copt=-D...` flags, ETL can be configured in bulk through a user-provided `etl_profile.h` header. When such a header is reachable on the include path, `include/etl/platform.h` includes it automatically; otherwise ETL falls back to its built-in defaults (`ETL_NO_PROFILE_HEADER`). + +Because the header must sit on ETL's include path, `BUILD.bazel` exposes an `etl_profile` [`label_flag`](https://bazel.build/extending/config) so you can inject it as a Bazel target — without patching ETL's `BUILD.bazel`. + +First, wrap your profile header in a `cc_library` that places `etl_profile.h` on its include path: + +```python +# path/to/BUILD.bazel +cc_library( + name = "my_etl_profile", + hdrs = ["etl_profile.h"], + strip_include_prefix = ".", +) +``` + +Then point the `etl_profile` flag at that target when building: + +```sh +bazel build @etl//:etl --@etl//:etl_profile=//path/to:my_etl_profile +``` + +The flag defaults to an empty library (`:no_profile`), so ETL uses its built-in defaults unless you override it. As with any flag, the override can be made permanent in `.bazelrc`: + +``` +# .bazelrc +build --@etl//:etl_profile=//path/to:my_etl_profile +``` + +> **Note:** Use the repository-qualified form `--@etl//:etl_profile=...` when consuming ETL as an +> external dependency. When building from within the ETL repository itself, drop the repository +> prefix: `--//:etl_profile=...`. diff --git a/docs/types/type-traits.md b/docs/types/type-traits.md index 6bd1fcaa..721fdfc3 100644 --- a/docs/types/type-traits.md +++ b/docs/types/type-traits.md @@ -3,7 +3,7 @@ title: "type_traits" --- Reverse engineered types traits classes from C++11 plus several ETL extensions. -This file is generated from type_traits_generator.h. See Generators +This file is generated from `type_traits_generator.h`. See Generators Not all traits have been defined as some rely on compiler intrinsics that are not available on all compiler platforms. `integral_constant` @@ -459,3 +459,20 @@ template class Template> inline constexpr bool is_specialization_v = etl::is_specialization::value; ``` C++17 + +## is_object_pointer +From: `20.49.0` + +```cpp +template +struct is_object_pointer +``` +Checks if `T` is a pointer to an object. +Pointers to functions and member functions return `false`. +The result is found in the member `value`. + +```cpp +template +inline constexpr bool is_object_pointer_v = etl::is_object_pointer::value; +``` +C++17 diff --git a/hugo/assets/version.txt b/hugo/assets/version.txt index 45d90e97..09bbfc15 100644 --- a/hugo/assets/version.txt +++ b/hugo/assets/version.txt @@ -1 +1 @@ -20.48.0 +20.48.1 diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index 1c544b40..7e4bfd72 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -914,6 +914,7 @@ namespace etl TDistance top_index = value_index; TDistance child2nd = (2 * value_index) + 2; +#include "etl/private/diagnostic_array_bounds_push.h" while (child2nd < length) { if (compare(*(first + child2nd), *(first + (child2nd - 1)))) @@ -931,6 +932,7 @@ namespace etl *(first + value_index) = ETL_MOVE(*(first + (child2nd - 1))); value_index = child2nd - 1; } +#include "etl/private/diagnostic_pop.h" push_heap(first, value_index, top_index, ETL_MOVE(value), compare); } @@ -965,6 +967,12 @@ namespace etl typedef typename etl::iterator_traits::value_type value_t; typedef typename etl::iterator_traits::difference_type distance_t; + const distance_t n = last - first; + if (n <= 1) + { + return; + } + value_t value = ETL_MOVE(*(last - 1)); *(last - 1) = ETL_MOVE(*first); @@ -5844,6 +5852,8 @@ namespace etl { ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "partial_sort requires random access iterators"); + #include "etl/private/diagnostic_array_bounds_push.h" + I last_it = ranges::next(first, last); if (first == middle || first == last_it) @@ -5880,6 +5890,8 @@ namespace etl } return last_it; + + #include "etl/private/diagnostic_pop.h" } template >> @@ -5933,6 +5945,8 @@ namespace etl { ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "partial_sort_copy requires the output to be random access iterators"); + #include "etl/private/diagnostic_array_bounds_push.h" + I1 in_last = ranges::next(first, last); I2 out_last = ranges::next(result_first, result_last); @@ -5970,7 +5984,6 @@ namespace etl } } - #include "etl/private/diagnostic_array_bounds_push.h" // Sort the heap to produce a sorted output range for (auto heap_end = heap_size - 1; heap_end > 0; --heap_end) { @@ -7025,6 +7038,8 @@ namespace etl { ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "pop_heap requires random access iterators"); + #include "etl/private/diagnostic_array_bounds_push.h" + I last_it = ranges::next(first, last); auto length = etl::distance(first, last_it); @@ -7041,6 +7056,8 @@ namespace etl sift_down(first, decltype(length)(0), etl::distance(first, last_it), comp, proj); return ranges::next(first, last); + + #include "etl/private/diagnostic_pop.h" } template >> diff --git a/include/etl/histogram.h b/include/etl/histogram.h index 95943b76..aad21b18 100644 --- a/include/etl/histogram.h +++ b/include/etl/histogram.h @@ -296,6 +296,7 @@ namespace etl histogram(const histogram& other) { this->accumulator = other.accumulator; + start_index = other.start_index; } #if ETL_USING_CPP11 @@ -305,6 +306,7 @@ namespace etl histogram(histogram&& other) { this->accumulator = etl::move(other.accumulator); + start_index = other.start_index; } #endif @@ -314,6 +316,7 @@ namespace etl histogram& operator=(const histogram& rhs) { this->accumulator = rhs.accumulator; + start_index = rhs.start_index; return *this; } @@ -325,6 +328,7 @@ namespace etl histogram& operator=(histogram&& rhs) { this->accumulator = etl::move(rhs.accumulator); + start_index = rhs.start_index; return *this; } diff --git a/include/etl/intrusive_avl_tree.h b/include/etl/intrusive_avl_tree.h index ff92935c..bb278500 100644 --- a/include/etl/intrusive_avl_tree.h +++ b/include/etl/intrusive_avl_tree.h @@ -227,11 +227,13 @@ namespace etl return ETL_NULLPTR == base::etl_parent; } +#include "private/diagnostic_null_dereference_push.h" ETL_NODISCARD link_type* get_parent() { return static_cast(base::etl_parent); } +#include "private/diagnostic_pop.h" ETL_NODISCARD const link_type* get_parent() const diff --git a/include/etl/mem_cast.h b/include/etl/mem_cast.h index 853aa18c..35980787 100644 --- a/include/etl/mem_cast.h +++ b/include/etl/mem_cast.h @@ -115,7 +115,7 @@ namespace etl { ETL_STATIC_ASSERT(Size >= Other_Size, "Other size is too large"); - memcpy(buffer, other.buffer, Size_); + memcpy(buffer, other.data(), Other_Size); } //*********************************** @@ -126,7 +126,7 @@ namespace etl { ETL_STATIC_ASSERT(Size >= Other_Size, "RHS size is too large"); - memcpy(buffer, rhs.buffer, Size_); + memcpy(buffer, rhs.data(), Other_Size); return *this; } diff --git a/include/etl/memory.h b/include/etl/memory.h index 40dd1183..f923a6ce 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -74,6 +74,323 @@ namespace etl return etl::to_address(itr.operator->()); } +#if ETL_USING_STL && ETL_USING_CPP17 && defined(__cpp_lib_launder) + using std::launder; +#else + //***************************************************************************** + /// Obtains a pointer to the object created in the storage pointed to by p. + /// Prevents the compiler from making invalid assumptions when the lifetime of + /// an object has ended and a new object has been created in the same storage. + /// T must not be a function type nor a (possibly cv-qualified) void type. + /// https://en.cppreference.com/w/cpp/utility/launder + ///\ingroup memory + //***************************************************************************** + template + ETL_NODISCARD ETL_CONSTEXPR17 T* launder(T* p) ETL_NOEXCEPT + { + #if ETL_USING_CPP11 + // etl::is_function is only defined for C++11 and later. + ETL_STATIC_ASSERT(!etl::is_function::value, "etl::launder argument must not be a function type"); + #endif + ETL_STATIC_ASSERT(!etl::is_void::value, "etl::launder argument must not be a void type"); + + #if defined(__has_builtin) && !defined(ETL_COMPILER_MICROSOFT) + #if __has_builtin(__builtin_launder) + return __builtin_launder(p); + #else + return p; + #endif + #elif ETL_USING_GCC_COMPILER && (ETL_COMPILER_FULL_VERSION >= 70000) + // GCC 7, 8 and 9 provide __builtin_launder but not __has_builtin. + return __builtin_launder(p); + #else + return p; + #endif + } +#endif + +#if ETL_USING_STL && ETL_USING_CPP23 && defined(__cpp_lib_start_lifetime_as) + using std::start_lifetime_as; + using std::start_lifetime_as_array; +#else + namespace private_memory + { + //************************************************************************* + /// Implicitly create the objects in [p, p + n) and return a usable pointer + /// to the first one. Used by start_lifetime_as / start_lifetime_as_array. + //************************************************************************* + template + ETL_NODISCARD + inline T* start_lifetime_as_impl(void* p, size_t n) ETL_NOEXCEPT + { + if (n == 0U) + { + // No objects are created, so there is nothing to launder. + // Return the original pointer to preserve pointer identity. + return static_cast(p); + } + + #if ETL_USING_BUILTIN_MEMMOVE + void* const q = __builtin_memmove(p, p, sizeof(T) * n); + #else + void* const q = ::memmove(p, p, sizeof(T) * n); + #endif + + return etl::launder(static_cast(q)); + } + } // namespace private_memory + + //***************************************************************************** + /// Implicitly creates an object of type T in the storage pointed to by p and + /// starts its lifetime. T must be a trivially copyable (implicit-lifetime) + /// type. The storage must be suitably sized and aligned for T. + /// https://en.cppreference.com/w/cpp/memory/start_lifetime_as + ///\ingroup memory + //***************************************************************************** + template + ETL_NODISCARD + T* start_lifetime_as(void* p) ETL_NOEXCEPT + { + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "T must be trivially copyable"); + return etl::private_memory::start_lifetime_as_impl(p, 1U); + } + + template + ETL_NODISCARD + const T* start_lifetime_as(const void* p) ETL_NOEXCEPT + { + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "T must be trivially copyable"); + return etl::private_memory::start_lifetime_as_impl(const_cast(p), 1U); + } + + template + ETL_NODISCARD + volatile T* start_lifetime_as(volatile void* p) ETL_NOEXCEPT + { + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "T must be trivially copyable"); + return etl::private_memory::start_lifetime_as_impl(const_cast(p), 1U); + } + + template + ETL_NODISCARD + const volatile T* start_lifetime_as(const volatile void* p) ETL_NOEXCEPT + { + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "T must be trivially copyable"); + return etl::private_memory::start_lifetime_as_impl(const_cast(p), 1U); + } + + //***************************************************************************** + /// Implicitly creates an array of n objects of type T in the storage pointed + /// to by p and starts their lifetimes. T must be a trivially copyable + /// (implicit-lifetime) type. Returns a pointer to the first element, or a + /// pointer comparing equal to p when n is zero. + /// https://en.cppreference.com/w/cpp/memory/start_lifetime_as + ///\ingroup memory + //***************************************************************************** + template + ETL_NODISCARD + T* start_lifetime_as_array(void* p, size_t n) ETL_NOEXCEPT + { + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "T must be trivially copyable"); + return etl::private_memory::start_lifetime_as_impl(p, n); + } + + template + ETL_NODISCARD + const T* start_lifetime_as_array(const void* p, size_t n) ETL_NOEXCEPT + { + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "T must be trivially copyable"); + return etl::private_memory::start_lifetime_as_impl(const_cast(p), n); + } + + template + ETL_NODISCARD + volatile T* start_lifetime_as_array(volatile void* p, size_t n) ETL_NOEXCEPT + { + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "T must be trivially copyable"); + return etl::private_memory::start_lifetime_as_impl(const_cast(p), n); + } + + template + ETL_NODISCARD + const volatile T* start_lifetime_as_array(const volatile void* p, size_t n) ETL_NOEXCEPT + { + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "T must be trivially copyable"); + return etl::private_memory::start_lifetime_as_impl(const_cast(p), n); + } +#endif + +#if ETL_USING_STL && ETL_USING_CPP11 + using std::pointer_traits; +#else + #if ETL_USING_CPP11 + namespace private_memory + { + //************************************************************************* + /// Decomposes a pointer-like class template of the form + /// Pointer to recover its first template parameter and + /// to rebind it to a different first parameter. Left undefined for types + /// that are not such a template instantiation. + //************************************************************************* + template + struct pointer_traits_template; + + template