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