mbed-os5 only for TYBLE16
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
platform/cxxsupport/mstd_utility
- Committer:
- kenjiArai
- Date:
- 2019-12-31
- Revision:
- 1:9db0e321a9f4
File content as of revision 1:9db0e321a9f4:
/* 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_