/* 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_ /* * * - includes toolchain's * - For ARM C 5, standard C++11/14 features: * - include * - std::move, std::forward, std::exchange * - std::declval * - std::integer_sequence * - include 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 #ifdef __CC_ARM #include <_move.h> #include // to get std::swap #include #include #include // uintmax_t #include #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 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 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 constexpr conditional_t::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 does not move, but // we can add this std overload for arrays, and send it to our mstd moving version template void swap(_TypeT (&__a)[_Size], _TypeT (&__b)[_Size]) noexcept(noexcept(mstd::swap(*__a, *__b))) { mstd::swap(__a, __b); } // [intseq.intseq] template struct integer_sequence { using value_type = T; static constexpr size_t size() noexcept { return sizeof...(I); } }; template using index_sequence = integer_sequence; // [intseq.make] namespace impl { template struct combine_umax_sequences; template struct combine_umax_sequences, integer_sequence> : mstd::type_identity> { }; template struct make_umax_sequence : combine_umax_sequences::type, typename make_umax_sequence::type> { }; template <> struct make_umax_sequence<1> : mstd::type_identity> { }; template <> struct make_umax_sequence<0> : mstd::type_identity> { }; template ::type> struct make_integer_sequence; template struct make_integer_sequence> { static_assert(N >= 0, "negative integer sequence"); using type = integer_sequence(I)...>; }; } template using make_integer_sequence = typename impl::make_integer_sequence::type; template using make_index_sequence = make_integer_sequence; template using index_sequence_for = make_index_sequence; // [pair.astuple] template struct tuple_size; template struct tuple_element; template using tuple_element_t = typename tuple_element::type; template struct tuple_size> : integral_constant { }; template struct tuple_element<0, pair> : mstd::type_identity { }; template struct tuple_element<1, pair> : mstd::type_identity { }; namespace impl{ template struct pair_getter; template <> struct pair_getter<0> { template static T1 &get(pair &p) { return p.first; } template static const T1 &cget(const pair &p) { return p.first; } template static T1 &&get_move(pair &&p) { return std::forward(p.first); } template static const T1 &&cget_move(const pair &&p) { return std::forward(p.first); } }; template <> struct pair_getter<1> { template static T2 &get(pair &p) { return p.second; } template static const T2 &cget(const pair &p) { return p.second; } template static T2 &&get_move(pair &&p) { return std::forward(p.second); } template static const T2 &&cget_move(const pair &&p) { return std::forward(p.second); } }; } template constexpr tuple_element_t> &get(pair &p) noexcept { return impl::pair_getter::get(p); } template constexpr const tuple_element_t> &get(const pair &p) noexcept { return impl::pair_getter::cget(p); } template constexpr tuple_element_t> &&get(pair &&p) noexcept { return impl::pair_getter::get_move(std::move(p)); } template constexpr const tuple_element_t> &&get(const pair &&p) noexcept { return impl::pair_getter::cget_move(std::move(p)); } template constexpr T1 &get(pair &p) noexcept { return p.first; } template constexpr const T1 &get(const pair &p) noexcept { return p.first; } template constexpr T1 &&get(pair &&p) noexcept { return p.first; } template constexpr const T1 &&get(const pair &&p) noexcept { return p.first; } template constexpr T2 &get(pair &p) noexcept { return p.second; } template constexpr const T2 &get(const pair &p) noexcept { return p.second; } template constexpr T2 &&get(pair &&p) noexcept { return p.second; } template constexpr const T2 &&get(const pair &&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 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 constexpr std::add_const_t<_TypeT> &as_const(_TypeT &__t) noexcept { return __t; } template void as_const(_TypeT &&) = delete; #endif } // namespace mstd #endif // MSTD_UTILITY_