mbed-os5 only for TYBLE16
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
Diff: platform/cxxsupport/mstd_utility
- Revision:
- 1:9db0e321a9f4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/platform/cxxsupport/mstd_utility Tue Dec 31 06:02:27 2019 +0000 @@ -0,0 +1,341 @@ +/* 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; +using std::index_sequence; +using std::make_integer_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +// 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_