Split mbed_cxxsupport.h up - add namespace mstd

Regularise the C++ support glue, adding `<mstd_type_traits>` etc.

These include the base toolchain file, backfill `namespace std` as much
as possible for ARM C 5, and then arrange to create unified
`namespace mstd`, which can incorporate toolchain bypasses
(eg `mstd::swap` for ARM C 5, or `mstd::atomic`), and include local
implementations of post-ARM C++14 stuff.

All APIs in `namespace mstd` are intended to function as their
`namespace std` equivalent, and their presence there indicates they
are functional on all toolchains, and should be safe to use in
an Mbed OS build (including not unreasonable memory footprint).

See README.md for more info.
pull/11039/head
Kevin Bracey 2019-07-10 12:35:51 +03:00
parent de7e72befe
commit 0aab1a9ea1
15 changed files with 2727 additions and 571 deletions

View File

@ -20,11 +20,12 @@
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <mstd_memory>
#include <mstd_type_traits>
#include <mstd_utility>
#include "platform/mbed_assert.h"
#include "platform/mbed_atomic.h"
#include "platform/mbed_critical.h"
#include "platform/mbed_cxxsupport.h"
#include "platform/CriticalSectionLock.h"
/*
@ -141,16 +142,16 @@ template<typename N>
struct atomic_container_is_lock_free;
template<>
struct atomic_container_is_lock_free<uint8_t> : mbed::bool_constant<bool(MBED_ATOMIC_CHAR_LOCK_FREE)> { };
struct atomic_container_is_lock_free<uint8_t> : mstd::bool_constant<bool(MBED_ATOMIC_CHAR_LOCK_FREE)> { };
template<>
struct atomic_container_is_lock_free<uint16_t> : mbed::bool_constant<bool(MBED_ATOMIC_SHORT_LOCK_FREE)> { };
struct atomic_container_is_lock_free<uint16_t> : mstd::bool_constant<bool(MBED_ATOMIC_SHORT_LOCK_FREE)> { };
template<>
struct atomic_container_is_lock_free<uint32_t> : mbed::bool_constant<bool(MBED_ATOMIC_INT_LOCK_FREE)> { };
struct atomic_container_is_lock_free<uint32_t> : mstd::bool_constant<bool(MBED_ATOMIC_INT_LOCK_FREE)> { };
template<>
struct atomic_container_is_lock_free<uint64_t> : mbed::bool_constant<bool(MBED_ATOMIC_LLONG_LOCK_FREE)> { };
struct atomic_container_is_lock_free<uint64_t> : mstd::bool_constant<bool(MBED_ATOMIC_LLONG_LOCK_FREE)> { };
template<typename T>
using atomic_is_lock_free = atomic_container_is_lock_free<atomic_container_t<T>>;
@ -702,15 +703,15 @@ struct AtomicWithBitwise : public AtomicWithAdd<T, A> {
*/
// *INDENT-OFF*
template<typename T, typename = void>
struct AtomicSelector : mbed::type_identity<AtomicBaseRaw<T>> { };
struct AtomicSelector : mstd::type_identity<AtomicBaseRaw<T>> { };
template<typename T>
struct AtomicSelector<T, std::enable_if_t<std::is_same<bool, T>::value>>
: mbed::type_identity<AtomicBaseInt<T>> { };
: mstd::type_identity<AtomicBaseInt<T>> { };
template<typename T>
struct AtomicSelector<T, std::enable_if_t<std::is_integral<T>::value && !std::is_same<bool, T>::value>>
: mbed::type_identity<AtomicWithBitwise<T>> { };
: mstd::type_identity<AtomicWithBitwise<T>> { };
// *INDENT-ON*
template<typename T>

View File

@ -0,0 +1,65 @@
## C++ support ##
Mbed OS supports a number of toolchains, and the files here provide support
to smooth over C++ library differences.
The current baseline version is C++14, so we hope for full C++14 library
support.
Omissions are:
* areas like chrono and threads, which depend on OS support, where
retargeting is not complete.
* atomics and shared pointers, as atomic implementations for ARMv6-M
are not provided by all toolchains, and the ARMv7-M implementations include
DMB instructions we do not want/need for non-SMP.
User code should normally be able to include C++14 headers and get
most expected functionality. (But bear in mind that many C++ library
features like streams and STL containers are quite heavy and may
not be appropriate for small embnedded use).
However, ARM C 5 has only C++11 language support (at least a large subset), and
no C++11/14 library. For the headers that are totally new in C++11,
they are provided here in TOOLCHAIN_ARMC5 under their standard C++11 name.
(Eg `<array>`, `<cinttypes>`, `<initializer_list>`, `<type_traits>`).
But for headers that already exist in C++03, extensions are required.
So, to support ARM C 5, use `#include <mstd_utility>`, rather than
`#include <utility>` if you need C++11 or later features from that header.
Each `mstd_` file includes the toolchain's corresponding header file,
which will provide its facilities in `namespace std`. Any missing
C++11/C++14 facilities for ARM C 5 are also provided in `namespace std`.
Then APIs from `namespace std` are added to `namespace mstd`, with adjustment
if necessary, and APIs being omitted if not suitable for embedded use.
For example:
* `std::size_t` (`<cstddef>`) - toolchain's `std::size_t`
* `mstd::size_t` (`<mstd_cstddef>`) - alias for `std::size_t`
* `std::swap` (`<utility>`) - toolchain's `std::swap` (not move-capable for ARM C 5)
* `mstd::swap` (`<mstd_utility>`) - alias for `std::swap` or move-capable ARM C 5 replacement.
* `std::atomic` (`<atomic>`) - toolchain's `std::atomic` (not implemented for IAR ARMv6)
* `mstd::atomic` (`<mstd_atomic>`) - custom `mstd::atomic` for all toolchains
* `std::void_t` (`<type_traits>`) - toolchain's `std::void_t` if available (it's C++17 so likely not)
* `mstd::void_t` (`<mstd_type_traits>`) - alias for `std::void_t` if available, else local implementation
* `std::thread` (`<thread>`) - toolchain's `std::thread` - not available or ported
* `mstd::thread` - doesn't exist - `mstd` APIs only exist if available on all toolchains
Using `std::xxx` will generally work, but may suffer from toolchain variance. `mstd::xxx` should always be better - it will either be an alias to `std::xxx`, or work better for Mbed OS.
In portable code, when compiling for non-Mbed OS, the directive `namespace mstd == std` can be used
to cover the difference:
```C++
// my_code.c
#if TARGET_LIKE_MBED
#include <mstd_atomic>
#else
#include <atomic>
namespace mstd = std;
#endif
mstd::atomic my_atomic;
```

View File

@ -0,0 +1,68 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __move_h
#define __move_h
namespace std
{
template <typename T>
struct remove_reference { using type = T; };
template <typename T>
struct remove_reference<T &> { using type = T; };
template <typename T>
struct remove_reference<T &&> { using type = T; };
template <typename T>
using remove_reference_t = typename remove_reference<T>::type;
// Note that these implementations do not function as
// constant expressions in ARM C 5, so are not marked constexpr.
// This makes them C++11 compliant, but not C++14.
// [forward]
template <typename _TypeT>
_TypeT &&forward(remove_reference_t<_TypeT> &__t) noexcept
{
return static_cast<_TypeT &&>(__t);
}
template <typename _TypeT>
_TypeT &&forward(remove_reference_t<_TypeT> &&__t) noexcept
{
return static_cast<_TypeT &&>(__t);
}
template <typename _TypeT>
remove_reference_t<_TypeT> &&move(_TypeT &&__t) noexcept
{
return static_cast<remove_reference_t<_TypeT> &&>(__t);
}
// [utility.exchange]
template <typename _TypeT, typename _TypeU = _TypeT>
_TypeT exchange(_TypeT &__obj, _TypeU &&__new_val)
{
_TypeT __old_val = std::move(__obj);
__obj = std::forward<_TypeU>(__new_val);
return __old_val;
}
} // namespace std
#endif /* __move_h */

View File

@ -0,0 +1,171 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __array
#define __array
#include <initializer_list> // required by standard
#include <cstddef> // size_t, ptrdiff_t
#include <algorithm> // fill and swap_ranges
namespace std {
template <typename>
struct reverse_iterator;
// [array]
template <typename _TypeT, size_t _Size>
struct array {
// [array.overview]
_TypeT _C_elem[_Size];
using value_type = _TypeT;
using size_type = size_t;
using difference_type = ptrdiff_t;
using reference = _TypeT &;
using const_reference = const _TypeT &;
using pointer = _TypeT *;
using const_pointer = const _TypeT *;
using iterator = _TypeT *;
using const_iterator = const _TypeT *;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
// [array.size]
constexpr size_type size() const noexcept
{
return _Size;
}
// [array.data]
_TypeT *data() noexcept
{
return _C_elem;
}
const _TypeT *data() const noexcept
{
return _C_elem;
}
// [array.fill]
void fill(const _TypeT &value)
{
std::fill(begin(), end(), value);
}
// [array.swap]
void swap(array &__y)
{
std::swap_ranges(begin(), end(), __y.begin());
}
_TypeT &at(size_t pos)
{
MBED_ASSERT(pos < size());
return _C_elem[pos];
}
const _TypeT &at(size_t pos) const
{
MBED_ASSERT(pos < size());
return _C_elem[pos];
}
_TypeT &operator[](size_t pos)
{
return _C_elem[pos];
}
const _TypeT &operator[](size_t pos) const
{
return _C_elem[pos];
}
_TypeT &front()
{
return _C_elem[0];
}
const _TypeT &front() const
{
return _C_elem[0];
}
_TypeT &back()
{
return _C_elem[_Size - 1];
}
const _TypeT &back() const
{
return _C_elem[_Size - 1];
}
constexpr bool empty() const noexcept
{
return false;
}
constexpr size_type max_size() const noexcept
{
return _Size;
}
iterator begin() noexcept
{
return _C_elem;
}
const_iterator begin() const noexcept
{
return _C_elem;
}
const_iterator cbegin() const noexcept
{
return _C_elem;
}
iterator end() noexcept
{
return _C_elem + _Size;
}
const_iterator end() const noexcept
{
return _C_elem + _Size;
}
const_iterator cend() const noexcept
{
return _C_elem + _Size;
}
reverse_iterator rbegin() noexcept
{
return reverse_iterator(end());
}
const_reverse_iterator rbegin() const noexcept
{
return const_reverse_iterator(end());
}
const_reverse_iterator crbegin() const noexcept
{
return const_reverse_iterator(end());
}
reverse_iterator rend() noexcept
{
return reverse_iterator(begin());
}
const_reverse_iterator rend() const noexcept
{
return const_reverse_iterator(begin());
}
const_reverse_iterator crend() const noexcept
{
return const_reverse_iterator(begin());
}
};
// [array.special]
template <class _TypeT, size_t _Size>
void swap(array<_TypeT, _Size> &__x, array<_TypeT, _Size> &__y)
{
__x.swap(__y);
}
} // namespace std
#endif /* __array */

View File

@ -0,0 +1,38 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __cinttypes
#define __cinttypes
#include <cstdint>
/* Poor but conforming implementation - get everything into global namespace, then add to std */
#include "stdint.h"
#include "inttypes.h"
namespace std {
using ::imaxdiv_t;
using ::abs;
using ::div;
using ::imaxabs;
using ::imaxdiv;
using ::strtoimax;
using ::strtoumax;
using ::wcstoimax;
using ::wcstoumax;
}
#endif /* __cinttypes */

View File

@ -0,0 +1,76 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __initializer_list
#define __initializer_list
#include <cstddef>
namespace std {
// [support.initlist]
template <class _TypeE>
struct initializer_list {
using value_type = _TypeE;
using reference = const _TypeE &;
using const_reference = const _TypeE &;
using size_type = size_t;
using iterator = const _TypeE *;
using const_iterator = const _TypeE *;
// [support.initlist.cons]
constexpr initializer_list() noexcept : _C_ptr(nullptr), _C_count(0)
{
}
constexpr initializer_list(const _TypeE *p, size_type n) noexcept : _C_ptr(p), _C_count(n)
{
}
// [support.initlist.access]
constexpr const _TypeE *begin() const noexcept
{
return _C_ptr;
}
constexpr const _TypeE *end() const noexcept
{
return _C_ptr + _C_count;
}
constexpr size_t size() const noexcept
{
return _C_count;
}
private:
const _TypeE *_C_ptr;
size_t _C_count;
};
// [support.initlist.range]
template <class _TypeE>
constexpr const _TypeE *begin(initializer_list<_TypeE> il) noexcept
{
return il.begin();
}
template <class _TypeE>
constexpr const _TypeE *end(initializer_list<_TypeE> il) noexcept
{
return il.end();
}
} // namespace std
#endif /* __initializer_list */

View File

@ -0,0 +1,25 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __type_traits
#define __type_traits
// Just go straight to the main file - separating out C++11 core is not reasonable
#include <mstd_type_traits>
// Note that mstd_type_traits defines everything in std for ARM C 5 for us.
#endif /* __type_traits */

View File

@ -0,0 +1,385 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MSTD_ALGORITHM_
#define MSTD_ALGORITHM_
/* <mstd_algorithm>
*
* - provides <algorithm>
* - For ARM C 5, standard C++11/14 features:
* - std::min, std::max for std::initializer_list
* - std::all_of, std::any_of, std::none_of
* - std::find_if_not
* - std::equal (2-range forms)
* - std::copy_n, std::move, std::move_backward
* - mstd::min, mstd::max constexpr replacements
*/
#include <algorithm>
#ifdef __CC_ARM
#include <mstd_utility>
#endif
namespace mstd {
#ifdef __CC_ARM
// Really want basic min/max to be constexpr as per C++14
template <typename T>
constexpr const T &max(const T &a, const T &b)
{
return a < b ? b : a;
}
template <typename T, class Compare>
constexpr const T &max(const T &a, const T &b, Compare comp)
{
return comp(a, b) ? b : a;
}
template <typename T>
constexpr const T &min(const T &a, const T &b)
{
return b < a ? b : a;
}
template <typename T>
constexpr const T &min(const T &a, const T &b, Compare comp)
{
return comp(b, a) ? b : a;
}
// Maybe sort out C++14 constexpr for these later - these are C++11 at least
template <typename T>
T max(initializer_list<T> il)
{
return *std::max_element(begin(il), end(il));
}
template <typename T, class Compare>
T max(initializer_list<T> il, Compare comp)
{
return *std::max_element(begin(il), end(il), comp);
}
template <typename T>
T min(initializer_list<T> il)
{
return *std::min_element(begin(il), end(il));
}
template <typename T, class Compare>
T min(initializer_list<T> il, Compare comp)
{
return *std::min_element(begin(il), end(il), comp);
}
template <typename T1, typename T2>
class pair;
template <typename T>
constexpr pair<const T &, const T &> minmax(const T &a, const T &b)
{
if (b < a) {
return pair<const T &, const T &>(b, a);
} else {
return pair<const T &, const T &>(a, b);
}
}
template <typename T, class Compare>
constexpr pair<const T &, const T &> minmax(const T &a, const T &b, Compare comp)
{
if (comp(b, a)) {
return pair<const T &, const T &>(b, a);
} else {
return pair<const T &, const T &>(a, b);
}
}
#else
using std::min;
using std::max;
using std::minmax;
#endif
}
#ifdef __CC_ARM
namespace std {
// [alg.all_of]
template <class InputIterator, class Predicate>
bool all_of(InputIterator first, InputIterator last, Predicate pred)
{
for (; first != last; ++first) {
if (!pred(*first)) {
return false;
}
}
return true;
}
// [alg.any_of]
template <class InputIterator, class Predicate>
bool any_of(InputIterator first, InputIterator last, Predicate pred)
{
for (; first != last; ++first) {
if (pred(*first)) {
return true;
}
}
return false;
}
// [alg.none_of]
template <class InputIterator, class Predicate>
bool none_of(InputIterator first, InputIterator last, Predicate pred)
{
for (; first != last; ++first) {
if (pred(*first)) {
return false;
}
}
return true;
}
// [alg.find]
template<class InputIterator, class Predicate>
InputIterator find_if_not(InputIterator first, InputIterator last, Predicate pred)
{
for (; first != last; ++first) {
if (!pred(*first)) {
return first;
}
}
return first;
}
// [alg.equal]
namespace impl {
template<class RandomAccessIterator1, class RandomAccessIterator2>
bool equal(RandomAccessIterator1 first1, RandomAccessIterator1 last1,
RandomAccessIterator2 first2, RandomAccessIterator2 last2,
random_access_iterator_tag,
random_access_iterator_tag)
{
if (last1 - first1 != last2 - first2) {
return false;
}
return equal(first1, last1, first2);
}
template<class RandomAccessIterator1, class RandomAccessIterator2, class BinaryPredicate>
bool equal(RandomAccessIterator1 first1, RandomAccessIterator1 last1,
RandomAccessIterator2 first2, RandomAccessIterator2 last2,
BinaryPredicate pred,
random_access_iterator_tag,
random_access_iterator_tag)
{
if (last1 - first1 != last2 - first2) {
return false;
}
return equal(first1, last1, first2, pred);
}
template<class InputIterator1, class InputIterator2>
bool equal(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
input_iterator_tag,
input_iterator_tag)
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
if (!(*first1 == *first2)) {
return false;
}
}
return first1 == last1 && first2 == last2;
}
template<class InputIterator1, class InputIterator2, class BinaryPredicate>
bool equal(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
BinaryPredicate pred,
input_iterator_tag,
input_iterator_tag)
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
if (!pred(*first1, *first2)) {
return false;
}
}
return first1 == last1 && first2 == last2;
}
}
template<class InputIterator1, class InputIterator2>
bool equal(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2)
{
return impl::equal(first1, last1, first2, last2,
typename iterator_traits<InputIterator1>::iterator_category(),
typename iterator_traits<InputIterator2>::iterator_category());
}
template<class InputIterator1, class InputIterator2, class BinaryPredicate>
bool equal(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
BinaryPredicate pred)
{
return impl::equal(first1, last1, first2, last2, pred,
typename iterator_traits<InputIterator1>::iterator_category(),
typename iterator_traits<InputIterator2>::iterator_category());
}
// [alg.copy]
namespace impl
{
template<class RandomAccessIterator, class Size, class OutputIterator>
OutputIterator copy_n(RandomAccessIterator first, Size n, OutputIterator result, random_access_iterator_tag)
{
// presumably this should have memcpy etc optimisations
return std::copy(first, first + n, result);
}
template<class InputIterator, class Size, class OutputIterator>
OutputIterator copy_n(InputIterator first, Size n, OutputIterator result, input_iterator_tag)
{
for (Size i = 0; i < n; ++i) {
*result++ = *first++;
}
return result;
}
}
template<class InputIterator, class Size, class OutputIterator>
OutputIterator copy_n(InputIterator first, Size n, OutputIterator result)
{
return impl::copy_n(first, n, result,
typename iterator_traits<InputIterator>::iterator_category());
}
template<class InputIterator, class OutputIterator, class Predicate>
OutputIterator copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred)
{
for (; first != last; ++first) {
if (pred(*first)) {
*result++ = *first;
}
}
return result;
}
// [alg.move]
template<class InputIterator, class OutputIterator>
OutputIterator move(InputIterator first, InputIterator last, OutputIterator result)
{
while (first != last) {
*result++ = std::move(*first++);
}
return result;
}
template<class BidirectionalIterator1, class BidirectionalIterator2>
BidirectionalIterator2 move_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result)
{
while (last != first) {
*--result = std::move(*--last);
}
return result;
}
}
#endif // __CC_ARM
namespace mstd
{
using std::initializer_list;
using std::all_of;
using std::any_of;
using std::none_of;
using std::for_each;
using std::find;
using std::find_if;
using std::find_if_not;
using std::find_end;
using std::find_first_of;
using std::adjacent_find;
using std::count;
using std::count_if;
using std::mismatch;
using std::equal;
using std::search;
using std::search_n;
using std::copy;
using std::copy_n;
using std::copy_if;
using std::move;
using std::move_backward;
using std::swap_ranges;
using std::iter_swap;
using std::transform;
using std::replace;
using std::replace_if;
using std::replace_copy;
using std::replace_copy_if;
using std::fill;
using std::fill_n;
using std::generate;
using std::generate_n;
using std::remove;
using std::remove_if;
using std::remove_copy;
using std::remove_copy_if;
using std::unique;
using std::unique_copy;
using std::reverse;
using std::reverse_copy;
using std::rotate;
using std::rotate_copy;
using std::partition;
using std::stable_partition;
using std::sort;
using std::stable_sort;
using std::partial_sort;
using std::partial_sort_copy;
using std::nth_element;
using std::lower_bound;
using std::upper_bound;
using std::equal_range;
using std::binary_search;
using std::merge;
using std::inplace_merge;
using std::includes;
using std::set_union;
using std::set_intersection;
using std::set_difference;
using std::set_symmetric_difference;
using std::push_heap;
using std::pop_heap;
using std::make_heap;
using std::sort_heap;
using std::min_element;
using std::max_element;
using std::lexicographical_compare;
using std::next_permutation;
using std::prev_permutation;
}
#endif // MSTD_ALGORITHM_

View File

@ -0,0 +1,75 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MSTD_CSTDDEF_
#define MSTD_CSTDDEF_
/* <mstd_cstddef>
*
* - provides <cstddef>
* - For ARM C 5, standard C++11/14 features:
* - - adds macro replacements for alignof and alignas keywords
* - - adds missing std::nullptr_t
* - For all toolchains:
* - - MSTD_CONSTEXPR_XX_14 macros that can be used to mark
* things that are valid as constexpr only for C++14 or later,
* permitting constexpr use where ARM C 5 would reject it.
*/
#include <cstddef>
/* Macros that can be used to mark functions and objects that are
* constexpr in C++14 or later, but not in earlier versions.
*/
#if __cplusplus >= 201402
#define MSTD_CONSTEXPR_FN_14 constexpr
#define MSTD_CONSTEXPR_OBJ_14 constexpr
#else
#define MSTD_CONSTEXPR_FN_14 inline
#define MSTD_CONSTEXPR_OBJ_14 const
#endif
#ifdef __CC_ARM
// [expr.alignof]
#define alignof(T) __alignof__(T)
// [dcl.align]
// Types not supported - workaround is to use alignas(alignof(T)), which is legal anyway
#ifndef __alignas_is_defined
#define __alignas_is_defined
#define alignas(N) __attribute__((aligned(N)))
#endif
namespace std
{
// [cstddef.syn]
using nullptr_t = decltype(nullptr);
} // namespace std
#endif // __CC_ARM
namespace mstd
{
using std::size_t;
using std::ptrdiff_t;
using std::nullptr_t;
using std::max_align_t;
}
#endif // MSTD_CSTDDEF_

View File

@ -0,0 +1,508 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under tUNChe License.
*/
#ifndef MSTD_FUNCTIONAL_
#define MSTD_FUNCTIONAL_
/* <mstd_functional>
*
* - includes toolchain's <functional>
* - For ARM C 5, standard C++11/14 features:
* - std::mem_fn,
* - std::reference_wrapper, std::ref, std::cref
* - transparent std::plus<> etc
* - std::bit_and, std::bit_or, std::bit_xor, std::bit_not
* - For all toolchains, C++17/20 backports:
* - mstd::not_fn (C++17)
* - mstd::invoke (C++17)
* - mstd::unwrap_reference, mstd::unwrap_ref_decay (C++20)
*/
#include <functional>
#include <mstd_memory> // addressof
#include <mstd_utility> // forward
#include <mstd_type_traits>
#ifdef __CC_ARM
namespace std
{
// [func.memfn]
namespace impl {
template <typename R, typename T>
class mem_fn_t {
R T::* pm;
public:
mem_fn_t(R T::* pm) : pm(pm) { }
template <typename... Args>
invoke_result_t<R T::*, Args...> operator()(Args&&... args) const
{
return std::invoke(pm, std::forward<Args>(args)...);
}
};
}
template <class R, class T>
impl::mem_fn_t<R, T> mem_fn(R T::* pm)
{
return impl::mem_fn_t<R, T>(pm);
}
} // namespace std
#endif // __CC_ARM
namespace mstd {
// [func.invoke]
#if __cpp_lib_invoke >= 201411
using std::invoke;
#else
template <typename F, typename... Args>
invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
{
return impl::INVOKE(std::forward<F>(f), std::forward<Args>(args)...);
}
#endif // __cpp_lib_invoke
} // namespace mstd
#ifdef __CC_ARM
namespace std {
using mstd::invoke;
// [refwrap]
template <typename T>
class reference_wrapper {
T &FUN(T &x) noexcept { return x; }
void FUN(T &&x) = delete;
T *ptr;
public:
using type = T;
// [refwrap.const]
#if 0
// decltype doesn't seem to work well enough for this revised version
template <typename U,
typename = enable_if_t<!is_same<reference_wrapper, decay_t<U>>::value &&
!is_void<decltype(FUN(declval<U>()))>::value>>
reference_wrapper(U&& x) //noexcept(noexcept(FUN(declval<U>())))
: ptr(addressof(FUN(forward<U>(x)))) { }
#else
reference_wrapper(T &x) noexcept : ptr(addressof(x)) { }
reference_wrapper(T &&x) = delete;
#endif
reference_wrapper(const reference_wrapper &) noexcept = default;
// [refwrap.assign]
reference_wrapper &operator=(const reference_wrapper &) noexcept = default;
// [refwrap.access]
operator T &() const noexcept { return *ptr; }
T &get() const noexcept { return *ptr; }
// [refwrap.invoke]
template <typename... ArgTypes>
invoke_result_t<T &, ArgTypes...> operator()(ArgTypes&&... args) const
{
return std::invoke(get(), forward<ArgTypes>(args)...);
}
};
// [refwrap.helpers]
template <typename T>
reference_wrapper<T> ref(T &t) noexcept
{
return reference_wrapper<T>(t);
}
template <typename T>
reference_wrapper<T> ref(reference_wrapper<T> &t) noexcept
{
return ref(t.get());
}
template <typename T>
void ref(const T &&) = delete;
template <typename T>
reference_wrapper<const T> cref(const T &t) noexcept
{
return reference_wrapper<const T>(t);
}
template <typename T>
reference_wrapper<const T> cref(reference_wrapper<T> &t) noexcept
{
return cref(t.get());
}
template <typename T>
void cref(const T &&) = delete;
// ARMC5 has basic plus<T> etc - we can add plus<void> specialisations;
// and the language rules allow us to add the default void arguments missing
// from its header.
template <typename T = void> struct plus;
template <typename T = void> struct minus;
template <typename T = void> struct multiplies;
template <typename T = void> struct divides;
template <typename T = void> struct modulus;
template <typename T = void> struct negate;
template <typename T = void> struct equal_to;
template <typename T = void> struct not_equal_to;
template <typename T = void> struct greater;
template <typename T = void> struct less;
template <typename T = void> struct greater_equal;
template <typename T = void> struct less_equal;
template <typename T = void> struct logical_and;
template <typename T = void> struct logical_or;
template <typename T = void> struct logical_not;
// [arithmetic.operations.plus]
template <>
struct plus<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) + std::forward<U>(u))
{
return std::forward<T>(t) + std::forward<U>(u);
}
};
// [arithmetic.operations.minus]
template <>
struct minus<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) - std::forward<U>(u))
{
return std::forward<T>(t) - std::forward<U>(u);
}
};
// [arithmetic.operations.multiplies]
template <>
struct multiplies<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) * std::forward<U>(u))
{
return std::forward<T>(t) * std::forward<U>(u);
}
};
// [arithmetic.operations.divides]
template <>
struct divides<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) / std::forward<U>(u))
{
return std::forward<T>(t) / std::forward<U>(u);
}
};
// [arithmetic.operations.modulus]
template <>
struct modulus<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) % std::forward<U>(u))
{
return std::forward<T>(t) % std::forward<U>(u);
}
};
// [arithmetic.operations.negate]
template <>
struct negate<void> {
using is_transparent = true_type;
template <typename T>
constexpr auto operator()(T&& t) const -> decltype(-std::forward<T>(t))
{
return -std::forward<T>(t);
}
};
// [comparisons.equal_to]
template <>
struct equal_to<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) == std::forward<U>(u))
{
return std::forward<T>(t) == std::forward<U>(u);
}
};
// [comparisons.not_equal_to]
template <>
struct not_equal_to<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) != std::forward<U>(u))
{
return std::forward<T>(t) != std::forward<U>(u);
}
};
// [comparisons.greater]
template <>
struct greater<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) > std::forward<U>(u))
{
return std::forward<T>(t) > std::forward<U>(u);
}
};
// [comparisons.less]
template <>
struct less<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) < std::forward<U>(u))
{
return std::forward<T>(t) < std::forward<U>(u);
}
};
// [comparisons.greater_equal]
template <>
struct greater_equal<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) >= std::forward<U>(u))
{
return std::forward<T>(t) >= std::forward<U>(u);
}
};
// [comparisons.less_equal]
template <>
struct less_equal<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) <= std::forward<U>(u))
{
return std::forward<T>(t) <= std::forward<U>(u);
}
};
// [logical.operations.and]
template <>
struct logical_and<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) && std::forward<U>(u))
{
return std::forward<T>(t) && std::forward<U>(u);
}
};
// [logical.operations.or]
template <>
struct logical_or<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) || std::forward<U>(u))
{
return std::forward<T>(t) || std::forward<U>(u);
}
};
// [logical.operations.not]
template <>
struct logical_not<void> {
using is_transparent = true_type;
template <typename T>
constexpr auto operator()(T&& t) const -> decltype(!std::forward<T>(t))
{
return !std::forward<T>(t);
}
};
// [bitwise.operations.and]
template <typename T = void>
struct bit_and {
constexpr T operator()(const T &x, const T &y) const
{
return x & y;
}
};
template <>
struct bit_and<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t,U&& u) const -> decltype(std::forward<T>(t) & std::forward<U>(u))
{
return std::forward<T>(t) & std::forward<U>(u);
}
};
// [bitwise.operations.or]
template <typename T = void>
struct bit_or {
constexpr T operator()(const T &x, const T &y) const
{
return x & y;
}
};
template <>
struct bit_or<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t,U&& u) const -> decltype(std::forward<T>(t) | std::forward<U>(u))
{
return std::forward<T>(t) | std::forward<U>(u);
}
};
// [bitwise.operations.xor]
template <typename T = void>
struct bit_xor {
constexpr T operator()(const T &x, const T &y) const
{
return x ^ y;
}
};
template <>
struct bit_xor<void> {
using is_transparent = true_type;
template <typename T, typename U>
constexpr auto operator()(T&& t,U&& u) const -> decltype(std::forward<T>(t) ^ std::forward<U>(u))
{
return std::forward<T>(t) ^ std::forward<U>(u);
}
};
// [bitwise.operations.not]
template <typename T = void>
struct bit_not {
constexpr T operator()(const T &arg) const
{
return ~arg;
}
};
template <>
struct bit_not<void> {
using is_transparent = true_type;
template <typename T>
constexpr auto operator()(T&& arg) const -> decltype(~std::forward<T>(arg))
{
return ~std::forward<T>(arg);
}
};
} // namespace std
#endif // __CC_ARM
namespace mstd {
using std::reference_wrapper;
using std::ref;
using std::cref;
using std::plus;
using std::minus;
using std::multiplies;
using std::divides;
using std::modulus;
using std::negate;
using std::equal_to;
using std::not_equal_to;
using std::greater;
using std::less;
using std::greater_equal;
using std::less_equal;
using std::logical_and;
using std::logical_or;
using std::logical_not;
using std::bit_and;
using std::bit_or;
using std::bit_xor;
using std::bit_not;
#if __cpp_lib_not_fn >= 201603
using std::not_fn;
#else
namespace impl {
// [func.not_fn]
template <typename F>
class not_fn_t {
std::decay_t<F> fn;
public:
explicit not_fn_t(F&& f) : fn(std::forward<F>(f)) { }
not_fn_t(const not_fn_t &other) = default;
not_fn_t(not_fn_t &&other) = default;
template<typename... Args>
auto operator()(Args&&... args) & -> decltype(!std::declval<invoke_result_t<std::decay_t<F> &, Args...>>())
{
return !mstd::invoke(fn, std::forward<Args>(args)...);
}
template<typename... Args>
auto operator()(Args&&... args) const & -> decltype(!std::declval<invoke_result_t<std::decay_t<F> const &, Args...>>())
{
return !mstd::invoke(fn, std::forward<Args>(args)...);
}
template<typename... Args>
auto operator()(Args&&... args) && -> decltype(!std::declval<invoke_result_t<std::decay_t<F>, Args...>>())
{
return !mstd::invoke(std::move(fn), std::forward<Args>(args)...);
}
template<typename... Args>
auto operator()(Args&&... args) const && -> decltype(!std::declval<invoke_result_t<std::decay_t<F> const, Args...>>())
{
return !mstd::invoke(std::move(fn), std::forward<Args>(args)...);
}
};
}
template <typename F>
impl::not_fn_t<F> not_fn_t(F&& f)
{
return impl::not_fn_t<F>(std::forward<F>(f));
}
#endif
/* C++20 unwrap_reference */
template <typename T>
struct unwrap_reference : type_identity<T> { };
template <typename T>
struct unwrap_reference<std::reference_wrapper<T>> : type_identity<T &> { };
template <typename T>
using unwrap_reference_t = typename unwrap_reference<T>::type;
/* C++20 unwrap_ref_decay */
template <typename T>
struct unwrap_ref_decay : unwrap_reference<std::decay_t<T>> { };
template <typename T>
using unwrap_ref_decay_t = typename unwrap_ref_decay<T>::type;
}
#endif // MSTD_FUNCTIONAL_

View File

@ -0,0 +1,460 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MSTD_ITERATOR_
#define MSTD_ITERATOR_
/* <mstd_iterator>
*
* - includes toolchain's <iterator>
* - For ARM C 5, C++11/14 features:
* - std::begin, std::end, etc
* - std::make_reverse_iterator
* - std::move_iterator, std::make_move_iterator
* - For all toolchains, C++17/20 backports:
* - mbed::size
* - mbed::ssize
* - mbed::empty
* - mbed::data
*/
#include <iterator>
#include <mstd_type_traits>
#ifdef __CC_ARM
#include <mstd_cstddef> // size_t
namespace std {
template <typename E>
struct initializer_list;
// [iterator.operations]
template <typename ForwardIterator>
ForwardIterator next(ForwardIterator x, typename iterator_traits<ForwardIterator>::difference_type n = 1)
{
advance(x, n);
return x;
}
template <typename BidirectionalIterator>
BidirectionalIterator prev(BidirectionalIterator x, typename iterator_traits<BidirectionalIterator>::difference_type n = 1)
{
advance(x, -n);
return x;
}
// [reverse.iter.make]
template <typename Iterator>
reverse_iterator<Iterator> make_reverse_iterator(Iterator i)
{
return reverse_iterator<Iterator>(i);
}
// [move.iterators]
template <typename Iterator>
class move_iterator {
Iterator current;
using R = typename iterator_traits<Iterator>::reference;
public:
using iterator_type = Iterator;
using iterator_category = typename iterator_traits<Iterator>::iterator_category;
using value_type = typename iterator_traits<Iterator>::value_type;
using difference_type = typename iterator_traits<Iterator>::difference_type;
using pointer = Iterator;
using reference = conditional_t<is_reference<R>::value,
remove_reference_t<R> &&,
R>;
// [move.iter.op.const]
constexpr move_iterator() : current() { }
constexpr explicit move_iterator(Iterator i) : current(i) { }
template <typename U>
constexpr move_iterator(const move_iterator<U> &u) : current(u.base()) { }
// [move.iter.op=]
template <typename U>
move_iterator &operator=(const move_iterator<U> &u)
{
current = u.base();
return *this;
}
// [move.iter.op.conv]
constexpr Iterator base() const
{
return current;
}
// [move.iter.op.star]
constexpr reference operator*() const
{
return static_cast<reference>(*current);
}
// [move.iter.op.ref]
constexpr pointer operator->() const
{
return current;
}
// [move.iter.op.incr]
move_iterator &operator++()
{
++current;
return *this;
}
move_iterator operator++(int)
{
move_iterator tmp = *this;
++current;
return tmp;
}
// [move.iter.op.decr]
move_iterator &operator--()
{
--current;
return *this;
}
move_iterator operator--(int)
{
move_iterator tmp = *this;
--current;
return tmp;
}
// [move.iter.op.+]
constexpr move_iterator operator+(difference_type n) const
{
return move_iterator(current + n);
}
// [move.iter.op.+=]
move_iterator &operator+=(difference_type n)
{
current += n;
return *this;
}
// [move.iter.op.-]
constexpr move_iterator operator-(difference_type n) const
{
return move_iterator(current - n);
}
// [move.iter.op.-=]
move_iterator &operator-=(difference_type n)
{
current -= n;
return *this;
}
// [move.iter.op.index]
constexpr auto operator[](difference_type n) const -> decltype(std::move(current[n]))
{
return std::move(current[n]);
}
};
// [move.iter.op.cmp]
template <typename Iterator1, typename Iterator2>
bool operator==(const move_iterator<Iterator1> &x, const move_iterator<Iterator2> &y)
{
return x.base() == y.base();
}
template <typename Iterator1, typename Iterator2>
bool operator!=(const move_iterator<Iterator1> &x, const move_iterator<Iterator2> &y)
{
return !(x == y);
}
template <typename Iterator1, typename Iterator2>
bool operator<(const move_iterator<Iterator1> &x, const move_iterator<Iterator2> &y)
{
return x.base() < y.base();
}
template <typename Iterator1, typename Iterator2>
bool operator<=(const move_iterator<Iterator1> &x, const move_iterator<Iterator2> &y)
{
return !(y < x);
}
template <typename Iterator1, typename Iterator2>
bool operator>(const move_iterator<Iterator1> &x, const move_iterator<Iterator2> &y)
{
return y < x;
}
template <typename Iterator1, typename Iterator2>
bool operator>=(const move_iterator<Iterator1> &x, const move_iterator<Iterator2> &y)
{
return !(x < y);
}
// [move.iter.nonmember]
template <typename Iterator1, typename Iterator2>
auto operator-(const move_iterator<Iterator1> &x,
const move_iterator<Iterator2> &y) -> decltype(x.base() - y.base())
{
return x.base() - y.base();
}
template <typename Iterator>
move_iterator<Iterator> operator+(typename move_iterator<Iterator>::difference_type n, const move_iterator<Iterator> &x)
{
return x + n;
}
template <typename Iterator>
constexpr move_iterator<Iterator> make_move_iterator(Iterator i)
{
return move_iterator<Iterator>(i);
}
// [iterator.range]
template <class C>
constexpr auto begin(C &c) -> decltype(c.begin())
{
return c.begin();
}
template <class C>
constexpr auto begin(const C &c) -> decltype(c.begin())
{
return c.begin();
}
template <class C>
constexpr auto end(C &c) -> decltype(c.end())
{
return c.end();
}
template <class C>
constexpr auto end(const C &c) -> decltype(c.end())
{
return c.end();
}
template <class T, size_t N>
constexpr T *begin(T (&array)[N]) noexcept
{
return array;
}
template <class T, size_t N>
constexpr T *end(T (&array)[N]) noexcept
{
return array + N;
}
template <class C>
constexpr auto cbegin(const C &c) noexcept(noexcept(std::begin(c))) -> decltype(std::begin(c))
{
return std::begin(c);
}
template <class C>
constexpr auto cend(const C &c) noexcept(noexcept(std::end(c))) -> decltype(std::end(c))
{
return std::end(c);
}
template <class C>
constexpr auto rbegin(C &c) -> decltype(c.rbegin())
{
return c.rbegin();
}
template <class C>
constexpr auto rbegin(const C &c) -> decltype(c.rbegin())
{
return c.rbegin();
}
template <class C>
constexpr auto rend(C &c) -> decltype(c.rend())
{
return c.rend();
}
template <class C>
constexpr auto rend(const C &c) -> decltype(c.rend())
{
return c.rend();
}
template <class T, size_t N>
reverse_iterator<T *> rbegin(T (&array)[N])
{
return reverse_iterator<T *>(array + N);
}
template <class T, size_t N>
reverse_iterator<T *> rend(T (&array)[N])
{
return reverse_iterator<T *>(array);
}
template <class E>
reverse_iterator<const E *> rbegin(initializer_list<E> il)
{
return reverse_iterator<const E *>(il.end());
}
template <class E>
reverse_iterator<const E *> rend(initializer_list<E> il)
{
return reverse_iterator<const E *>(il.end());
}
template <class C>
constexpr auto crbegin(const C &c) -> decltype(std::rbegin(c))
{
return std::rbegin(c);
}
template <class C>
constexpr auto crend(const C &c) -> decltype(std::rend(c))
{
return std::rend(c);
}
} // namespace std
#endif
namespace mstd {
using std::initializer_list;
using std::iterator_traits;
// omitting deprecated std::iterator
using std::input_iterator_tag;
using std::output_iterator_tag;
using std::forward_iterator_tag;
using std::bidirectional_iterator_tag;
using std::random_access_iterator_tag;
using std::advance;
using std::distance;
using std::next;
using std::prev;
using std::reverse_iterator;
using std::make_reverse_iterator;
using std::back_insert_iterator;
using std::back_inserter;
using std::front_insert_iterator;
using std::front_inserter;
using std::insert_iterator;
using std::inserter;
using std::move_iterator;
using std::make_move_iterator;
using std::istream_iterator;
using std::ostream_iterator;
using std::istreambuf_iterator;
using std::ostreambuf_iterator;
using std::begin;
using std::end;
using std::cbegin;
using std::cend;
using std::rbegin;
using std::rend;
using std::crbegin;
using std::crend;
#if __cpp_lib_nonmember_container_access >= 201411
using std::size;
using std::empty;
using std::data;
#else
// [iterator.container]
template <class C>
constexpr auto size(const C &c) -> decltype(c.size())
{
return c.size();
}
template <class T, size_t N>
constexpr size_t size(const T (&)[N]) noexcept
{
return N;
}
template <class C>
constexpr auto empty(const C &c) -> decltype(c.empty())
{
return c.empty();
}
template <class T, size_t N>
constexpr bool empty(T (&)[N]) noexcept
{
return false;
}
template <class E>
constexpr bool empty(initializer_list<E> il)
{
return il.size() == 0;
}
template <class C>
constexpr auto data(C &c) -> decltype(c.data())
{
return c.data();
}
template <class C>
constexpr auto data(const C &c) -> decltype(c.data())
{
return c.data();
}
template <class T, size_t N>
constexpr T *data(T (&array)[N]) noexcept
{
return array;
}
template <class E>
constexpr const E *data(initializer_list<E> il)
{
return il.begin();
}
#endif
// C++20
template <class C>
constexpr auto ssize(const C &c) -> common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>
{
return static_cast<common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>>(c.size());
}
template <class T, ptrdiff_t N>
constexpr ptrdiff_t ssize(const T (&)[N]) noexcept
{
return N;
}
}
#endif // MSTD_ITERATOR_

View File

@ -0,0 +1,72 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MSTD_MEMORY_
#define MSTD_MEMORY_
/* <mstd_memory>
*
* - includes toolchain's <memory>
* - For ARM C 5, C++11/14 features:
* - std::align
* - std::addressof
*/
#include <memory>
#ifdef __CC_ARM
#include <cstddef> // size_t, ptrdiff_t
namespace std
{
// [ptr.align]
inline void *align(size_t alignment, size_t size, void *&ptr, size_t &space) noexcept
{
/* Behavior is undefined if alignment is not a power of 2 */
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
uintptr_t new_addr = (addr + (alignment - 1)) & ~(alignment - 1);
uintptr_t pad = new_addr - addr;
if (pad + size <= space) {
space -= pad;
ptr = reinterpret_cast<void *>(new_addr);
return ptr;
} else {
return nullptr;
}
}
// [specialized.addressof]
template <typename T>
T *addressof(T &arg) noexcept
{
return reinterpret_cast<T *>(const_cast<char *>(&reinterpret_cast<const volatile char &>(arg)));
}
} // namespace std
#endif // __CC_ARM
namespace mstd {
using std::allocator;
using std::uninitialized_copy;
using std::uninitialized_fill;
using std::uninitialized_fill_n;
using std::addressof;
using std::align;
}
#endif // MSTD_MEMORY_

View File

@ -0,0 +1,337 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MSTD_UTILITY_
#define MSTD_UTILITY_
/* <mstd_utility>
*
* - includes toolchain's <utility>
* - For ARM C 5, standard C++11/14 features:
* - include <initializer_list>
* - std::move, std::forward, std::exchange
* - std::declval
* - std::integer_sequence
* - include <algorithm> to get default std::swap
* - mstd::swap - substitute for std::swap that can move
* - std::swap(array)
* - Swap assistance, to ensure moves happen on ARM C 5
* - mstd::swap - alias for std::swap, or a local moving implementation for ARM C 5
* - For all toolchains, C++17/20 backports:
* - mstd::as_const
*/
#include <utility>
#ifdef __CC_ARM
#include <_move.h>
#include <algorithm> // to get std::swap
#include <cstddef>
#include <initializer_list>
#include <cstdint> // uintmax_t
#include <mstd_type_traits>
#endif
namespace mstd {
// [utility.swap] - ARMC5's std::swap is not C++11, so make sure mstd::swap is
// So to get ADL-aware lookup with good default swap, users should do `using mstd::swap; swap(x, y);`.
#ifdef __CC_ARM
template <class _TypeT>
void swap(_TypeT &__a, _TypeT &__b)
noexcept(__is_nothrow_constructible(_TypeT, _TypeT &&) && __is_nothrow_assignable(_TypeT &, _TypeT &&))
{
_TypeT __tmp = std::move(__a);
__a = std::move(__b);
__b = std::move(__tmp);
}
template <class _TypeT, std::size_t _Size>
void swap(_TypeT (&__a)[_Size], _TypeT (&__b)[_Size])
noexcept(noexcept(swap(*__a, *__b)))
{
_TypeT *__ptr_a = __a, *__ptr_b = __b;
const _TypeT * const __end_a = __a + _Size;
for (; __ptr_a != __end_a; ++__ptr_a, ++__ptr_b) {
swap(*__ptr_a, *__ptr_b);
}
}
#else
using std::swap;
#endif
} // namespace mstd
#ifdef __CC_ARM
namespace std {
template <typename _TypeT>
constexpr conditional_t<!is_nothrow_move_constructible<_TypeT>::value && is_copy_constructible<_TypeT>::value,
const _TypeT &, _TypeT &&>
move_if_noexcept(_TypeT &__t) noexcept
{
return std::move(__t);
}
// [declval]
// is provided by mstd_type_traits, which we include
// [utility.swap] - ARMC5's basic swap in <algorithm> does not move, but
// we can add this std overload for arrays, and send it to our mstd moving version
template <class _TypeT, std::size_t _Size>
void swap(_TypeT (&__a)[_Size], _TypeT (&__b)[_Size])
noexcept(noexcept(mstd::swap(*__a, *__b)))
{
mstd::swap(__a, __b);
}
// [intseq.intseq]
template <typename T, T... I>
struct integer_sequence {
using value_type = T;
static constexpr size_t size() noexcept { return sizeof...(I); }
};
template <size_t... I>
using index_sequence = integer_sequence<size_t, I...>;
// [intseq.make]
namespace impl {
template <typename seq1, typename seq2>
struct combine_umax_sequences;
template <uintmax_t... seq1, uintmax_t... seq2>
struct combine_umax_sequences<integer_sequence<uintmax_t, seq1...>, integer_sequence<uintmax_t, seq2...>>
: mstd::type_identity<integer_sequence<uintmax_t, seq1..., sizeof...(seq1) + seq2...>> { };
template <uintmax_t N>
struct make_umax_sequence : combine_umax_sequences<typename make_umax_sequence<N / 2>::type,
typename make_umax_sequence<N - N / 2>::type> { };
template <>
struct make_umax_sequence<1> : mstd::type_identity<integer_sequence<uintmax_t, 0>> { };
template <>
struct make_umax_sequence<0> : mstd::type_identity<integer_sequence<uintmax_t>> { };
template <typename T, T N, typename useq = typename make_umax_sequence<N>::type>
struct make_integer_sequence;
template <typename T, T N, uintmax_t... I>
struct make_integer_sequence<T, N, integer_sequence<uintmax_t, I...>> {
static_assert(N >= 0, "negative integer sequence");
using type = integer_sequence<T, static_cast<T>(I)...>;
};
}
template <typename T, T N>
using make_integer_sequence = typename impl::make_integer_sequence<T, N>::type;
template <size_t N>
using make_index_sequence = make_integer_sequence<size_t, N>;
template <typename... T>
using index_sequence_for = make_index_sequence<sizeof...(T)>;
// [pair.astuple]
template <typename>
struct tuple_size;
template <size_t, typename>
struct tuple_element;
template <size_t I, typename T>
using tuple_element_t = typename tuple_element<I, T>::type;
template <typename T1, typename T2>
struct tuple_size<pair<T1, T2>> : integral_constant<size_t, 2> { };
template <typename T1, typename T2>
struct tuple_element<0, pair<T1, T2>> : mstd::type_identity<T1> { };
template <typename T1, typename T2>
struct tuple_element<1, pair<T1, T2>> : mstd::type_identity<T2> { };
namespace impl{
template <size_t I>
struct pair_getter;
template <>
struct pair_getter<0> {
template <typename T1, typename T2>
static T1 &get(pair<T1, T2> &p)
{
return p.first;
}
template <typename T1, typename T2>
static const T1 &cget(const pair<T1, T2> &p)
{
return p.first;
}
template <typename T1, typename T2>
static T1 &&get_move(pair<T1, T2> &&p)
{
return std::forward<T1>(p.first);
}
template <typename T1, typename T2>
static const T1 &&cget_move(const pair<T1, T2> &&p)
{
return std::forward<T1>(p.first);
}
};
template <>
struct pair_getter<1> {
template <typename T1, typename T2>
static T2 &get(pair<T1, T2> &p)
{
return p.second;
}
template <typename T1, typename T2>
static const T2 &cget(const pair<T1, T2> &p)
{
return p.second;
}
template <typename T1, typename T2>
static T2 &&get_move(pair<T1, T2> &&p)
{
return std::forward<T2>(p.second);
}
template <typename T1, typename T2>
static const T2 &&cget_move(const pair<T1, T2> &&p)
{
return std::forward<T2>(p.second);
}
};
}
template <size_t I, typename T1, typename T2>
constexpr tuple_element_t<I, pair<T1, T2>> &get(pair<T1, T2> &p) noexcept
{
return impl::pair_getter<I>::get(p);
}
template <size_t I, typename T1, typename T2>
constexpr const tuple_element_t<I, pair<T1, T2>> &get(const pair<T1, T2> &p) noexcept
{
return impl::pair_getter<I>::cget(p);
}
template <size_t I, typename T1, typename T2>
constexpr tuple_element_t<I, pair<T1, T2>> &&get(pair<T1, T2> &&p) noexcept
{
return impl::pair_getter<I>::get_move(std::move(p));
}
template <size_t I, typename T1, typename T2>
constexpr const tuple_element_t<I, pair<T1, T2>> &&get(const pair<T1, T2> &&p) noexcept
{
return impl::pair_getter<I>::cget_move(std::move(p));
}
template <typename T1, typename T2>
constexpr T1 &get(pair<T1, T2> &p) noexcept
{
return p.first;
}
template <typename T1, typename T2>
constexpr const T1 &get(const pair<T1, T2> &p) noexcept
{
return p.first;
}
template <typename T1, typename T2>
constexpr T1 &&get(pair<T1, T2> &&p) noexcept
{
return p.first;
}
template <typename T1, typename T2>
constexpr const T1 &&get(const pair<T1, T2> &&p) noexcept
{
return p.first;
}
template <typename T2, typename T1>
constexpr T2 &get(pair<T1, T2> &p) noexcept
{
return p.second;
}
template <typename T2, typename T1>
constexpr const T2 &get(const pair<T1, T2> &p) noexcept
{
return p.second;
}
template <typename T2, typename T1>
constexpr T2 &&get(pair<T1, T2> &&p) noexcept
{
return p.second;
}
template <typename T2, typename T1>
constexpr const T2 &&get(const pair<T1, T2> &&p) noexcept
{
return p.second;
}
} // namespace std
#endif
namespace mstd {
namespace rel_ops { using namespace std::rel_ops; }
using std::initializer_list;
using std::exchange;
using std::forward;
using std::move;
// No exceptions in mbed OS
template <typename T>
T &&move_if_noexcept(T &t) noexcept
{
return mstd::move(t);
}
using std::declval;
using std::make_pair;
using std::get;
using std::pair;
using std::integer_sequence;
// C++17 [utility.as_const] */
#if __cpp_lib_as_const >= 201510
using std::as_const;
#else
template <typename _TypeT>
constexpr std::add_const_t<_TypeT> &as_const(_TypeT &__t) noexcept
{
return __t;
}
template <typename _TypeT>
void as_const(_TypeT &&) = delete;
#endif
} // namespace mstd
#endif // MSTD_UTILITY_

View File

@ -880,7 +880,7 @@ MBED_FORCEINLINE uint64_t core_util_atomic_fetch_xor_explicit_u64(volatile uint6
#ifdef __cplusplus
} // extern "C"
#include "mbed_cxxsupport.h"
#include <mstd_type_traits>
// For each operation, two overloaded templates:
// * one for non-pointer types, which has implementations based on the
@ -900,65 +900,65 @@ template<typename T> T core_util_atomic_load(const volatile T *valuePtr) noexcep
/** \copydoc core_util_atomic_load_u8 */
template<typename T> T core_util_atomic_load(const T *valuePtr) noexcept;
/** \copydoc core_util_atomic_store_u8 */
template<typename T> void core_util_atomic_store(volatile T *valuePtr, mbed::type_identity_t<T> desiredValue) noexcept;
template<typename T> void core_util_atomic_store(volatile T *valuePtr, mstd::type_identity_t<T> desiredValue) noexcept;
/** \copydoc core_util_atomic_store_u8 */
template<typename T> void core_util_atomic_store(T *valuePtr, mbed::type_identity_t<T> desiredValue) noexcept;
template<typename T> void core_util_atomic_store(T *valuePtr, mstd::type_identity_t<T> desiredValue) noexcept;
/** \copydoc core_util_atomic_exchange_u8 */
template<typename T> T core_util_atomic_exchange(volatile T *ptr, mbed::type_identity_t<T> desiredValue) noexcept;
template<typename T> T core_util_atomic_exchange(volatile T *ptr, mstd::type_identity_t<T> desiredValue) noexcept;
/** \copydoc core_util_atomic_cas_u8 */
template<typename T> bool core_util_atomic_compare_exchange_strong(volatile T *ptr, mbed::type_identity_t<T> *expectedCurrentValue, mbed::type_identity_t<T> desiredValue) noexcept;
template<typename T> bool core_util_atomic_compare_exchange_strong(volatile T *ptr, mstd::type_identity_t<T> *expectedCurrentValue, mstd::type_identity_t<T> desiredValue) noexcept;
/** \copydoc core_util_atomic_compare_exchange_weak_u8 */
template<typename T> bool core_util_atomic_compare_exchange_weak(volatile T *ptr, mbed::type_identity_t<T> *expectedCurrentValue, mbed::type_identity_t<T> desiredValue) noexcept;
template<typename T> bool core_util_atomic_compare_exchange_weak(volatile T *ptr, mstd::type_identity_t<T> *expectedCurrentValue, mstd::type_identity_t<T> desiredValue) noexcept;
/** \copydoc core_util_fetch_add_u8 */
template<typename T> T core_util_atomic_fetch_add(volatile T *valuePtr, mbed::type_identity_t<T> arg) noexcept;
template<typename T> T core_util_atomic_fetch_add(volatile T *valuePtr, mstd::type_identity_t<T> arg) noexcept;
/** \copydoc core_util_fetch_sub_u8 */
template<typename T> T core_util_atomic_fetch_sub(volatile T *valuePtr, mbed::type_identity_t<T> arg) noexcept;
template<typename T> T core_util_atomic_fetch_sub(volatile T *valuePtr, mstd::type_identity_t<T> arg) noexcept;
/** \copydoc core_util_fetch_and_u8 */
template<typename T> T core_util_atomic_fetch_and(volatile T *valuePtr, mbed::type_identity_t<T> arg) noexcept;
template<typename T> T core_util_atomic_fetch_and(volatile T *valuePtr, mstd::type_identity_t<T> arg) noexcept;
/** \copydoc core_util_fetch_or_u8 */
template<typename T> T core_util_atomic_fetch_or(volatile T *valuePtr, mbed::type_identity_t<T> arg) noexcept;
template<typename T> T core_util_atomic_fetch_or(volatile T *valuePtr, mstd::type_identity_t<T> arg) noexcept;
/** \copydoc core_util_fetch_xor_u8 */
template<typename T> T core_util_atomic_fetch_xor(volatile T *valuePtr, mbed::type_identity_t<T> arg) noexcept;
template<typename T> T core_util_atomic_fetch_xor(volatile T *valuePtr, mstd::type_identity_t<T> arg) noexcept;
/** \copydoc core_util_atomic_load_explicit_u8 */
template<typename T> T core_util_atomic_load_explicit(const volatile T *valuePtr, mbed_memory_order order) noexcept;
/** \copydoc core_util_atomic_load_explicit_u8 */
template<typename T> T core_util_atomic_load_explicit(const T *valuePtr, mbed_memory_order order) noexcept;
/** \copydoc core_util_atomic_store_explicit_u8 */
template<typename T> void core_util_atomic_store_explicit(volatile T *valuePtr, mbed::type_identity_t<T> desiredValue, mbed_memory_order order) noexcept;
template<typename T> void core_util_atomic_store_explicit(volatile T *valuePtr, mstd::type_identity_t<T> desiredValue, mbed_memory_order order) noexcept;
/** \copydoc core_util_atomic_store_explicit_u8 */
template<typename T> void core_util_atomic_store_explicit(T *valuePtr, mbed::type_identity_t<T> desiredValue, mbed_memory_order order) noexcept;
template<typename T> void core_util_atomic_store_explicit(T *valuePtr, mstd::type_identity_t<T> desiredValue, mbed_memory_order order) noexcept;
/** \copydoc core_util_atomic_exchange_explicit_u8 */
template<typename T> T core_util_atomic_exchange_explicit(volatile T *ptr, mbed::type_identity_t<T> desiredValue, mbed_memory_order order) noexcept;
template<typename T> T core_util_atomic_exchange_explicit(volatile T *ptr, mstd::type_identity_t<T> desiredValue, mbed_memory_order order) noexcept;
/** \copydoc core_util_atomic_cas_explicit_u8 */
template<typename T> bool core_util_atomic_compare_exchange_strong_explicit(volatile T *ptr, mbed::type_identity_t<T> *expectedCurrentValue, mbed::type_identity_t<T> desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
template<typename T> bool core_util_atomic_compare_exchange_strong_explicit(volatile T *ptr, mstd::type_identity_t<T> *expectedCurrentValue, mstd::type_identity_t<T> desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */
template<typename T> bool core_util_atomic_compare_exchange_weak_explicit(volatile T *ptr, mbed::type_identity_t<T> *expectedCurrentValue, mbed::type_identity_t<T> desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
template<typename T> bool core_util_atomic_compare_exchange_weak_explicit(volatile T *ptr, mstd::type_identity_t<T> *expectedCurrentValue, mstd::type_identity_t<T> desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
/** \copydoc core_util_fetch_add_explicit_u8 */
template<typename T> T core_util_atomic_fetch_add_explicit(volatile T *valuePtr, mbed::type_identity_t<T> arg, mbed_memory_order order) noexcept;
template<typename T> T core_util_atomic_fetch_add_explicit(volatile T *valuePtr, mstd::type_identity_t<T> arg, mbed_memory_order order) noexcept;
/** \copydoc core_util_fetch_sub_explicit_u8 */
template<typename T> T core_util_atomic_fetch_sub_explicit(volatile T *valuePtr, mbed::type_identity_t<T> arg, mbed_memory_order order) noexcept;
template<typename T> T core_util_atomic_fetch_sub_explicit(volatile T *valuePtr, mstd::type_identity_t<T> arg, mbed_memory_order order) noexcept;
/** \copydoc core_util_fetch_and_explicit_u8 */
template<typename T> T core_util_atomic_fetch_and_explicit(volatile T *valuePtr, mbed::type_identity_t<T> arg, mbed_memory_order order) noexcept;
template<typename T> T core_util_atomic_fetch_and_explicit(volatile T *valuePtr, mstd::type_identity_t<T> arg, mbed_memory_order order) noexcept;
/** \copydoc core_util_fetch_or_explicit_u8 */
template<typename T> T core_util_atomic_fetch_or_explicit(volatile T *valuePtr, mbed::type_identity_t<T> arg, mbed_memory_order order) noexcept;
template<typename T> T core_util_atomic_fetch_or_explicit(volatile T *valuePtr, mstd::type_identity_t<T> arg, mbed_memory_order order) noexcept;
/** \copydoc core_util_fetch_xor_explicit_u8 */
template<typename T> T core_util_atomic_fetch_xor_explicit(volatile T *valuePtr, mbed::type_identity_t<T> arg, mbed_memory_order order) noexcept;
template<typename T> T core_util_atomic_fetch_xor_explicit(volatile T *valuePtr, mstd::type_identity_t<T> arg, mbed_memory_order order) noexcept;
/** \copydoc core_util_atomic_load_ptr */
template<typename T> inline T *core_util_atomic_load(T *const volatile *valuePtr) noexcept;
/** \copydoc core_util_atomic_load_ptr */
template<typename T> inline T *core_util_atomic_load(T *const *valuePtr) noexcept;
/** \copydoc core_util_atomic_store_ptr */
template<typename T> inline void core_util_atomic_store(T *volatile *valuePtr, mbed::type_identity_t<T> *desiredValue) noexcept;
template<typename T> inline void core_util_atomic_store(T *volatile *valuePtr, mstd::type_identity_t<T> *desiredValue) noexcept;
/** \copydoc core_util_atomic_store_ptr */
template<typename T> inline void core_util_atomic_store(T **valuePtr, mbed::type_identity_t<T> *desiredValue) noexcept;
template<typename T> inline void core_util_atomic_store(T **valuePtr, mstd::type_identity_t<T> *desiredValue) noexcept;
/** \copydoc core_util_atomic_exchange_ptr */
template<typename T> inline T *core_util_atomic_exchange(T *volatile *valuePtr, mbed::type_identity_t<T> *desiredValue) noexcept;
template<typename T> inline T *core_util_atomic_exchange(T *volatile *valuePtr, mstd::type_identity_t<T> *desiredValue) noexcept;
/** \copydoc core_util_atomic_cas_ptr */
template<typename T> inline bool core_util_atomic_compare_exchange_strong(T *volatile *ptr, mbed::type_identity_t<T> **expectedCurrentValue, mbed::type_identity_t<T> *desiredValue) noexcept;
template<typename T> inline bool core_util_atomic_compare_exchange_strong(T *volatile *ptr, mstd::type_identity_t<T> **expectedCurrentValue, mstd::type_identity_t<T> *desiredValue) noexcept;
/** \copydoc core_util_atomic_compare_exchange_weak_ptr */
template<typename T> inline bool core_util_atomic_compare_exchange_weak(T *volatile *ptr, mbed::type_identity_t<T> **expectedCurrentValue, mbed::type_identity_t<T> *desiredValue) noexcept;
template<typename T> inline bool core_util_atomic_compare_exchange_weak(T *volatile *ptr, mstd::type_identity_t<T> **expectedCurrentValue, mstd::type_identity_t<T> *desiredValue) noexcept;
/** \copydoc core_util_fetch_add_ptr */
template<typename T> inline T *core_util_atomic_fetch_add(T *volatile *valuePtr, ptrdiff_t arg) noexcept;
/** \copydoc core_util_fetch_sub_ptr */
@ -969,15 +969,15 @@ template<typename T> inline T *core_util_atomic_load_explicit(T *const volatile
/** \copydoc core_util_atomic_load_explicit_ptr */
template<typename T> inline T *core_util_atomic_load_explicit(T *const *valuePtr, mbed_memory_order order) noexcept;
/** \copydoc core_util_atomic_store_explicit_ptr */
template<typename T> inline void core_util_atomic_store_explicit(T *volatile *valuePtr, mbed::type_identity_t<T> *desiredValue, mbed_memory_order order) noexcept;
template<typename T> inline void core_util_atomic_store_explicit(T *volatile *valuePtr, mstd::type_identity_t<T> *desiredValue, mbed_memory_order order) noexcept;
/** \copydoc core_util_atomic_store_explicit_ptr */
template<typename T> inline void core_util_atomic_store_explicit(T **valuePtr, mbed::type_identity_t<T> *desiredValue, mbed_memory_order order) noexcept;
template<typename T> inline void core_util_atomic_store_explicit(T **valuePtr, mstd::type_identity_t<T> *desiredValue, mbed_memory_order order) noexcept;
/** \copydoc core_util_atomic_exchange_explicit_ptr */
template<typename T> inline T *core_util_atomic_exchange_explicit(T *volatile *valuePtr, mbed::type_identity_t<T> *desiredValue, mbed_memory_order order) noexcept;
template<typename T> inline T *core_util_atomic_exchange_explicit(T *volatile *valuePtr, mstd::type_identity_t<T> *desiredValue, mbed_memory_order order) noexcept;
/** \copydoc core_util_atomic_cas_explicit_ptr */
template<typename T> inline bool core_util_atomic_compare_exchange_strong_explicit(T *volatile *ptr, mbed::type_identity_t<T> **expectedCurrentValue, mbed::type_identity_t<T> *desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
template<typename T> inline bool core_util_atomic_compare_exchange_strong_explicit(T *volatile *ptr, mstd::type_identity_t<T> **expectedCurrentValue, mstd::type_identity_t<T> *desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
/** \copydoc core_util_atomic_compare_exchange_weak_explicit_ptr */
template<typename T> inline bool core_util_atomic_compare_exchange_weak_explicit(T *volatile *ptr, mbed::type_identity_t<T> **expectedCurrentValue, mbed::type_identity_t<T> *desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
template<typename T> inline bool core_util_atomic_compare_exchange_weak_explicit(T *volatile *ptr, mstd::type_identity_t<T> **expectedCurrentValue, mstd::type_identity_t<T> *desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
/** \copydoc core_util_fetch_add_explicit_ptr */
template<typename T> inline T *core_util_atomic_fetch_add_explicit(T *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order) noexcept;
/** \copydoc core_util_fetch_sub_explicit_ptr */