mbed-os5 only for TYBLE16
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
Diff: platform/cxxsupport/mstd_functional
- Revision:
- 1:9db0e321a9f4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/platform/cxxsupport/mstd_functional Tue Dec 31 06:02:27 2019 +0000 @@ -0,0 +1,499 @@ +/* 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 *ptr; +public: + using type = T; + // [refwrap.const] + // LWG 2993 version of constructor does not seem to work in ARM C 5, so stick with + // this original version. + reference_wrapper(T &x) noexcept : ptr(addressof(x)) { } + reference_wrapper(T &&x) = delete; + + 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(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_