mirror of https://github.com/ARMmbed/mbed-os.git
Remove ARMC5 reference from Mbed OS platform
parent
696467976f
commit
eb40dbcc20
|
@ -196,8 +196,8 @@ struct SingletonPtr {
|
|||
}
|
||||
|
||||
mutable T *_ptr;
|
||||
#if __cplusplus >= 201103L && !defined __CC_ARM
|
||||
// Align data appropriately (ARM Compiler 5 does not support alignas in C++11 mode)
|
||||
#if __cplusplus >= 201103L
|
||||
// Align data appropriately
|
||||
alignas(T) mutable char _data[sizeof(T)];
|
||||
#else
|
||||
// Force data to be 8 byte aligned
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
/* 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 */
|
|
@ -1,251 +0,0 @@
|
|||
/* 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 <_move.h>
|
||||
#include <cstddef> // size_t, ptrdiff_t
|
||||
#include <algorithm> // fill and swap_ranges
|
||||
#include <type_traits> // integral_constant
|
||||
|
||||
namespace std {
|
||||
template <typename>
|
||||
struct reverse_iterator;
|
||||
|
||||
// [array]
|
||||
template <typename _TypeT, size_t _Size>
|
||||
struct array {
|
||||
// [array.overview]
|
||||
_TypeT _C_elem[_Size != 0 ? _Size : 1];
|
||||
|
||||
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]
|
||||
// ARMC5 complains "a constexpr member function is only permitted in a literal class type"
|
||||
/*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());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename _TypeT, size_t _Size>
|
||||
bool operator==(const array<_TypeT, _Size> &__x, const array<_TypeT, _Size> &__y)
|
||||
{
|
||||
return equal(__x.begin(), __x.end(), __y.begin());
|
||||
}
|
||||
|
||||
template <typename _TypeT, size_t _Size>
|
||||
bool operator!=(const array<_TypeT, _Size> &__x, const array<_TypeT, _Size> &__y)
|
||||
{
|
||||
return !(__x == __y);
|
||||
}
|
||||
|
||||
template <typename _TypeT, size_t _Size>
|
||||
bool operator<(const array<_TypeT, _Size> &__x, const array<_TypeT, _Size> &__y)
|
||||
{
|
||||
return lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end());
|
||||
}
|
||||
|
||||
template <typename _TypeT, size_t _Size>
|
||||
bool operator>(const array<_TypeT, _Size> &__x, const array<_TypeT, _Size> &__y)
|
||||
{
|
||||
return __y < __x;
|
||||
}
|
||||
|
||||
template <typename _TypeT, size_t _Size>
|
||||
bool operator<=(const array<_TypeT, _Size> &__x, const array<_TypeT, _Size> &__y)
|
||||
{
|
||||
return !(__x > __y);
|
||||
}
|
||||
|
||||
template <typename _TypeT, size_t _Size>
|
||||
bool operator>=(const array<_TypeT, _Size> &__x, const array<_TypeT, _Size> &__y)
|
||||
{
|
||||
return !(__x < __y);
|
||||
}
|
||||
|
||||
// [array.special]
|
||||
template <typename _TypeT, size_t _Size>
|
||||
void swap(array<_TypeT, _Size> &__x, array<_TypeT, _Size> &__y)
|
||||
{
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
// [array.tuple]
|
||||
template <typename>
|
||||
struct tuple_size;
|
||||
|
||||
template <typename _TypeT, size_t _Size>
|
||||
struct tuple_size<array<_TypeT, _Size>> : integral_constant<size_t, _Size> { };
|
||||
|
||||
template <size_t, typename>
|
||||
struct tuple_element;
|
||||
|
||||
template <size_t _Idx, typename _TypeT, size_t _Size>
|
||||
struct tuple_element<_Idx, array<_TypeT, _Size>> : type_identity<_TypeT> {
|
||||
static_assert(_Idx < _Size, "array index out of bounds");
|
||||
};
|
||||
|
||||
template <size_t _Idx, typename _TypeT, size_t _Size>
|
||||
constexpr _TypeT &get(array<_TypeT, _Size> &__a) noexcept
|
||||
{
|
||||
static_assert(_Idx < _Size, "array index out of bounds");
|
||||
return __a._C_elem[_Idx];
|
||||
}
|
||||
|
||||
template <size_t _Idx, typename _TypeT, size_t _Size>
|
||||
_TypeT &&get(array<_TypeT, _Size> &&__a) noexcept
|
||||
{
|
||||
return std::move(get<_Idx>(__a));
|
||||
}
|
||||
|
||||
template <size_t _Idx, typename _TypeT, size_t _Size>
|
||||
constexpr const _TypeT &get(const array<_TypeT, _Size> &__a) noexcept
|
||||
{
|
||||
static_assert(_Idx < _Size, "array index out of bounds");
|
||||
return __a._C_elem[_Idx];
|
||||
}
|
||||
|
||||
template <size_t _Idx, typename _TypeT, size_t _Size>
|
||||
const _TypeT &&get(const array<_TypeT, _Size> &&__a) noexcept
|
||||
{
|
||||
return std::move(get<_Idx>(__a));
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif /* __array */
|
|
@ -1,62 +0,0 @@
|
|||
/* 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 __atomic
|
||||
#define __atomic
|
||||
|
||||
// Just go straight to the main file
|
||||
#include <mstd_atomic>
|
||||
|
||||
#define ATOMIC_VAR_INIT(x) { x }
|
||||
#define ATOMIC_FLAG_INIT MSTD_ATOMIC_FLAG_INIT
|
||||
|
||||
// And then pull it all into our std
|
||||
namespace std {
|
||||
using mstd::atomic;
|
||||
using mstd::atomic_is_lock_free;
|
||||
using mstd::atomic_store;
|
||||
using mstd::atomic_store_explicit;
|
||||
using mstd::atomic_load;
|
||||
using mstd::atomic_load_explicit;
|
||||
using mstd::atomic_exchange;
|
||||
using mstd::atomic_exchange_explicit;
|
||||
using mstd::atomic_compare_exchange_weak;
|
||||
using mstd::atomic_compare_exchange_weak_explicit;
|
||||
using mstd::atomic_compare_exchange_strong;
|
||||
using mstd::atomic_compare_exchange_strong_explicit;
|
||||
using mstd::atomic_fetch_add;
|
||||
using mstd::atomic_fetch_add_explicit;
|
||||
using mstd::atomic_fetch_sub;
|
||||
using mstd::atomic_fetch_sub_explicit;
|
||||
using mstd::atomic_fetch_and;
|
||||
using mstd::atomic_fetch_and_explicit;
|
||||
using mstd::atomic_fetch_or;
|
||||
using mstd::atomic_fetch_or_explicit;
|
||||
using mstd::atomic_fetch_xor;
|
||||
using mstd::atomic_fetch_xor_explicit;
|
||||
using mstd::atomic_flag;
|
||||
using mstd::atomic_flag_test_and_set;
|
||||
using mstd::atomic_flag_test_and_set_explicit;
|
||||
using mstd::atomic_flag_clear;
|
||||
using mstd::atomic_flag_clear_explicit;
|
||||
using mstd::atomic_init;
|
||||
using mstd::memory_order;
|
||||
using mstd::kill_dependency;
|
||||
using mstd::atomic_thread_fence;
|
||||
using mstd::atomic_signal_fence;
|
||||
}
|
||||
|
||||
#endif /* __atomic */
|
|
@ -1,38 +0,0 @@
|
|||
/* 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 */
|
|
@ -1,76 +0,0 @@
|
|||
/* 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 */
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/* 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 __mutex
|
||||
#define __mutex
|
||||
|
||||
// Just go straight to the main file - we also need IAR implementation, so do it there
|
||||
#include <mstd_mutex>
|
||||
|
||||
// And then pull it all into our std
|
||||
namespace std {
|
||||
using mstd::defer_lock;
|
||||
using mstd::defer_lock_t;
|
||||
using mstd::try_to_lock;
|
||||
using mstd::try_to_lock_t;
|
||||
using mstd::adopt_lock;
|
||||
using mstd::adopt_lock_t;
|
||||
|
||||
using mstd::lock_guard;
|
||||
using mstd::unique_lock;
|
||||
using mstd::scoped_lock;
|
||||
using mstd::try_lock;
|
||||
using mstd::lock;
|
||||
|
||||
using mstd::once_flag;
|
||||
using mstd::call_once;
|
||||
|
||||
using mstd::mutex;
|
||||
using mstd::recursive_mutex;
|
||||
}
|
||||
|
||||
#endif /* __mutex */
|
|
@ -1,734 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
/* class tuple implementation based on Sashsa Goldstein's series
|
||||
* "Implementing std::tuple from The Ground Up".
|
||||
*
|
||||
* http://blogs.microsoft.co.il/sasha/2015/01/12/implementing-tuple-part-1/
|
||||
*
|
||||
* tuple_cat based on Peter Dimov's article "Simple C++11 metaprogramming",
|
||||
* which in turn is based on work by Eric Niebler and Stephan T. Lavavej.
|
||||
*
|
||||
* https://www.boost.org/doc/libs/develop/libs/mp11/doc/html/simple_cxx11_metaprogramming.html
|
||||
*
|
||||
* As ARM C 5 can't do constexpr std::move or std::forward, there's no way
|
||||
* tuple can be constexpr either, so this is a C++11 implementation, not C++14.
|
||||
*
|
||||
* Allocators are not supported.
|
||||
*/
|
||||
#ifndef __tuple
|
||||
#define __tuple
|
||||
|
||||
#include <mstd_utility>
|
||||
#include <type_traits>
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template <typename... T>
|
||||
struct tuple;
|
||||
|
||||
template <size_t I, class T>
|
||||
struct tuple_element;
|
||||
|
||||
// ARM C 5 (incorrectly? doesn't allow duplicate using - utility has already done this (for pair)
|
||||
//template <size_t I, class T>
|
||||
//using tuple_element_t = typename tuple_element<I, T>::type;
|
||||
|
||||
template <size_t I, typename Type0, typename... TypeN>
|
||||
struct tuple_element<I, tuple<Type0, TypeN...>> : tuple_element<I-1, tuple<TypeN...>> { };
|
||||
|
||||
template <typename Type0, typename... TypeN>
|
||||
struct tuple_element<0, tuple<Type0, TypeN...>> : type_identity<Type0> { };
|
||||
|
||||
template <size_t I, typename T>
|
||||
struct tuple_element<I, const T> : type_identity<add_const_t<tuple_element_t<I,T>>> { };
|
||||
|
||||
template <size_t I, class T>
|
||||
struct tuple_element<I, volatile T> : type_identity<add_volatile_t<tuple_element_t<I,T>>> { };
|
||||
|
||||
template <size_t I, class T>
|
||||
struct tuple_element<I, const volatile T> : type_identity<add_cv_t<tuple_element_t<I,T>>> { };
|
||||
|
||||
template <size_t I, typename... T>
|
||||
tuple_element_t<I, tuple<T...>> &get(tuple<T...> &t) noexcept;
|
||||
|
||||
template <size_t I, typename... T>
|
||||
tuple_element_t<I, tuple<T...>> &&get(tuple<T...> &&t) noexcept;
|
||||
|
||||
template <size_t I, typename... T>
|
||||
const tuple_element_t<I, tuple<T...>> &get(const tuple<T...> &t) noexcept;
|
||||
|
||||
template <size_t I, typename... T>
|
||||
const tuple_element_t<I, tuple<T...>> &&get(const tuple<T...> &&t) noexcept;
|
||||
|
||||
namespace impl {
|
||||
|
||||
/* Tuple element container - tuple has these as multiple base classes */
|
||||
template <size_t, typename T>
|
||||
struct tuple_elem {
|
||||
constexpr tuple_elem() : value() { } // tuple default constructor value-initializes elements
|
||||
explicit tuple_elem(const T &val) : value(val) { }
|
||||
template <typename U, typename = enable_if_t<is_constructible<T,U&&>::value>>
|
||||
explicit tuple_elem(U&& val) : value(std::forward<U>(val)) { }
|
||||
/* Copy and move constructors and assignments implicitly defined (only way to get default move in ARMC5) */
|
||||
tuple_elem &operator=(const T &val) { value = val; return *this; }
|
||||
template <typename U, typename = enable_if_t<is_assignable<T &,U &&>::value>>
|
||||
tuple_elem &operator=(U&& val) { value = std::forward<U>(val); return *this; }
|
||||
void swap(T &other) { using namespace std; std::swap(value, other); }
|
||||
T value;
|
||||
};
|
||||
|
||||
template <typename Seq, typename... T>
|
||||
class tuple_base;
|
||||
|
||||
/* C++17 form - conditional explicit idiom from N4387 */
|
||||
template <size_t... Is, typename... Types>
|
||||
struct tuple_base<index_sequence<Is...>, Types...> : tuple_elem<Is, Types>... {
|
||||
private:
|
||||
template <typename... UTypes>
|
||||
struct we_are_convertible_from : conjunction<is_convertible<UTypes,Types>...> { };
|
||||
|
||||
template <typename... UTypes>
|
||||
struct we_are_constructible_from : conjunction<is_constructible<Types,UTypes>...> { };
|
||||
|
||||
void ignore(int...) { }
|
||||
public:
|
||||
/* Default constructor, 0 args */
|
||||
constexpr tuple_base() : tuple_elem<Is,Types>()... { }
|
||||
/* Direct constructor, 1+ args */
|
||||
template <typename Dummy=int, // enable_if will hard error if it doesn't depend on an immediate template parameter
|
||||
enable_if_t<sizeof(Dummy) && sizeof...(Types) >= 1 &&
|
||||
conjunction<is_copy_constructible<Types>...>::value, bool> = false>
|
||||
explicit tuple_base(const Types &...args) : tuple_elem<Is, Types>(args)... { }
|
||||
/* Converting constructor, 1+ args */
|
||||
template <typename... UTypes,
|
||||
enable_if_t<sizeof...(Types) == sizeof...(UTypes) && sizeof...(Types) >= 1 &&
|
||||
conjunction<is_constructible<Types,UTypes&&>...>::value, bool> = true>
|
||||
explicit tuple_base(UTypes &&...args) : tuple_elem<Is, Types>(std::forward<UTypes>(args))... { }
|
||||
/* Converting copy constructor */
|
||||
template <typename... UTypes,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(Types) == sizeof...(UTypes)>,
|
||||
is_constructible<Types,const UTypes&>...,
|
||||
disjunction<bool_constant<sizeof...(Types) != 1>,
|
||||
conjunction<negation<we_are_convertible_from<const tuple<UTypes> &...>>,
|
||||
negation<conjunction<is_constructible<Types, const tuple<UTypes> &>...>>,
|
||||
negation<conjunction<is_same<Types, UTypes>...>>
|
||||
>
|
||||
>
|
||||
>::value, bool> = true>
|
||||
explicit tuple_base(const tuple<UTypes...> &other) : tuple_elem<Is, Types>(get<Is>(other))... { }
|
||||
/* Converting move constructor */
|
||||
template <typename... UTypes,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(Types) == sizeof...(UTypes)>,
|
||||
is_constructible<Types,const UTypes&&>...,
|
||||
disjunction<bool_constant<sizeof...(Types) != 1>,
|
||||
conjunction<negation<we_are_convertible_from<tuple<UTypes>...>>,
|
||||
negation<conjunction<is_constructible<Types, tuple<UTypes>>...>>,
|
||||
negation<conjunction<is_same<Types, UTypes>...>>
|
||||
>
|
||||
>
|
||||
>::value, bool> = true>
|
||||
explicit tuple_base(tuple<UTypes...> &&other) : tuple_elem<Is, Types>(std::forward<UTypes>(get<Is>(other)))... { }
|
||||
/* Converting pair copy constructor */
|
||||
template <typename U1, typename U2,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(Types) == 2>,
|
||||
we_are_constructible_from<const U1 &, const U2 &>
|
||||
>::value, bool> = true>
|
||||
explicit tuple_base(const pair<U1,U2> &pair) :
|
||||
tuple_base(pair.first, pair.second) { }
|
||||
/* Converting pair move constructor */
|
||||
template <typename U1, typename U2,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(Types) == 2>,
|
||||
we_are_constructible_from<U1 &&, U2 &&>
|
||||
>::value, bool> = true>
|
||||
explicit tuple_base(pair<U1,U2> &&pair) :
|
||||
tuple_elem<0, tuple_element_t<0, tuple<Types...>>>(std::forward<U1>(pair.first)),
|
||||
tuple_elem<1, tuple_element_t<1, tuple<Types...>>>(std::forward<U2>(pair.second)) { }
|
||||
|
||||
/* Copy and move constructors and assignments implicitly defined (only way to get default move in ARMC5) */
|
||||
|
||||
template <size_t In, typename Tn, typename U>
|
||||
int do_copy1(const U &other) {
|
||||
impl::tuple_elem<In, Tn> &e = *this;
|
||||
e = other;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <size_t In, typename Tn, typename U>
|
||||
int do_move1(U &&other) {
|
||||
impl::tuple_elem<In, Tn> &e = *this;
|
||||
e = std::move(other);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename... UTypes >
|
||||
tuple_base &operator=(const tuple<UTypes...> &other) {
|
||||
ignore(do_copy1<Is, Types>(get<Is>(other))...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t Ihead, size_t... Irest, typename... UTypes>
|
||||
void do_move(tuple<UTypes...> &&other) {
|
||||
impl::tuple_elem<Ihead, tuple_element_t<Ihead, tuple<Types...>>> &e = *this;
|
||||
e = std::forward<tuple_element_t<Ihead, tuple<UTypes...>>>(get<Ihead>(other));
|
||||
do_move<Irest...>(std::forward<tuple<UTypes...>>(other));
|
||||
}
|
||||
|
||||
template <typename... UTypes>
|
||||
tuple_base &operator=(tuple<UTypes...> &&other) {
|
||||
ignore(do_move1<Is, Types>(std::forward<UTypes>(get<Is>(other)))...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U1, typename U2>
|
||||
tuple_base &operator=(const pair<U1,U2> &pair) {
|
||||
do_copy1<0, tuple_element_t<0, tuple<Types...>>>(pair.first);
|
||||
do_copy1<1, tuple_element_t<1, tuple<Types...>>>(pair.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U1, typename U2>
|
||||
tuple_base &operator=(pair<U1,U2> &&pair) {
|
||||
do_move1<0, tuple_element_t<0, tuple<Types...>>>(std::forward<U1>(pair.first));
|
||||
do_move1<1, tuple_element_t<1, tuple<Types...>>>(std::forward<U2>(pair.second));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t In, typename Tn>
|
||||
int do_swap1(Tn &other) {
|
||||
impl::tuple_elem<In, Tn> &e = *this;
|
||||
using std::swap;
|
||||
swap(e.value, other);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void swap(tuple<Types...> &other) {
|
||||
ignore(do_swap1<Is, Types>(get<Is>(other))...);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
template <typename... Types>
|
||||
struct tuple : impl::tuple_base<make_index_sequence<sizeof...(Types)>, Types...> {
|
||||
private:
|
||||
using base_type = impl::tuple_base<make_index_sequence<sizeof...(Types)>, Types...>;
|
||||
// Need this deferred so not evaluated in conjunction<size == 2, is_pair_assignable>
|
||||
// when size < 2
|
||||
template <typename U1, typename U2>
|
||||
struct is_pair_assignable : conjunction<is_assignable<tuple_element_t<0, tuple> &, U1>,
|
||||
is_assignable<tuple_element_t<1, tuple> &, U2>> { };
|
||||
template <typename... UTypes>
|
||||
struct we_are_convertible_from : conjunction<is_convertible<UTypes,Types>...> { };
|
||||
|
||||
template <typename... UTypes>
|
||||
struct we_are_constructible_from : conjunction<is_constructible<Types,UTypes>...> { };
|
||||
public:
|
||||
/* This would be simpler if ARM C 5 supported inheriting constructors,
|
||||
* but as it doesn't, we need to repeat stuff here and in tuple_base.
|
||||
*/
|
||||
|
||||
/* C++17 form - conditional explicit idiom from N4387 */
|
||||
/* Default constructor, 0 args */
|
||||
template <typename Dummy = int, // enable_if will hard error if it doesn't depend on an immediate template parameter
|
||||
enable_if_t<sizeof(Dummy) &&
|
||||
conjunction<is_default_constructible<Types>...>::value, bool> = false>
|
||||
constexpr tuple() : base_type() { }
|
||||
/* Direct constructor, 1+ args */
|
||||
template <typename Dummy=int, // enable_if will hard error if it doesn't depend on an immediate template parameter
|
||||
enable_if_t<sizeof(Dummy) && sizeof...(Types) >= 1 &&
|
||||
conjunction<is_copy_constructible<Types>...>::value &&
|
||||
we_are_convertible_from<const Types&...>::value, bool> = false>
|
||||
tuple(const Types &...args) : base_type(args...) { }
|
||||
template <typename Dummy=int, // enable_if will hard error if it doesn't depend on an immediate template parameter
|
||||
enable_if_t<sizeof(Dummy) && sizeof...(Types) >= 1 &&
|
||||
conjunction<is_copy_constructible<Types>...>::value &&
|
||||
!we_are_convertible_from<const Types&...>::value, bool> = true>
|
||||
explicit tuple(const Types &...args) : base_type(args...) { }
|
||||
/* Converting constructor, 1+ args */
|
||||
template <typename... UTypes,
|
||||
enable_if_t<sizeof...(Types) == sizeof...(UTypes) && sizeof...(Types) >= 1 &&
|
||||
conjunction<is_constructible<Types,UTypes&&>...>::value &&
|
||||
conjunction<is_convertible<UTypes&&,Types>...>::value/*we_are_convertible_from<UTypes&&...>::value*/, bool> = false>
|
||||
tuple(UTypes &&...args) : base_type(std::forward<UTypes>(args)...) { }
|
||||
template <typename... UTypes,
|
||||
enable_if_t<sizeof...(Types) == sizeof...(UTypes) && sizeof...(Types) >= 1 &&
|
||||
conjunction<is_constructible<Types,UTypes&&>...>::value &&
|
||||
!conjunction<is_convertible<UTypes&&,Types>...>::value/*we_are_convertible_from<UTypes&&...>::value*/, bool> = true>
|
||||
explicit tuple(UTypes &&...args) : base_type(std::forward<UTypes>(args)...) { }
|
||||
/* Converting copy constructor */
|
||||
template <typename... UTypes,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(Types) == sizeof...(UTypes)>,
|
||||
is_constructible<Types,const UTypes&>...,
|
||||
disjunction<bool_constant<sizeof...(Types) != 1>,
|
||||
conjunction<negation<we_are_convertible_from<const tuple<UTypes> &...>>,
|
||||
negation<conjunction<is_constructible<Types, const tuple<UTypes> &>...>>,
|
||||
negation<conjunction<is_same<Types, UTypes>...>>
|
||||
>
|
||||
>,
|
||||
conjunction<is_convertible<const UTypes&, Types>...>
|
||||
>::value, bool> = false>
|
||||
tuple(const tuple<UTypes...> &other) : base_type(other) { }
|
||||
template <typename... UTypes,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(Types) == sizeof...(UTypes)>,
|
||||
is_constructible<Types,const UTypes&>...,
|
||||
disjunction<bool_constant<sizeof...(Types) != 1>,
|
||||
conjunction<negation<we_are_convertible_from<const tuple<UTypes> &...>>,
|
||||
negation<conjunction<is_constructible<Types, const tuple<UTypes> &>...>>,
|
||||
negation<conjunction<is_same<Types, UTypes>...>>
|
||||
>
|
||||
>,
|
||||
negation<conjunction<is_convertible<const UTypes&, Types>...>>
|
||||
>::value, bool> = true>
|
||||
explicit tuple(const tuple<UTypes...> &other) : base_type(other) { }
|
||||
/* Converting move constructor */
|
||||
template <typename... UTypes,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(Types) == sizeof...(UTypes)>,
|
||||
is_constructible<Types,const UTypes&&>...,
|
||||
disjunction<bool_constant<sizeof...(Types) != 1>,
|
||||
conjunction<negation<we_are_convertible_from<tuple<UTypes>...>>,
|
||||
negation<conjunction<is_constructible<Types, tuple<UTypes>>...>>,
|
||||
negation<conjunction<is_same<Types, UTypes>...>>
|
||||
>
|
||||
>,
|
||||
conjunction<is_convertible<UTypes&&, Types>...>
|
||||
>::value, bool> = false>
|
||||
tuple(tuple<UTypes...> &&other) : base_type(std::forward<tuple<UTypes...>>(other)) { }
|
||||
template <typename... UTypes,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(Types) == sizeof...(UTypes)>,
|
||||
is_constructible<Types,const UTypes&&>...,
|
||||
disjunction<bool_constant<sizeof...(Types) != 1>,
|
||||
conjunction<negation<we_are_convertible_from<tuple<UTypes>...>>,
|
||||
negation<conjunction<is_constructible<Types, tuple<UTypes>>...>>,
|
||||
negation<conjunction<is_same<Types, UTypes>...>>
|
||||
>
|
||||
>,
|
||||
negation<conjunction<is_convertible<UTypes&&, Types>...>>
|
||||
>::value, bool> = true>
|
||||
explicit tuple(tuple<UTypes...> &&other) : base_type(std::forward<tuple<UTypes...>>(other)) { }
|
||||
/* Converting pair copy constructor */
|
||||
template <typename U1, typename U2,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(Types) == 2>,
|
||||
we_are_constructible_from<const U1 &, const U2 &>,
|
||||
we_are_convertible_from<const U1 &, const U2 &>
|
||||
>::value, bool> = false>
|
||||
tuple(const pair<U1,U2> &p) : base_type(p) { }
|
||||
template <typename U1, typename U2,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(Types) == 2>,
|
||||
we_are_constructible_from<const U1 &, const U2 &>,
|
||||
negation<we_are_convertible_from<const U1 &, const U2 &>>
|
||||
>::value, bool> = true>
|
||||
explicit tuple(const pair<U1,U2> &p) : base_type(p) { }
|
||||
/* Converting pair move constructor */
|
||||
template <typename U1, typename U2,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(Types) == 2>,
|
||||
we_are_constructible_from<U1 &&, U2 &&>,
|
||||
we_are_convertible_from<U1 &&, U2 &&>
|
||||
>::value, bool> = false>
|
||||
tuple(pair<U1,U2> &&p) : base_type(std::forward<pair<U1,U2>>(p)) { }
|
||||
template <typename U1, typename U2,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(Types) == 2>,
|
||||
we_are_constructible_from<U1 &&, U2 &&>,
|
||||
negation<we_are_convertible_from<U1 &&, U2 &&>>
|
||||
>::value, bool> = true>
|
||||
explicit tuple(pair<U1,U2> &&p) : base_type(std::forward<pair<U1,U2>>(p)) { }
|
||||
|
||||
/* Copy and move constructors and assignments implicitly defined (only way to get default move in ARMC5) */
|
||||
|
||||
template <typename... UTypes,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(UTypes) == sizeof...(Types)>,
|
||||
conjunction<is_assignable<Types &, const UTypes &>...>>::value, int> = 0>
|
||||
tuple &operator=(const tuple<UTypes...> &other) {
|
||||
*static_cast<base_type *>(this) = other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename... UTypes,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(UTypes) == sizeof...(Types)>,
|
||||
conjunction<is_assignable<Types &, UTypes &&>...>>::value, int> = 0>
|
||||
tuple &operator=(tuple<UTypes...> &&other) {
|
||||
*static_cast<base_type *>(this) = std::move(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U1, typename U2,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(Types) == 2>,
|
||||
is_pair_assignable<const U1 &, const U2 &>>::value, int> = 0>
|
||||
tuple &operator=(const pair<U1,U2> &pair) {
|
||||
*static_cast<base_type *>(this) = pair;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U1, typename U2,
|
||||
enable_if_t<
|
||||
conjunction<bool_constant<sizeof...(Types) == 2>,
|
||||
is_pair_assignable<U1 &&, U2 &&>>::value, int> = 0>
|
||||
tuple &operator=(pair<U1,U2> &&pair) {
|
||||
*static_cast<base_type *>(this) = std::move(pair);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace impl
|
||||
{
|
||||
template <typename T, typename... Us>
|
||||
struct type_count : integral_constant<size_t, 0> { };
|
||||
|
||||
template <typename T, typename U0, typename... UN>
|
||||
struct type_count<T, U0, UN...> : integral_constant<size_t, is_same<T, U0>::value + type_count<T, UN...>::value> { };
|
||||
|
||||
template <typename T, size_t I, typename... Us>
|
||||
struct type_find : integral_constant<size_t, size_t(-1)> { };
|
||||
|
||||
template <typename T, size_t I, typename U0, typename... UN>
|
||||
struct type_find<T, I, U0, UN...> : conditional_t<is_same<T, U0>::value, integral_constant<size_t, I>, type_find<T, I + 1, UN...>> { };
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
struct tuple_size;
|
||||
|
||||
template <typename... Types>
|
||||
struct tuple_size<tuple<Types...>> : integral_constant<size_t, sizeof...(Types)> { };
|
||||
|
||||
template <class T>
|
||||
struct tuple_size<const T> : integral_constant<size_t, tuple_size<T>::value> { };
|
||||
|
||||
template <class T>
|
||||
struct tuple_size<volatile T> : integral_constant<size_t, tuple_size<T>::value> { };
|
||||
|
||||
template <class T>
|
||||
struct tuple_size<const volatile T> : integral_constant<size_t, tuple_size<T>::value> { };
|
||||
|
||||
template <size_t I, typename... T>
|
||||
tuple_element_t<I, tuple<T...>> &get(tuple<T...> &t) noexcept
|
||||
{
|
||||
impl::tuple_elem<I, tuple_element_t<I, tuple<T...>>> &e = t;
|
||||
return e.value;
|
||||
}
|
||||
|
||||
template <size_t I, typename... T>
|
||||
tuple_element_t<I, tuple<T...>> &&get(tuple<T...> &&t) noexcept
|
||||
{
|
||||
impl::tuple_elem<I, tuple_element_t<I, tuple<T...>>> &&e = std::move(t);
|
||||
return std::forward<tuple_element_t<I, tuple<T...>>>(e.value);
|
||||
}
|
||||
|
||||
template <size_t I, typename... T>
|
||||
const tuple_element_t<I, tuple<T...>> &get(const tuple<T...> &t) noexcept
|
||||
{
|
||||
const impl::tuple_elem<I, tuple_element_t<I, tuple<T...>>> &e = t;
|
||||
return e.value;
|
||||
}
|
||||
|
||||
template <size_t I, typename... T>
|
||||
const tuple_element_t<I, tuple<T...>> &&get(const tuple<T...> &&t) noexcept
|
||||
{
|
||||
const impl::tuple_elem<I, tuple_element_t<I, tuple<T...>>> &&e = std::move(t);
|
||||
return std::forward<tuple_element_t<I, tuple<T...>>>(e.value);
|
||||
}
|
||||
|
||||
template <typename T, typename... Types>
|
||||
T &get(tuple<Types...> &t) noexcept
|
||||
{
|
||||
static_assert(impl::type_count<T, Types...>::value == 1, "not exactly 1 matching type in tuple");
|
||||
return get<impl::type_find<T, 0, Types...>::value>(t);
|
||||
}
|
||||
|
||||
namespace impl{
|
||||
template <typename T>
|
||||
struct unwrap_ref_wrapper : type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
struct unwrap_ref_wrapper<reference_wrapper<T>> : type_identity<T &> { };
|
||||
|
||||
template <typename T>
|
||||
struct tuple_decay : unwrap_ref_wrapper<decay_t<T>> { };
|
||||
|
||||
template <typename T>
|
||||
using tuple_decay_t = typename tuple_decay<T>::type;
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
tuple<impl::tuple_decay_t<Types>...> make_tuple(Types&&... args)
|
||||
{
|
||||
return tuple<impl::tuple_decay_t<Types>...>(std::forward<Types>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
tuple<Types&&...> forward_as_tuple(Types&&... args) noexcept
|
||||
{
|
||||
return tuple<Types&&...>(std::forward<Types>(args)...);
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
struct ignore {
|
||||
template <typename T>
|
||||
constexpr const ignore &operator=(const T &) const { return *this; }
|
||||
};
|
||||
}
|
||||
|
||||
const impl::ignore ignore;
|
||||
|
||||
template <typename... Types>
|
||||
tuple<Types &...> tie(Types &... args) noexcept
|
||||
{
|
||||
return tuple<Types &...>(args...);
|
||||
}
|
||||
|
||||
namespace impl
|
||||
{
|
||||
template <size_t I, size_t N, typename T, typename U>
|
||||
struct tuple_cmp
|
||||
{
|
||||
static bool equal(const T &t, const U &u)
|
||||
{
|
||||
return get<I>(t) == get<I>(u) ? tuple_cmp<I + 1, N, T, U>::equal(t, u) : false;
|
||||
}
|
||||
|
||||
static bool less(const T &t, const U &u)
|
||||
{
|
||||
return get<I>(t) < get<I>(u) ? true :
|
||||
get<I>(u) < get<I>(t) ? false :
|
||||
tuple_cmp<I + 1, N, T, U>::less(t, u);
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t N, typename T, typename U>
|
||||
struct tuple_cmp<N, N, T, U>
|
||||
{
|
||||
static bool equal(const T &t, const U &u)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool less(const T &t, const U &u)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename... TTypes, typename... UTypes>
|
||||
bool operator==(const tuple<TTypes...> &t, const tuple<UTypes...> &u)
|
||||
{
|
||||
static_assert(sizeof...(TTypes) == sizeof...(UTypes), "tuple size mismatch");
|
||||
return impl::tuple_cmp<0, sizeof...(TTypes), tuple<TTypes...>, tuple<UTypes...>>::equal(t, u);
|
||||
}
|
||||
|
||||
template <typename... TTypes, typename... UTypes>
|
||||
bool operator<(const tuple<TTypes...> &t, const tuple<UTypes...> &u)
|
||||
{
|
||||
static_assert(sizeof...(TTypes) == sizeof...(UTypes), "tuple size mismatch");
|
||||
return impl::tuple_cmp<0, sizeof...(TTypes), tuple<TTypes...>, tuple<UTypes...>>::less(t, u);
|
||||
}
|
||||
|
||||
template <typename... TTypes, typename... UTypes>
|
||||
bool operator!=(const tuple<TTypes...> &t, const tuple<UTypes...> &u)
|
||||
{
|
||||
return !(t == u);
|
||||
}
|
||||
|
||||
template <typename... TTypes, typename... UTypes>
|
||||
bool operator>(const tuple<TTypes...> &t, const tuple<UTypes...> &u)
|
||||
{
|
||||
return u < t;
|
||||
}
|
||||
|
||||
template <typename... TTypes, typename... UTypes>
|
||||
bool operator<=(const tuple<TTypes...> &t, const tuple<UTypes...> &u)
|
||||
{
|
||||
return !(u < t);
|
||||
}
|
||||
template <typename... TTypes, typename... UTypes>
|
||||
bool operator>=(const tuple<TTypes...> &t, const tuple<UTypes...> &u)
|
||||
{
|
||||
return !(t < u);
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
void swap(tuple<Types...> &x, tuple<Types...> &y)
|
||||
{
|
||||
x.swap(y);
|
||||
}
|
||||
|
||||
// Start deep meta-programming for tuple_cat
|
||||
|
||||
namespace impl {
|
||||
|
||||
// List of types Ts...
|
||||
template <typename... Ts>
|
||||
struct mp_list { };
|
||||
|
||||
// Given A<...>, B, produce B<...>
|
||||
template <class A, template <typename...> class B>
|
||||
struct _mp_rename;
|
||||
|
||||
template <template <typename...> class A, typename... Ts, template <typename...> class B>
|
||||
struct _mp_rename<A<Ts...>, B> : type_identity<B<Ts...>> { };
|
||||
|
||||
template <class A, template <typename...> class B>
|
||||
using mp_rename = typename _mp_rename<A, B>::type;
|
||||
|
||||
// Or, looking at it another way, given <Fun, List<...>>, produce Fun<...>
|
||||
template <template <typename...> class Fun, class List>
|
||||
using mp_apply = mp_rename<List, Fun>;
|
||||
|
||||
// Return the length of its arguments, as an integral_constant
|
||||
template <typename... Ts>
|
||||
using mp_length = integral_constant<std::size_t, sizeof...(Ts)>;
|
||||
|
||||
// Return size of a list, such as mp_list, as an integral_constant
|
||||
template <class List>
|
||||
using mp_size = mp_apply<mp_length, List>;
|
||||
|
||||
// Given <List<A,B,C>, D, E, F>, produce <List<D,E,F,A,B,C>>
|
||||
template <class List, typename... Ts>
|
||||
struct _mp_push_front;
|
||||
|
||||
template <template <typename...> class List, typename... Us, typename... Ts>
|
||||
struct _mp_push_front<List<Us...>, Ts...> : type_identity<List<Ts..., Us...>> { };
|
||||
|
||||
template <class List, typename... Ts>
|
||||
using mp_push_front = typename _mp_push_front<List, Ts...>::type;
|
||||
|
||||
// Given <Fun, List<A,B,C>>, produce List<Fun<A>, Fun<B>, Fun<C>>
|
||||
// Or given <Fun, List1<A,B,C>, List2<D,E,F>>, produce List1<Fun<A,D>, Fun<B,E>, Fun<C,F>>
|
||||
template <template <typename...> class Fun, class... List>
|
||||
struct _mp_transform;
|
||||
|
||||
template <template <typename...> class Fun,
|
||||
template <typename...> class List,
|
||||
typename... Ts>
|
||||
struct _mp_transform<Fun, List<Ts...>> : type_identity<List<Fun<Ts>...>> { };
|
||||
|
||||
template <template <typename...> class Fun,
|
||||
template <typename...> class List1,
|
||||
template <typename...> class List2,
|
||||
typename... T1, typename... T2>
|
||||
struct _mp_transform<Fun, List1<T1...>, List2<T2...>> : type_identity<List1<Fun<T1,T2>...>> { };
|
||||
|
||||
template <template <typename...> class Fun, class... List>
|
||||
using mp_transform = typename _mp_transform<Fun, List...>::type;
|
||||
|
||||
// Given <List1<A,B,C>, List2<D,E,F>, List3<G>, ...>, produce List1<A,B,C,D,E,F>
|
||||
template <class... List>
|
||||
struct _mp_append;
|
||||
|
||||
template <class... List>
|
||||
using mp_append = typename _mp_append<List...>::type;
|
||||
|
||||
template <>
|
||||
struct _mp_append<> : type_identity<mp_list<>> { };
|
||||
|
||||
template <template <typename...> class List, typename... Ts>
|
||||
struct _mp_append<List<Ts...>> : type_identity<List<Ts...>> { };
|
||||
|
||||
template <
|
||||
template <typename...> class List1, typename... T1,
|
||||
template <typename...> class List2, typename... T2,
|
||||
class... Rest>
|
||||
struct _mp_append<List1<T1...>, List2<T2...>, Rest...> : type_identity<mp_append<List1<T1..., T2...>, Rest...>> { };
|
||||
|
||||
// mp_constant<T>::apply(any arguments) is an alias for T.
|
||||
template <class T>
|
||||
struct mp_constant
|
||||
{
|
||||
template <typename...>
|
||||
using apply = T;
|
||||
};
|
||||
|
||||
// Given a list, replace all elements with V
|
||||
template <class List, typename V>
|
||||
using mp_fill = mp_transform<mp_constant<V>::template apply, List>;
|
||||
|
||||
// Given an integer_sequence<T,x,y,z...> , produce a mp_list of integral_constants: mp_list<ic<T,x>,ic<T,y>,ic<T,z>...>
|
||||
template <class Seq>
|
||||
struct _mp_from_sequence;
|
||||
template <template <typename U, U...> class S, class T, T... Is>
|
||||
struct _mp_from_sequence<S<T, Is...>> : type_identity<mp_list<integral_constant<T, Is>...>> { };
|
||||
|
||||
template <class Seq>
|
||||
using mp_from_sequence = typename _mp_from_sequence<Seq>::type;
|
||||
|
||||
// Given an integral constant N, produce the mp_list of integral constants from 0 to N-1.
|
||||
template <class N>
|
||||
using mp_iota = mp_from_sequence<make_index_sequence<N::value>>;
|
||||
|
||||
// Given a list, produce a series of indexing integers
|
||||
template <class List>
|
||||
using mp_index_sequence_for = mp_iota<mp_size<List>>;
|
||||
|
||||
// Given the lists Is=<0,0,0,1,1>, Ks=<0,1,2,0,1>
|
||||
// and a tuple of tuples tuple<tuple<a,b,c>, tuple<d,e>>
|
||||
// use the indexes to do get<Ks>(get<Is>)..., ie
|
||||
// get<0>(get<0>), _get<1>(get<0>), get<2>(get<0>), get<0>(get<1>), get<1>(get<1>)
|
||||
// thus extracting a,b,c,d,e in order, producing tuple<a,b,c,d,e>
|
||||
template <typename Ret, typename... Is, typename... Ks, typename Tuples>
|
||||
Ret tuple_cat_(mp_list<Is...>, mp_list<Ks...>, Tuples tpls)
|
||||
{
|
||||
return Ret{get<Ks::value>(get<Is::value>(std::forward<Tuples>(tpls)))...};
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
|
||||
// Compute the indexing arrays for the above concatenation.
|
||||
// Illustrating steps with parameters tuple<a,b,c>, tuple<d,e>
|
||||
template <typename... Tuples,
|
||||
typename Res = impl::mp_append<tuple<>, remove_cvref_t<Tuples>...>>
|
||||
Res tuple_cat(Tuples&&... tpls)
|
||||
{
|
||||
// mp_list<tuple<a,b,c>,tuple<d,e>>
|
||||
using tuple_list = impl::mp_list<remove_cvref_t<Tuples>...>;
|
||||
// mp_list<0,1>
|
||||
using tuple_index = impl::mp_from_sequence<make_index_sequence<sizeof...(Tuples)>>;
|
||||
// mp_list<tuple<0,0,0>,tuple<1,1>>
|
||||
using filled = impl::mp_transform<impl::mp_fill, tuple_list, tuple_index>;
|
||||
// tuple<0,0,0,1,1>
|
||||
using joined_fills = impl::mp_apply<impl::mp_append, filled>;
|
||||
// mp_list<0,0,0,1,1>
|
||||
using inner = impl::mp_rename<joined_fills, impl::mp_list>;
|
||||
|
||||
// mp_list<mp_list<0,1,2>,mp_list<0,1>>
|
||||
using indexed = impl::mp_transform<impl::mp_index_sequence_for, tuple_list>;
|
||||
// mp_list<0,1,2,0,1>
|
||||
using outer = impl::mp_apply<impl::mp_append, indexed>;
|
||||
|
||||
return impl::tuple_cat_<Res>(inner(), outer(), std::forward_as_tuple(std::forward<Tuples>(tpls)...));
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif /* __tuple */
|
|
@ -1,25 +0,0 @@
|
|||
/* 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 */
|
|
@ -17,296 +17,8 @@
|
|||
#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;
|
||||
|
@ -379,7 +91,9 @@ using std::max_element;
|
|||
using std::lexicographical_compare;
|
||||
using std::next_permutation;
|
||||
using std::prev_permutation;
|
||||
|
||||
using std::min;
|
||||
using std::max;
|
||||
using std::minmax;
|
||||
}
|
||||
|
||||
#endif // MSTD_ALGORITHM_
|
||||
|
|
|
@ -576,14 +576,8 @@ protected:
|
|||
template<typename T, typename DiffT = T, typename StrideT = char, typename A = atomic_container_t<T>>
|
||||
struct AtomicWithAdd : public AtomicBaseInt<T, A> {
|
||||
using difference_type = DiffT;
|
||||
#ifdef __CC_ARM
|
||||
AtomicWithAdd() noexcept = default;
|
||||
constexpr AtomicWithAdd(T v) noexcept : AtomicBaseInt<T, A>(v)
|
||||
{
|
||||
}
|
||||
#else
|
||||
using AtomicBaseInt<T, A>::AtomicBaseInt;
|
||||
#endif
|
||||
|
||||
T operator++() volatile noexcept
|
||||
{
|
||||
A d = static_cast<A>(sizeof(StrideT));
|
||||
|
@ -640,14 +634,8 @@ struct AtomicWithAdd : public AtomicBaseInt<T, A> {
|
|||
*/
|
||||
template<typename T, typename A = atomic_container_t<T>>
|
||||
struct AtomicWithBitwise : public AtomicWithAdd<T, A> {
|
||||
#ifdef __CC_ARM
|
||||
AtomicWithBitwise() noexcept = default;
|
||||
constexpr AtomicWithBitwise(T v) noexcept : AtomicWithAdd<T, A>(v)
|
||||
{
|
||||
}
|
||||
#else
|
||||
using AtomicWithAdd<T, A>::AtomicWithAdd;
|
||||
#endif
|
||||
|
||||
T fetch_and(T arg) volatile noexcept
|
||||
{
|
||||
A d = static_cast<A>(arg);
|
||||
|
|
|
@ -49,26 +49,6 @@
|
|||
#define MSTD_CONSTEXPR_FN_11 constexpr
|
||||
#define MSTD_CONSTEXPR_OBJ_11 constexpr
|
||||
|
||||
#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;
|
||||
|
|
|
@ -20,11 +20,6 @@
|
|||
/* <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)
|
||||
|
@ -37,35 +32,6 @@
|
|||
#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]
|
||||
|
@ -81,335 +47,6 @@ invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
|
|||
|
||||
} // 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;
|
||||
|
|
|
@ -34,316 +34,6 @@
|
|||
#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;
|
||||
|
|
|
@ -37,484 +37,6 @@
|
|||
#include <mstd_utility> // std::pair
|
||||
#include <mstd_iterator> // std::iterator_traits
|
||||
|
||||
#ifdef __CC_ARM
|
||||
|
||||
#include <cstddef> // size_t, ptrdiff_t
|
||||
#include <_move.h> // exchange
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
// [uninitialized.copy] - ARMCC has pre-C++11 uninitialized_copy
|
||||
template <class InputIterator, class Size, class ForwardIterator>
|
||||
ForwardIterator uninitialized_copy_n(InputIterator first, Size n, ForwardIterator result) {
|
||||
for ( ; n > 0; ++result, (void) ++first, --n) {
|
||||
::new (static_cast<void*>(addressof(*result)))
|
||||
typename std::iterator_traits<ForwardIterator>::value_type(*first);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// [uninitialized.fill] - ARMCC has pre-C++11 uninitialized_fill and uninitialized_fill_n
|
||||
|
||||
// [unique.ptr]
|
||||
namespace impl
|
||||
{
|
||||
/* Base version - use T * */
|
||||
template <typename T, typename D, typename = void>
|
||||
struct unique_ptr_type_helper {
|
||||
typedef T *type;
|
||||
};
|
||||
|
||||
/* if "remove_reference_t<D>::pointer" is a type, specialise to use it */
|
||||
template <typename T, typename D>
|
||||
struct unique_ptr_type_helper<T, D, mstd::void_t<typename remove_reference_t<D>::pointer>> {
|
||||
typedef typename remove_reference_t<D>::pointer type;
|
||||
};
|
||||
|
||||
template <class T, class D>
|
||||
using unique_ptr_type_helper_t = typename unique_ptr_type_helper<T, D>::type;
|
||||
|
||||
// Want to eliminate storage for the deleter - could just use it as a base
|
||||
// class, for empty base optimisation, if we knew it was a class. But it could be
|
||||
// a pointer or reference. Here's a version that uses deleter as base,
|
||||
template<class D, typename = void>
|
||||
class deleter_store : private D {
|
||||
public:
|
||||
constexpr deleter_store() noexcept = default;
|
||||
template <typename _D>
|
||||
constexpr deleter_store(_D &&d) noexcept : D(std::forward<_D>(d)) { }
|
||||
|
||||
D &get_deleter() noexcept { return static_cast<D &>(*this); }
|
||||
const D &get_deleter() const noexcept { return static_cast<const D &>(*this); }
|
||||
};
|
||||
|
||||
//Here's a version that stores (for pointer/reference)
|
||||
template<class D>
|
||||
class deleter_store<D, enable_if_t<!is_class<D>::value>> {
|
||||
D d;
|
||||
public:
|
||||
constexpr deleter_store() noexcept : d() { }
|
||||
template <typename _D>
|
||||
constexpr deleter_store(_D &&d) noexcept : d(std::forward<_D>(d)) { }
|
||||
|
||||
D &get_deleter() noexcept { return d; }
|
||||
const D &get_deleter() const noexcept { return d; }
|
||||
};
|
||||
}
|
||||
|
||||
// [unique.ptr.dltr.dflt]
|
||||
template<class T>
|
||||
struct default_delete {
|
||||
constexpr default_delete() noexcept = default;
|
||||
|
||||
template <class U, class = enable_if_t<is_convertible<U *, T *>::value>>
|
||||
default_delete(const default_delete<U> &d) noexcept { }
|
||||
|
||||
void operator()(T *ptr) const
|
||||
{
|
||||
// Program is ill-formed if T is incomplete - generate diagnostic by breaking compilation
|
||||
// (Behaviour of raw delete of incomplete class is undefined if complete class is non-trivial, else permitted)
|
||||
static_assert(sizeof(T) == sizeof(T), "Cannot delete incomplete type");
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
// [unique.ptr.dltr.dflt1]
|
||||
template<class T>
|
||||
struct default_delete<T[]> {
|
||||
constexpr default_delete() noexcept = default;
|
||||
|
||||
template <class U, class = enable_if_t<is_convertible<U (*)[], T (*)[]>::value>>
|
||||
default_delete(const default_delete<U> &d) noexcept { }
|
||||
|
||||
template <class U, class = enable_if_t<is_convertible<U (*)[], T (*)[]>::value>>
|
||||
void operator()(U *ptr) const
|
||||
{
|
||||
delete[] ptr;
|
||||
}
|
||||
};
|
||||
|
||||
// [unique.ptr.single]
|
||||
template<
|
||||
class T,
|
||||
class D = default_delete<T>
|
||||
> class unique_ptr : public impl::deleter_store<D>
|
||||
{
|
||||
template <class U, class E>
|
||||
static constexpr bool is_compatible_unique_ptr()
|
||||
{
|
||||
return is_convertible<typename unique_ptr<U,E>::pointer, pointer>::value &&
|
||||
!is_array<U>::value;
|
||||
}
|
||||
public:
|
||||
typedef impl::unique_ptr_type_helper_t<T, D> pointer;
|
||||
typedef T element_type;
|
||||
typedef D deleter_type;
|
||||
// [unique.ptr.single.ctor]
|
||||
template <class _D = D, typename = enable_if_t<!is_pointer<_D>::value && is_default_constructible<_D>::value>>
|
||||
constexpr unique_ptr() noexcept : impl::deleter_store<D>(), ptr_() { }
|
||||
template <class _D = D, typename = enable_if_t<!is_pointer<_D>::value && is_default_constructible<_D>::value>>
|
||||
constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
|
||||
template <class _D = D, typename = enable_if_t<!is_pointer<_D>::value && is_default_constructible<_D>::value>>
|
||||
explicit unique_ptr(pointer ptr) noexcept : impl::deleter_store<D>(), ptr_(ptr) { }
|
||||
template <class _D = D, typename = enable_if_t<is_copy_constructible<_D>::value>>
|
||||
unique_ptr(pointer ptr, const D &d) noexcept : impl::deleter_store<D>(d), ptr_(ptr) { }
|
||||
template <class _D = D, typename = enable_if_t<is_move_constructible<_D>::value>>
|
||||
unique_ptr(pointer ptr, enable_if_t<!is_lvalue_reference<_D>::value, _D &&> d) noexcept : impl::deleter_store<D>(move(d)), ptr_(ptr) { }
|
||||
template <class _D = D, typename _A = remove_reference_t<_D>>
|
||||
unique_ptr(pointer ptr, enable_if_t<is_lvalue_reference<_D>::value, _A &&> d) = delete;
|
||||
unique_ptr(const unique_ptr &) = delete;
|
||||
unique_ptr(unique_ptr &&u) noexcept : impl::deleter_store<D>(forward<D>(u.get_deleter())), ptr_(u.ptr_) { u.ptr_ = nullptr; }
|
||||
template <class U, class E, class = enable_if_t<
|
||||
is_compatible_unique_ptr<U, E>() &&
|
||||
(is_reference<D>::value ? is_same<E, D>::value : is_convertible<E,D>::value)>>
|
||||
unique_ptr(unique_ptr<U, E>&& u) noexcept : impl::deleter_store<D>(std::forward<E>(u.get_deleter())), ptr_(u.release()) { }
|
||||
|
||||
// [unique.ptr.single.dtor]
|
||||
~unique_ptr()
|
||||
{
|
||||
if (ptr_) {
|
||||
this->get_deleter()(ptr_);
|
||||
}
|
||||
}
|
||||
|
||||
// [unique.ptr.single.modifiers]
|
||||
pointer release() noexcept
|
||||
{
|
||||
return std::exchange(ptr_, nullptr);
|
||||
}
|
||||
|
||||
void reset(pointer ptr = pointer()) noexcept
|
||||
{
|
||||
pointer old = std::exchange(ptr_, ptr);
|
||||
if (old) {
|
||||
this->get_deleter()(old);
|
||||
}
|
||||
}
|
||||
|
||||
void swap(unique_ptr &other) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
swap(this->get_deleter(), other.get_deleter());
|
||||
swap(ptr_, other.ptr_);
|
||||
}
|
||||
|
||||
// [unique.ptr.single.asgn]
|
||||
unique_ptr &operator=(const unique_ptr &r) = delete;
|
||||
unique_ptr &operator=(unique_ptr &&r) noexcept
|
||||
{
|
||||
reset(r.release());
|
||||
this->get_deleter() = std::forward<D>(r.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
unique_ptr &operator=(nullptr_t) noexcept
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U, class E>
|
||||
enable_if_t<is_compatible_unique_ptr<U, E>() &&
|
||||
is_assignable<D &, E &&>::value,
|
||||
unique_ptr> &operator=(unique_ptr<U, E> &&u) noexcept
|
||||
{
|
||||
reset(u.release());
|
||||
this->get_deleter() = std::forward<E>(u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// [unique.ptr.single.observers]
|
||||
pointer get() const noexcept { return ptr_; }
|
||||
pointer operator->() const noexcept { return ptr_; }
|
||||
add_lvalue_reference_t<T> operator*() const noexcept { return *ptr_; }
|
||||
explicit operator bool() const noexcept { return ptr_; }
|
||||
private:
|
||||
pointer ptr_;
|
||||
};
|
||||
|
||||
// [unique.ptr.runtime]
|
||||
template<class T, class D>
|
||||
class unique_ptr<T[], D> : public impl::deleter_store<D>
|
||||
{
|
||||
template <class U>
|
||||
static constexpr bool is_compatible_pointer()
|
||||
{
|
||||
return is_same<U, pointer>::value ||
|
||||
is_same<U, nullptr_t>::value ||
|
||||
(is_same<pointer, element_type *>::value && is_pointer<U>::value &&
|
||||
is_convertible<remove_pointer_t<U> (*)[], element_type (*)[]>::value);
|
||||
}
|
||||
|
||||
template <class U, class E, class UP = unique_ptr<U,E>>
|
||||
static constexpr bool is_compatible_unique_ptr()
|
||||
{
|
||||
return is_array<U>::value &&
|
||||
is_same<pointer, element_type *>::value &&
|
||||
is_same<typename UP::pointer, typename UP::element_type *>::value &&
|
||||
is_convertible<typename UP::element_type(*)[], element_type(*)[]>::value;
|
||||
}
|
||||
public:
|
||||
typedef impl::unique_ptr_type_helper_t<T, D> pointer;
|
||||
typedef T element_type;
|
||||
typedef D deleter_type;
|
||||
|
||||
// [unique.ptr.runtime.ctor] / [unique.ptr.single.ctor]
|
||||
template <class _D = D, typename = enable_if_t<!is_pointer<_D>::value && is_default_constructible<_D>::value>>
|
||||
constexpr unique_ptr() noexcept : impl::deleter_store<D>(), ptr_() { }
|
||||
|
||||
template <class _D = D, typename = enable_if_t<!is_pointer<_D>::value && is_default_constructible<_D>::value>>
|
||||
constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
|
||||
|
||||
template <class _D = D, typename = enable_if_t<!is_pointer<_D>::value && is_default_constructible<_D>::value>,
|
||||
class U, typename = enable_if_t<is_compatible_pointer<U>()>>
|
||||
explicit unique_ptr(U ptr) noexcept : impl::deleter_store<D>(), ptr_(ptr) { }
|
||||
|
||||
template <class _D = D, typename = enable_if_t<is_copy_constructible<_D>::value>,
|
||||
class U, typename = enable_if_t<is_compatible_pointer<U>()>>
|
||||
unique_ptr(U ptr, const D &d) noexcept : impl::deleter_store<D>(d), ptr_(ptr) { }
|
||||
|
||||
template <class _D = D, typename = enable_if_t<is_move_constructible<_D>::value>,
|
||||
class U, typename = enable_if_t<is_compatible_pointer<U>()>>
|
||||
unique_ptr(U ptr, enable_if_t<!is_lvalue_reference<_D>::value, _D &&> d) noexcept : impl::deleter_store<D>(std::move(d)), ptr_(ptr) { }
|
||||
|
||||
template <class _D = D, typename _A = remove_reference_t<_D>,
|
||||
class U, typename = enable_if_t<is_compatible_pointer<U>()>>
|
||||
unique_ptr(U ptr, enable_if_t<is_lvalue_reference<_D>::value, _A &&> d) = delete;
|
||||
|
||||
unique_ptr(const unique_ptr &) = delete;
|
||||
unique_ptr(unique_ptr &&u) noexcept : impl::deleter_store<D>(std::forward<D>(u.get_deleter())), ptr_(u.ptr_) { u.ptr_ = nullptr; }
|
||||
|
||||
template <class U, class E,
|
||||
typename = enable_if_t<is_compatible_unique_ptr<U, E>() &&
|
||||
(is_reference<D>::value ? is_same<E,D>::value : is_convertible<E,D>::value)>>
|
||||
unique_ptr(unique_ptr<U, E>&& u) noexcept : impl::deleter_store<D>(std::forward<E>(u.get_deleter())), ptr_(u.release()) { }
|
||||
|
||||
// [unique.ptr.single.dtor]
|
||||
~unique_ptr()
|
||||
{
|
||||
if (ptr_) {
|
||||
this->get_deleter()(ptr_);
|
||||
}
|
||||
}
|
||||
|
||||
// [unique.ptr.runtime.modifiers] / [unique.ptr.single.modifiers]
|
||||
pointer release() noexcept
|
||||
{
|
||||
return std::exchange(ptr_, nullptr);
|
||||
}
|
||||
|
||||
void reset(pointer ptr = pointer()) noexcept
|
||||
{
|
||||
pointer old = std::exchange(ptr_, ptr);
|
||||
if (old) {
|
||||
this->get_deleter()(old);
|
||||
}
|
||||
}
|
||||
|
||||
template <class U>
|
||||
void reset(U) = delete;
|
||||
|
||||
void swap(unique_ptr &other) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
swap(this->get_deleter(), other.get_deleter());
|
||||
swap(ptr_, other.ptr_);
|
||||
}
|
||||
|
||||
// [unique.ptr.runtime.asgn] / [unique.ptr.single.asgn]
|
||||
unique_ptr &operator=(const unique_ptr &r) = delete;
|
||||
unique_ptr &operator=(unique_ptr &&r) noexcept
|
||||
{
|
||||
reset(r.release());
|
||||
this->get_deleter() = std::forward<D>(r.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
unique_ptr &operator=(nullptr_t) noexcept
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
template <class U, class E>
|
||||
enable_if_t<is_compatible_unique_ptr<U, E>() &&
|
||||
is_assignable<D &, E &&>::value,
|
||||
unique_ptr> &operator=(unique_ptr<U, E> &&u) noexcept
|
||||
{
|
||||
reset(u.release());
|
||||
this->get_deleter() = std::forward<E>(u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// [unique.ptr.runtime.observers] / [unique.ptr.single.observers]
|
||||
pointer get() const noexcept { return ptr_; }
|
||||
T &operator[](size_t index) const { return ptr_[index]; }
|
||||
explicit operator bool() const noexcept { return ptr_; }
|
||||
private:
|
||||
pointer ptr_;
|
||||
};
|
||||
|
||||
// [unique.ptr.create]
|
||||
template <typename T, typename... Args>
|
||||
enable_if_t<!is_array<T>::value,
|
||||
unique_ptr<T>> make_unique(Args &&... args)
|
||||
{
|
||||
return unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
enable_if_t<is_array<T>::value && extent<T>::value == 0,
|
||||
unique_ptr<T>> make_unique(size_t size)
|
||||
{
|
||||
return unique_ptr<T>(new remove_extent_t<T>[size]());
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
enable_if_t<extent<T>::value != 0,
|
||||
void> make_unique(Args &&... args) = delete;
|
||||
|
||||
// [unique.ptr.special]
|
||||
template< class T, class D>
|
||||
void swap(unique_ptr<T,D> &lhs, unique_ptr<T,D> &rhs) noexcept
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
template<class T1, class D1, class T2, class D2>
|
||||
bool operator==(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
{
|
||||
return x.get() == y.get();
|
||||
}
|
||||
|
||||
template<class T1, class D1, class T2, class D2>
|
||||
bool operator!=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
{
|
||||
return x.get() != y.get();
|
||||
}
|
||||
|
||||
template<class T1, class D1, class T2, class D2>
|
||||
bool operator<(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
{
|
||||
using CT = common_type_t<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer>;
|
||||
return less<CT>()(x.get(), y.get());
|
||||
}
|
||||
|
||||
template<class T1, class D1, class T2, class D2>
|
||||
bool operator<=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
{
|
||||
return !(y < x);
|
||||
}
|
||||
|
||||
template<class T1, class D1, class T2, class D2>
|
||||
bool operator>(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
{
|
||||
return y < x;
|
||||
}
|
||||
|
||||
template<class T1, class D1, class T2, class D2>
|
||||
bool operator>=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
{
|
||||
return !(x < y);
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator==(const unique_ptr<T, D> &x, nullptr_t) noexcept
|
||||
{
|
||||
return !x;
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator==(nullptr_t, const unique_ptr<T, D> &x) noexcept
|
||||
{
|
||||
return !x;
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator!=(const unique_ptr<T, D> &x, nullptr_t) noexcept
|
||||
{
|
||||
return bool(x);
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator!=(nullptr_t, const unique_ptr<T, D> &x) noexcept
|
||||
{
|
||||
return bool(x);
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator<(const unique_ptr<T, D> &x, nullptr_t) noexcept
|
||||
{
|
||||
return less<typename unique_ptr<T, D>::pointer>()(x.get(), nullptr);
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator<(nullptr_t, const unique_ptr<T, D> &x) noexcept
|
||||
{
|
||||
return less<typename unique_ptr<T, D>::pointer>()(nullptr, x.get());
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator>(const unique_ptr<T, D> &x, nullptr_t) noexcept
|
||||
{
|
||||
return nullptr < x;
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator>(nullptr_t, const unique_ptr<T, D> &x) noexcept
|
||||
{
|
||||
return x < nullptr;
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator<=(const unique_ptr<T, D> &x, nullptr_t) noexcept
|
||||
{
|
||||
return !(nullptr < x);
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator<=(nullptr_t, const unique_ptr<T, D> &x) noexcept
|
||||
{
|
||||
return !(x < nullptr);
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator>=(const unique_ptr<T, D> &x, nullptr_t) noexcept
|
||||
{
|
||||
return !(x < nullptr);
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator>=(nullptr_t, const unique_ptr<T, D> &x) noexcept
|
||||
{
|
||||
return !(nullptr < x);
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // __CC_ARM
|
||||
|
||||
namespace mstd {
|
||||
using std::align;
|
||||
using std::allocator;
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
* Toolchains will vary greatly in how much is in namespace std, depending on retargetting.
|
||||
*/
|
||||
|
||||
#if !defined __CC_ARM && !defined __IAR_SYSTEMS_ICC__
|
||||
#if !defined __IAR_SYSTEMS_ICC__
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
|
@ -56,9 +56,9 @@ extern "C" void __cxa_guard_release(int *guard_object_p);
|
|||
// IAR does not provide <mutex> at all - it errors on inclusion
|
||||
// ARMC6 provides it, but it is empty unless _ARM_LIBCPP_EXTERNAL_THREADS is defined
|
||||
// GCC has it, and only the actual `mutex` types are conditional on _GLIBCXX_HAS_GTHREADS
|
||||
// So pick up std stuff, unless ARMC5, ICC, or ARMC6-without-threads
|
||||
// So pick up std stuff, unless ICC, or ARMC6-without-threads
|
||||
namespace mstd {
|
||||
#if !defined __CC_ARM && !defined __IAR_SYSTEMS_ICC__ && !defined _LIBCPP_HAS_NO_THREADS
|
||||
#if !defined __IAR_SYSTEMS_ICC__ && !defined _LIBCPP_HAS_NO_THREADS
|
||||
using std::defer_lock;
|
||||
using std::defer_lock_t;
|
||||
using std::try_to_lock;
|
||||
|
|
|
@ -20,26 +20,6 @@
|
|||
/* <mstd_type_traits>
|
||||
*
|
||||
* - includes toolchain's <type_traits>
|
||||
* - For ARM C 5, standard C++11/14 features:
|
||||
* - std::integral_constant, std::true_type, std::false_type
|
||||
* - primary type categories (std::is_void, std::is_integral etc)
|
||||
* - composite type categories (std::is_reference etc)
|
||||
* - type properties (std::is_const, std::is_constructible etc), except std::is_final
|
||||
* - type property queries (std::alignment_of, std::rank, std::extent)
|
||||
* - type relations (std::is_same, std::is_base_of, std::is_convertible)
|
||||
* - const-volatile modifications (std::remove_cv, std::add_const etc)
|
||||
* - reference modifications (std::remove_reference, std::add_lvalue_reference etc)
|
||||
* - sign modifications (std::make_signed, std::make_unsigned)
|
||||
* - array modifications (std::remove_extent, std::remove_all_extents)
|
||||
* - pointer modifications (std::remove_pointer, std::add_pointer)
|
||||
* - other modifications:
|
||||
* - std::aligned_storage
|
||||
* - std::decay
|
||||
* - std::enable_if
|
||||
* - std::conditional
|
||||
* - std::common_type
|
||||
* - std::underlying_type
|
||||
* - std::result_of
|
||||
* - For all toolchains, C++17/20 backports:
|
||||
* - mstd::type_identity
|
||||
* - mstd::bool_constant
|
||||
|
@ -51,46 +31,11 @@
|
|||
*/
|
||||
|
||||
#include <mstd_cstddef>
|
||||
#ifdef __CC_ARM
|
||||
#include <_move.h>
|
||||
#else
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
// The template stuff in here is too confusing for astyle
|
||||
// *INDENT-OFF*
|
||||
|
||||
/* Start with some core C++11 type trait building blocks for ARMC5 */
|
||||
#ifdef __CC_ARM
|
||||
|
||||
namespace std {
|
||||
|
||||
/* integral_constant */
|
||||
template <typename T, T V>
|
||||
struct integral_constant {
|
||||
using value_type = T;
|
||||
using type = integral_constant;
|
||||
static constexpr T value = V;
|
||||
constexpr operator T() const noexcept
|
||||
{
|
||||
return V;
|
||||
}
|
||||
constexpr T operator()() const noexcept
|
||||
{
|
||||
return V;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, T V>
|
||||
constexpr T integral_constant<T, V>::value;
|
||||
|
||||
/* true_type, false_type */
|
||||
using true_type = integral_constant<bool, true>;
|
||||
using false_type = integral_constant<bool, false>;
|
||||
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
namespace mstd {
|
||||
|
||||
/* C++20 type identity */
|
||||
|
@ -106,13 +51,6 @@ using type_identity_t = typename type_identity<T>::type;
|
|||
/* void_t<Args...> is void if args are valid, else a substitution failure */
|
||||
#if __cpp_lib_void_t >= 201411
|
||||
using std::void_t;
|
||||
#elif defined __CC_ARM
|
||||
namespace impl {
|
||||
template <typename...>
|
||||
struct void_helper : type_identity<void> { };
|
||||
}
|
||||
template <typename... Ts>
|
||||
using void_t = typename impl::void_helper<Ts...>::type;
|
||||
#else
|
||||
template <typename...>
|
||||
using void_t = void;
|
||||
|
@ -136,55 +74,6 @@ struct invoke_result;
|
|||
|
||||
} // namespace mstd
|
||||
|
||||
#ifdef __CC_ARM
|
||||
namespace std {
|
||||
|
||||
/* Fill in core missing C++11/C++14 functionality for ARM C 5 into namespace std */
|
||||
/* First, the things needed to support the detector idiom. */
|
||||
|
||||
/* is_same */
|
||||
template <typename, typename>
|
||||
struct is_same : false_type { };
|
||||
|
||||
template <typename T>
|
||||
struct is_same<T, T> : true_type { };
|
||||
|
||||
/* conditional */
|
||||
template <bool B, typename T, typename F>
|
||||
struct conditional : mstd::type_identity<F> { };
|
||||
|
||||
template <typename T, typename F>
|
||||
struct conditional<true, T, F> : mstd::type_identity<T> { };
|
||||
|
||||
template <bool B, typename T, typename F>
|
||||
using conditional_t = typename conditional<B, T, F>::type;
|
||||
|
||||
/* enable_if */
|
||||
template <bool B, typename T = void>
|
||||
struct enable_if { };
|
||||
|
||||
template <typename T>
|
||||
struct enable_if<true, T> : mstd::type_identity<T> { };
|
||||
|
||||
template <bool B, typename T = void>
|
||||
using enable_if_t = typename enable_if<B, T>::type;
|
||||
|
||||
/* Forward declarations */
|
||||
template <typename From, typename To>
|
||||
struct is_convertible;
|
||||
|
||||
template <typename T>
|
||||
struct is_object;
|
||||
|
||||
template <typename T>
|
||||
struct is_reference;
|
||||
|
||||
template <typename T>
|
||||
class reference_wrapper;
|
||||
|
||||
} // namespace std
|
||||
#endif // __CC_ARM
|
||||
|
||||
namespace mstd {
|
||||
|
||||
using std::is_same;
|
||||
|
@ -275,809 +164,6 @@ using is_detected_convertible = std::is_convertible<detected_t<Op, Args...>, To>
|
|||
} // namespace experimental
|
||||
} // namespace mstd
|
||||
|
||||
#ifdef __CC_ARM
|
||||
/* More missing C++11/C++14 functionality for ARM C 5 */
|
||||
namespace std {
|
||||
|
||||
/* remove_const/volatile/cv */
|
||||
template <typename T>
|
||||
struct remove_const : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
struct remove_const<const T> : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
using remove_const_t = typename remove_const<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct remove_volatile : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
struct remove_volatile<volatile T> : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
using remove_volatile_t = typename remove_volatile<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct remove_cv : remove_volatile<remove_const_t<T>> { };
|
||||
|
||||
template <typename T>
|
||||
using remove_cv_t = typename remove_cv<T>::type;
|
||||
|
||||
/* add_const/volatile/cv */
|
||||
template <typename T>
|
||||
struct add_const : mstd::type_identity<const T> { };
|
||||
|
||||
template <typename T>
|
||||
using add_const_t = typename add_const<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct add_volatile : mstd::type_identity<volatile T> { };
|
||||
|
||||
template <typename T>
|
||||
using add_volatile_t = typename add_volatile<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct add_cv : mstd::type_identity<const volatile T> { };
|
||||
|
||||
template <typename T>
|
||||
using add_cv_t = typename add_cv<T>::type;
|
||||
|
||||
/* add_lvalue_reference / add_value_reference */
|
||||
namespace impl {
|
||||
template <typename T> // Base test - objects and references
|
||||
struct is_referenceable : mstd::disjunction<is_object<T>, is_reference<T>> { };
|
||||
template <typename R, typename... Args> // Specialisation - unqualified functions (non-variadic)
|
||||
struct is_referenceable<R(Args...)> : true_type { };
|
||||
template <typename R, typename... Args> // Specialisation - unqualified functions (variadic)
|
||||
struct is_referenceable<R(Args... ...)> : true_type { };
|
||||
|
||||
template <typename T, bool = is_referenceable<T>::value>
|
||||
struct add_lvalue_reference : mstd::type_identity<T> { };
|
||||
template <typename T>
|
||||
struct add_lvalue_reference<T, true> : mstd::type_identity<T &> { };
|
||||
|
||||
template <typename T, bool = is_referenceable<T>::value>
|
||||
struct add_rvalue_reference : mstd::type_identity<T> { };
|
||||
template <typename T>
|
||||
struct add_rvalue_reference<T, true> : mstd::type_identity<T &&> { };
|
||||
} // namespace impl
|
||||
|
||||
template <typename T>
|
||||
struct add_lvalue_reference : impl::add_lvalue_reference<T> { };
|
||||
template <typename T>
|
||||
using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct add_rvalue_reference : impl::add_rvalue_reference<T> { };
|
||||
template <typename T>
|
||||
using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
|
||||
|
||||
// [declval]
|
||||
template <class T>
|
||||
add_rvalue_reference_t<T> declval() noexcept;
|
||||
|
||||
// [meta.unary.cat]
|
||||
/* is_void */
|
||||
template <typename T>
|
||||
struct is_void : is_same<void, remove_cv_t<T>> { };
|
||||
|
||||
/* is_null_pointer */
|
||||
template <typename T>
|
||||
struct is_null_pointer : is_same<decltype(nullptr), remove_cv_t<T>> { };
|
||||
|
||||
/* is_integral */
|
||||
template <typename T>
|
||||
struct is_integral :
|
||||
mstd::disjunction<
|
||||
is_same<bool, remove_cv_t<T>>,
|
||||
is_same<char, remove_cv_t<T>>,
|
||||
is_same<signed char, remove_cv_t<T>>,
|
||||
is_same<unsigned char, remove_cv_t<T>>,
|
||||
is_same<char16_t, remove_cv_t<T>>,
|
||||
is_same<char32_t, remove_cv_t<T>>,
|
||||
is_same<wchar_t, remove_cv_t<T>>,
|
||||
is_same<short, remove_cv_t<T>>,
|
||||
is_same<unsigned short, remove_cv_t<T>>,
|
||||
is_same<int, remove_cv_t<T>>,
|
||||
is_same<unsigned int, remove_cv_t<T>>,
|
||||
is_same<long, remove_cv_t<T>>,
|
||||
is_same<unsigned long, remove_cv_t<T>>,
|
||||
is_same<long long, remove_cv_t<T>>,
|
||||
is_same<unsigned long long, remove_cv_t<T>>> { };
|
||||
|
||||
/* is_floating_point */
|
||||
template <typename T>
|
||||
struct is_floating_point :
|
||||
mstd::disjunction<
|
||||
is_same<float, remove_cv_t<T>>,
|
||||
is_same<double, remove_cv_t<T>>,
|
||||
is_same<long double, remove_cv_t<T>>> { };
|
||||
|
||||
/* is_array */
|
||||
template <typename T>
|
||||
struct is_array : false_type { };
|
||||
|
||||
template <typename T>
|
||||
struct is_array<T[]> : true_type { };
|
||||
|
||||
template <typename T, size_t N>
|
||||
struct is_array<T[N]> : true_type { };
|
||||
|
||||
/* is_pointer */
|
||||
namespace impl {
|
||||
template <typename T>
|
||||
struct is_unqualified_pointer : false_type { };
|
||||
template <typename T>
|
||||
struct is_unqualified_pointer<T *> : true_type { };
|
||||
} // namespace impl
|
||||
|
||||
template <typename T>
|
||||
struct is_pointer : impl::is_unqualified_pointer<remove_cv_t<T>> { };
|
||||
|
||||
/* is_lvalue_reference */
|
||||
template <typename T>
|
||||
struct is_lvalue_reference : false_type { };
|
||||
|
||||
template <typename T>
|
||||
struct is_lvalue_reference<T &> : true_type { };
|
||||
|
||||
/* is_rvalue_reference */
|
||||
template <typename T>
|
||||
struct is_rvalue_reference : false_type { };
|
||||
|
||||
template <typename T>
|
||||
struct is_rvalue_reference<T &&> : true_type { };
|
||||
|
||||
/* is_enum */
|
||||
template <typename T>
|
||||
struct is_enum : mstd::bool_constant<__is_enum(T)> { };
|
||||
|
||||
/* is_union */
|
||||
template <typename T>
|
||||
struct is_union : mstd::bool_constant<__is_union(T)> { };
|
||||
|
||||
/* is_class */
|
||||
template <typename T>
|
||||
struct is_class : mstd::bool_constant<__is_class(T)> { };
|
||||
|
||||
/* is_function */
|
||||
template <typename T>
|
||||
struct is_function : false_type { };
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args...)> : true_type { }; // 0 or more named arguments
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args... ...)> : true_type { }; // 0 or more named arguments and variadic
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args...) &> : true_type { };
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args... ...) &> : true_type { };
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args...) &&> : true_type { };
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args... ...) &&> : true_type { };
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args...) const> : true_type { };
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args... ...) const> : true_type { };
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args...) const &> : true_type { };
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args... ...) const &> : true_type { };
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args...) const &&> : true_type { };
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args... ...) const &&> : true_type { };
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args...) volatile> : true_type { };
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args... ...) volatile> : true_type { };
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args...) volatile &> : true_type { };
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args... ...) volatile &> : true_type { };
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args...) volatile &&> : true_type { };
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args... ...) volatile &&> : true_type { };
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args...) const volatile> : true_type { };
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args... ...) const volatile> : true_type { };
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args...) const volatile &> : true_type { };
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args... ...) const volatile &> : true_type { };
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args...) const volatile &&> : true_type { };
|
||||
template <typename R, typename... Args>
|
||||
struct is_function<R(Args... ...) const volatile &&> : true_type { };
|
||||
|
||||
/* is_member_function_pointer */
|
||||
namespace impl {
|
||||
/* Two helper filters to complement is_function */
|
||||
template <typename>
|
||||
using always_true = true_type;
|
||||
template <typename T>
|
||||
using is_not_function = mstd::negation<is_function<T>>;
|
||||
|
||||
template <typename T, template<typename> class Filter = always_true>
|
||||
struct is_unqualified_member_pointer : false_type { };
|
||||
template <typename T, template<typename> class Filter, typename U>
|
||||
struct is_unqualified_member_pointer<T U::*, Filter> : Filter<T> { };
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template <typename T>
|
||||
struct is_member_function_pointer : impl::is_unqualified_member_pointer<remove_cv_t<T>, is_function> { };
|
||||
|
||||
/* is_member_object_pointer */
|
||||
template <typename T>
|
||||
struct is_member_object_pointer : impl::is_unqualified_member_pointer<remove_cv_t<T>, impl::is_not_function> { };
|
||||
|
||||
/* is_reference = (is_lvalue_reference || is_rvalue_reference) */
|
||||
template <typename T>
|
||||
struct is_reference : false_type { };
|
||||
|
||||
template <typename T>
|
||||
struct is_reference<T &> : true_type { };
|
||||
|
||||
template <typename T>
|
||||
struct is_reference<T &&> : true_type { };
|
||||
|
||||
/* is_arithmetic */
|
||||
template <typename T>
|
||||
struct is_arithmetic : mstd::disjunction<is_integral<T>, is_floating_point<T>> { };
|
||||
|
||||
/* is_fundamental */
|
||||
template <typename T>
|
||||
struct is_fundamental : mstd::disjunction<is_arithmetic<T>, is_void<T>, is_null_pointer<T>> { };
|
||||
|
||||
/* is_compound */
|
||||
template <typename T>
|
||||
struct is_compound : mstd::negation<is_fundamental<T>> { };
|
||||
|
||||
/* is_member_pointer */
|
||||
template <typename T>
|
||||
struct is_member_pointer : impl::is_unqualified_member_pointer<remove_cv_t<T>> { };
|
||||
|
||||
/* is_scalar */
|
||||
template <typename T>
|
||||
struct is_scalar : mstd::disjunction<is_arithmetic<T>, is_enum<T>, is_pointer<T>, is_member_pointer<T>, is_null_pointer<T>> { };
|
||||
|
||||
/* is_object */
|
||||
template <typename T>
|
||||
struct is_object : mstd::disjunction<is_scalar<T>, is_array<T>, is_union<T>, is_class<T>> { };
|
||||
|
||||
// [meta.unary.prop]
|
||||
/* is_const */
|
||||
template <typename T>
|
||||
struct is_const : false_type { };
|
||||
|
||||
template <typename T>
|
||||
struct is_const<const T> : true_type { };
|
||||
|
||||
/* is_volatile */
|
||||
template <typename T>
|
||||
struct is_volatile : false_type { };
|
||||
|
||||
template <typename T>
|
||||
struct is_volatile<volatile T> : true_type { };
|
||||
|
||||
/* is_trivial */
|
||||
template <typename T>
|
||||
struct is_trivial : mstd::bool_constant<__is_trivial(T)> { };
|
||||
|
||||
/* is_trivially_copyable */
|
||||
template <typename T>
|
||||
struct is_trivially_copyable : mstd::bool_constant<__is_trivially_copyable(T)> { };
|
||||
|
||||
/* is_standard_layout */
|
||||
template <typename T>
|
||||
struct is_standard_layout : mstd::bool_constant<__is_standard_layout(T)> { };
|
||||
|
||||
/* is_pod */
|
||||
template <typename T>
|
||||
struct is_pod : mstd::bool_constant<__is_pod(T)> { };
|
||||
|
||||
/* is_literal_type */
|
||||
template <typename T>
|
||||
struct is_literal_type : mstd::bool_constant<__is_literal_type(T)> { };
|
||||
|
||||
/* is_empty */
|
||||
template <typename T>
|
||||
struct is_empty : mstd::bool_constant<__is_empty(T)> { };
|
||||
|
||||
/* is_polymorphic */
|
||||
template <typename T>
|
||||
struct is_polymorphic : mstd::bool_constant<__is_polymorphic(T)> { };
|
||||
|
||||
/* is_abstract */
|
||||
template <typename T>
|
||||
struct is_abstract : mstd::bool_constant<__is_abstract(T)> { };
|
||||
|
||||
/* is_final (C++14) not supported */
|
||||
|
||||
/* is_signed */
|
||||
namespace impl {
|
||||
template <typename T, bool = is_arithmetic<T>::value >
|
||||
struct is_signed : false_type { };
|
||||
template <typename T>
|
||||
struct is_signed<T, true> : mstd::bool_constant<T(-1) < T(0)> { };
|
||||
} // namespace impl
|
||||
|
||||
template <typename T>
|
||||
struct is_signed : impl::is_signed<T> { };
|
||||
|
||||
/* is_unsigned */
|
||||
namespace impl {
|
||||
template <typename T, bool = is_arithmetic<T>::value >
|
||||
struct is_unsigned : false_type { };
|
||||
template <typename T>
|
||||
struct is_unsigned<T, true> : mstd::bool_constant<T(0) < T(-1)> { };
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct is_unsigned : impl::is_unsigned<T> { };
|
||||
|
||||
/* is_constructible */
|
||||
template <typename T, typename... Args>
|
||||
struct is_constructible : mstd::bool_constant<__is_constructible(T, Args...)> { };
|
||||
|
||||
/* is_default_constructible */
|
||||
template <typename T>
|
||||
struct is_default_constructible : is_constructible<T> { };
|
||||
|
||||
/* is_copy_constructible */
|
||||
template <typename T>
|
||||
struct is_copy_constructible : is_constructible<T, add_lvalue_reference_t<add_const_t<T>>> { };
|
||||
|
||||
/* is_move_constructible */
|
||||
template <typename T>
|
||||
struct is_move_constructible : is_constructible<T, add_rvalue_reference_t<T>> { };
|
||||
|
||||
/* is_assignable */
|
||||
namespace impl {
|
||||
template <typename To, typename From, typename = void>
|
||||
struct is_assignable : std::false_type { };
|
||||
|
||||
template <typename To, typename From>
|
||||
struct is_assignable<To, From, mstd::void_t<decltype(std::declval<To>() = std::declval<From>())>> : std::true_type { };
|
||||
} // namespace impl
|
||||
|
||||
template <typename To, typename From>
|
||||
struct is_assignable : impl::is_assignable<To, From> { };
|
||||
|
||||
/* is_copy_assignable */
|
||||
template <typename T>
|
||||
struct is_copy_assignable : is_assignable<add_lvalue_reference_t<T>,
|
||||
add_lvalue_reference_t<add_const_t<T>>> { };
|
||||
|
||||
/* is_move_assignable */
|
||||
template <typename T>
|
||||
struct is_move_assignable : is_assignable<add_lvalue_reference_t<T>,
|
||||
add_rvalue_reference_t<T>> { };
|
||||
|
||||
/* is_destructible */
|
||||
template <typename T>
|
||||
struct is_destructible : mstd::bool_constant<__is_destructible(T)> { };
|
||||
|
||||
/* is_trivially_constructible */
|
||||
template <typename T, typename... Args>
|
||||
struct is_trivially_constructible : mstd::bool_constant<__is_trivially_constructible(T, Args...)> { };
|
||||
|
||||
/* is_trivially_default_constructible */
|
||||
template <typename T>
|
||||
struct is_trivially_default_constructible : is_trivially_constructible<T> { };
|
||||
|
||||
/* is_trivially_copy_constructible */
|
||||
template <typename T>
|
||||
struct is_trivially_copy_constructible : is_trivially_constructible<T, add_lvalue_reference_t<add_const_t<T>>> { };
|
||||
|
||||
/* is_trivially_move_constructible */
|
||||
template <typename T>
|
||||
struct is_trivially_move_constructible : is_trivially_constructible<T, add_rvalue_reference_t<T>> { };
|
||||
|
||||
/* is_trivially_assignable */
|
||||
template <typename To, typename From>
|
||||
struct is_trivially_assignable : mstd::bool_constant<__is_trivially_assignable(To, From)> { };
|
||||
|
||||
/* is_trivially_copy_assignable */
|
||||
template <typename T>
|
||||
struct is_trivially_copy_assignable : is_trivially_assignable<add_lvalue_reference_t<T>,
|
||||
add_lvalue_reference_t<add_const_t<T>>> { };
|
||||
|
||||
/* is_trivially_move_assignable */
|
||||
template <typename T>
|
||||
struct is_trivially_move_assignable : is_trivially_assignable<add_lvalue_reference_t<T>,
|
||||
add_rvalue_reference_t<T>> { };
|
||||
|
||||
/* is_trivially_destructible */
|
||||
template <typename T>
|
||||
struct is_trivially_destructible : mstd::bool_constant<__is_trivially_destructible(T)> { };
|
||||
|
||||
/* is_nothrow_constructible */
|
||||
template <typename T, typename... Args>
|
||||
struct is_nothrow_constructible : mstd::bool_constant<__is_nothrow_constructible(T, Args...)> { };
|
||||
|
||||
/* is_nothrow_default_constructible */
|
||||
template <typename T>
|
||||
struct is_nothrow_default_constructible : is_nothrow_constructible<T> { };
|
||||
|
||||
/* is_nothrow_copy_constructible */
|
||||
template <typename T>
|
||||
struct is_nothrow_copy_constructible : is_nothrow_constructible<T, add_lvalue_reference_t<add_const_t<T>>> { };
|
||||
|
||||
/* is_nothrow_move_constructible */
|
||||
template <typename T>
|
||||
struct is_nothrow_move_constructible : is_nothrow_constructible<T, add_rvalue_reference_t<T>> { };
|
||||
|
||||
/* is_nothrow_assignable */
|
||||
template <typename To, typename From>
|
||||
struct is_nothrow_assignable : mstd::bool_constant<__is_nothrow_assignable(To, From)> { };
|
||||
|
||||
/* is_copy_assignable */
|
||||
template <typename T>
|
||||
struct is_nothrow_copy_assignable : is_nothrow_assignable<add_lvalue_reference_t<T>,
|
||||
add_lvalue_reference_t<add_const_t<T>>> { };
|
||||
|
||||
/* is_move_assignable */
|
||||
template <typename T>
|
||||
struct is_nothrow_move_assignable : is_nothrow_assignable<add_lvalue_reference_t<T>,
|
||||
add_rvalue_reference_t<T>> { };
|
||||
|
||||
/* is_nothrow_destructible */
|
||||
template <typename T>
|
||||
struct is_nothrow_destructible : mstd::bool_constant<__is_nothrow_destructible(T)> { };
|
||||
|
||||
/* has_virtual_destructor */
|
||||
template <typename T>
|
||||
struct has_virtual_destructor : mstd::bool_constant<__has_virtual_destructor(T)> { };
|
||||
|
||||
// [meta.unary.prop.query]
|
||||
/* alignment_of */
|
||||
template <typename T>
|
||||
struct alignment_of : integral_constant<size_t, alignof(T)> { };
|
||||
|
||||
/* rank */
|
||||
template <typename T>
|
||||
struct rank : integral_constant<size_t, 0> { };
|
||||
|
||||
template <typename T>
|
||||
struct rank<T[]> : integral_constant<size_t, rank<T>::value + 1u> { };
|
||||
|
||||
template <typename T, size_t N>
|
||||
struct rank<T[N]> : integral_constant<size_t, rank<T>::value + 1u> { };
|
||||
|
||||
/* extent */
|
||||
template <typename T, unsigned I = 0>
|
||||
struct extent : integral_constant<size_t, 0> { };
|
||||
|
||||
template <typename T>
|
||||
struct extent<T[], 0> : integral_constant<size_t, 0> { };
|
||||
|
||||
template <typename T, unsigned I>
|
||||
struct extent<T[], I> : extent<T, I - 1> { };
|
||||
|
||||
template <typename T, size_t N>
|
||||
struct extent<T[N], 0> : integral_constant<size_t, N> { };
|
||||
|
||||
template <typename T, size_t N, unsigned I>
|
||||
struct extent<T[N], I> : extent<T, I - 1> { };
|
||||
|
||||
// [meta.rel]
|
||||
/* is_convertible */
|
||||
/* __is_convertible_to apparently returns true for any From if To is void */
|
||||
template <typename From, typename To>
|
||||
struct is_convertible : conditional_t<is_void<To>::value,
|
||||
is_void<From>,
|
||||
mstd::bool_constant<__is_convertible_to(From, To)>> { };
|
||||
|
||||
/* is_base_of */
|
||||
template <typename Base, typename Derived>
|
||||
struct is_base_of : mstd::bool_constant<__is_base_of(Base, Derived) && __is_class(Derived)> { };
|
||||
|
||||
|
||||
/* make_signed */
|
||||
namespace impl
|
||||
{
|
||||
template <typename CV, typename T, bool = is_const<CV>::value, bool = is_volatile<CV>::value>
|
||||
struct copy_cv : mstd::type_identity<T> { };
|
||||
|
||||
template <typename CV, typename T>
|
||||
struct copy_cv<CV, T, true, false> : add_const<T> { };
|
||||
|
||||
template <typename CV, typename T>
|
||||
struct copy_cv<CV, T, false, true> : add_volatile<T> { };
|
||||
|
||||
template <typename CV, typename T>
|
||||
struct copy_cv<CV, T, true, true> : add_cv<T> { };
|
||||
|
||||
template <typename CV, typename T>
|
||||
using copy_cv_t = typename copy_cv<CV, T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct make_signed : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
using make_signed_t = typename make_signed<T>::type;
|
||||
|
||||
template <>
|
||||
struct make_signed<char> : mstd::type_identity<signed char> { };
|
||||
|
||||
template <>
|
||||
struct make_signed<unsigned char> : mstd::type_identity<signed char> { };
|
||||
|
||||
template <>
|
||||
struct make_signed<unsigned short> : mstd::type_identity<short> { };
|
||||
|
||||
template <>
|
||||
struct make_signed<unsigned int> : mstd::type_identity<int> { };
|
||||
|
||||
template <>
|
||||
struct make_signed<unsigned long> : mstd::type_identity<long> { };
|
||||
|
||||
template <>
|
||||
struct make_signed<unsigned long long> : mstd::type_identity<long long> { };
|
||||
|
||||
template <typename T>
|
||||
struct make_unsigned : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
using make_unsigned_t = typename make_unsigned<T>::type;
|
||||
|
||||
template <>
|
||||
struct make_unsigned<char> : mstd::type_identity<unsigned char> { };
|
||||
|
||||
template <>
|
||||
struct make_unsigned<signed char> : mstd::type_identity<unsigned char> { };
|
||||
|
||||
template <>
|
||||
struct make_unsigned<short> : mstd::type_identity<unsigned short> { };
|
||||
|
||||
template <>
|
||||
struct make_unsigned<int> : mstd::type_identity<unsigned int> { };
|
||||
|
||||
template <>
|
||||
struct make_unsigned<long> : mstd::type_identity<unsigned long> { };
|
||||
|
||||
template <>
|
||||
struct make_unsigned<long long> : mstd::type_identity<unsigned long long> { };
|
||||
|
||||
template <typename T, bool IsIntegral = is_integral<T>::value, bool IsEnum = is_enum<T>::value>
|
||||
struct make_signed_selector;
|
||||
|
||||
template <typename T>
|
||||
class make_signed_selector<T, true, false> { // integral
|
||||
using raw_signed_t = make_signed_t<remove_cv_t<T>>;
|
||||
public:
|
||||
using type = copy_cv_t<T, raw_signed_t>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class make_signed_selector<T, false, true> { // enum
|
||||
using raw_signed_t = mstd::conditional_t<sizeof(T) <= 1, signed char,
|
||||
mstd::conditional_t<sizeof(T) <= sizeof(short), short,
|
||||
mstd::conditional_t<sizeof(T) <= sizeof(int), int,
|
||||
mstd::conditional_t<sizeof(T) <= sizeof(long), long, long long>>>>;
|
||||
public:
|
||||
using type = copy_cv_t<T, raw_signed_t>;
|
||||
};
|
||||
|
||||
template <typename T, bool IsIntegral = is_integral<T>::value, bool IsEnum = is_enum<T>::value>
|
||||
struct make_unsigned_selector;
|
||||
|
||||
template <typename T>
|
||||
class make_unsigned_selector<T, true, false> { // integral
|
||||
using raw_unsigned_t = make_unsigned_t<remove_cv_t<T>>;
|
||||
public:
|
||||
using type = copy_cv_t<T, raw_unsigned_t>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class make_unsigned_selector<T, false, true> { // enum
|
||||
using raw_unsigned_t = mstd::conditional_t<sizeof(T) <= 1, unsigned char,
|
||||
mstd::conditional_t<sizeof(T) <= sizeof(short), unsigned short,
|
||||
mstd::conditional_t<sizeof(T) <= sizeof(int), unsigned int,
|
||||
mstd::conditional_t<sizeof(T) <= sizeof(long), unsigned long, unsigned long long>>>>;
|
||||
public:
|
||||
using type = copy_cv_t<T, raw_unsigned_t>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct make_signed : impl::make_signed_selector<T> { };
|
||||
|
||||
template <>
|
||||
struct make_signed<bool>; // bool is integral, but make_signed does not apply
|
||||
|
||||
template <typename T>
|
||||
using make_signed_t = typename make_signed<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct make_unsigned : impl::make_unsigned_selector<T> { };
|
||||
|
||||
template <>
|
||||
struct make_unsigned<bool>; // bool is integral, but make_unsigned does not apply
|
||||
|
||||
template <typename T>
|
||||
using make_unsigned_t = typename make_unsigned<T>::type;
|
||||
|
||||
/* remove_extent */
|
||||
template <typename T>
|
||||
struct remove_extent : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
struct remove_extent<T[]> : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T, size_t N>
|
||||
struct remove_extent<T[N]> : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
using remove_extent_t = typename remove_extent<T>::type;
|
||||
|
||||
/* remove_all_extents */
|
||||
template <typename T>
|
||||
struct remove_all_extents : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
using remove_all_extents_t = typename remove_all_extents<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct remove_all_extents<T[]> : mstd::type_identity<remove_all_extents_t<T>> { };
|
||||
|
||||
template <typename T, size_t N>
|
||||
struct remove_all_extents<T[N]> : mstd::type_identity<remove_all_extents_t<T>> { };
|
||||
|
||||
/* remove_pointer */
|
||||
template <typename T>
|
||||
struct remove_pointer : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
struct remove_pointer<T *> : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
struct remove_pointer<T * const> : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
struct remove_pointer<T * volatile> : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
struct remove_pointer<T * const volatile> : mstd::type_identity<T> { };
|
||||
|
||||
template <typename T>
|
||||
using remove_pointer_t = typename remove_pointer<T>::type;
|
||||
|
||||
/* add_pointer */
|
||||
namespace impl {
|
||||
template <typename T, bool = mstd::disjunction<is_referenceable<T>, is_void<T>>::value>
|
||||
struct add_pointer : mstd::type_identity<T> { };
|
||||
template <typename T>
|
||||
struct add_pointer<T, true> : mstd::type_identity<remove_reference_t<T> *> { };
|
||||
} // namespace impl
|
||||
|
||||
template <typename T>
|
||||
struct add_pointer : impl::add_pointer<T> { };
|
||||
|
||||
template <typename T>
|
||||
using add_pointer_t = typename add_pointer<T>::type;
|
||||
|
||||
/* aligned_storage */
|
||||
namespace impl {
|
||||
constexpr size_t possible_alignment_requirement(size_t n)
|
||||
{
|
||||
return n <= 1 ? 1 :
|
||||
n <= 2 ? 2 :
|
||||
n <= 4 ? 4 : 8;
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t Len, size_t Align = impl::possible_alignment_requirement(Len)>
|
||||
struct aligned_storage {
|
||||
struct type {
|
||||
__attribute__((aligned(Align))) unsigned char data[Len];
|
||||
};
|
||||
};
|
||||
|
||||
template <size_t Len, size_t Align = impl::possible_alignment_requirement(Len)>
|
||||
using aligned_storage_t = typename aligned_storage<Len, Align>::type;
|
||||
|
||||
/* decay */
|
||||
namespace impl {
|
||||
template <typename T>
|
||||
struct decay : mstd::type_identity<
|
||||
conditional_t<is_array<T>::value,
|
||||
remove_extent_t<T> *,
|
||||
conditional_t<is_function<T>::value,
|
||||
add_pointer_t<T>,
|
||||
remove_cv_t<T>
|
||||
>
|
||||
>
|
||||
> { };
|
||||
} // namespace impl
|
||||
|
||||
template <typename T>
|
||||
struct decay : impl::decay<remove_reference_t<T>> { };
|
||||
|
||||
template <typename T>
|
||||
using decay_t = typename decay<T>::type;
|
||||
|
||||
/* common_type (0 types) */
|
||||
template <typename...>
|
||||
struct common_type { };
|
||||
|
||||
template <typename... T>
|
||||
using common_type_t = typename common_type<T...>::type;
|
||||
|
||||
namespace impl {
|
||||
template <typename T1, typename T2>
|
||||
using ternary_t = decltype(false ? declval<T1>() : declval<T2>());
|
||||
|
||||
template <typename T1, typename T2, typename=void>
|
||||
struct ct2_default { };
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct ct2_default<T1, T2, mstd::void_t<ternary_t<T1, T2>>> : mstd::type_identity<decay_t<ternary_t<T1, T2>>> { };
|
||||
|
||||
template <typename T1, typename T2, typename D1 = decay_t<T1>, typename D2 = decay_t<T2>>
|
||||
struct ct2 : common_type<D1, D2> { };
|
||||
|
||||
template <typename D1, typename D2>
|
||||
struct ct2<D1, D2, D1, D2> : ct2_default<D1, D2> { };
|
||||
|
||||
template <typename Void, typename T1, typename T2, typename... TN>
|
||||
struct ct_multi { };
|
||||
|
||||
template <typename T1, typename T2, typename... TN>
|
||||
struct ct_multi<mstd::void_t<common_type<T1, T2>>, T1, T2, TN...> : common_type<common_type_t<T1, T2>, TN...> { };
|
||||
} // namespace impl
|
||||
|
||||
/* common_type (1 type) */
|
||||
template <typename T>
|
||||
struct common_type<T> : common_type<T, T> { };
|
||||
|
||||
/* common_type (2 types) - applications can add extra 2-type specializations */
|
||||
template <typename T1, typename T2>
|
||||
struct common_type<T1, T2> : impl::ct2<T1, T2> { };
|
||||
|
||||
/* common_type (3+ types) */
|
||||
template <typename T1, typename T2, typename... TN>
|
||||
struct common_type<T1, T2, TN...> : impl::ct_multi<void, T1, T2, TN...> { };
|
||||
|
||||
/* underlying_type */
|
||||
template <typename T>
|
||||
struct underlying_type : mstd::type_identity<__underlying_type(T)> { };
|
||||
|
||||
template <typename T>
|
||||
using underlying_type_t = typename underlying_type<T>::type;
|
||||
|
||||
/* result_of */
|
||||
template <typename>
|
||||
struct result_of;
|
||||
|
||||
template <typename F, typename... Args>
|
||||
struct result_of<F(Args...)> : mstd::invoke_result<F, Args...> { };
|
||||
|
||||
template <typename T>
|
||||
using result_of_t = typename result_of<T>::type;
|
||||
|
||||
} // namespace std
|
||||
#endif // __CC_ARM
|
||||
|
||||
|
||||
/* More post-C++14 stuff */
|
||||
namespace mstd {
|
||||
|
||||
|
@ -1200,14 +286,12 @@ using remove_cvref_t = typename remove_cvref<T>::type;
|
|||
|
||||
}
|
||||
|
||||
#ifndef __CC_ARM
|
||||
#if __cpp_lib_invoke < 201411
|
||||
#include <utility> // want std::forward
|
||||
#include <functional> // want std::reference_wrapper
|
||||
#elif __cpp_lib_is_invocable < 201703
|
||||
#include <functional> // want std::invoke
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace mstd {
|
||||
/* C++17 invoke_result, is_invocable, invoke */
|
||||
|
@ -1388,24 +472,4 @@ constexpr bool is_constant_evaluated() noexcept
|
|||
|
||||
} // namespace mstd
|
||||
|
||||
#ifdef __CC_ARM
|
||||
// And may as well give ourselves all the post C++14 stuff in std
|
||||
// to aid our implementations of std::tuple etc - not safe to do this for other toolchains
|
||||
namespace std {
|
||||
using mstd::bool_constant;
|
||||
using mstd::conjunction;
|
||||
using mstd::disjunction;
|
||||
using mstd::negation;
|
||||
using mstd::void_t;
|
||||
using mstd::type_identity;
|
||||
using mstd::type_identity_t;
|
||||
using mstd::is_invocable;
|
||||
using mstd::is_invocable_r;
|
||||
using mstd::invoke_result;
|
||||
using mstd::invoke_result_t;
|
||||
using mstd::remove_cvref;
|
||||
using mstd::remove_cvref_t;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MSTD_TYPE_TRAITS_ */
|
||||
|
|
|
@ -36,270 +36,6 @@
|
|||
|
||||
#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;
|
||||
|
@ -321,7 +57,7 @@ using std::index_sequence;
|
|||
using std::make_integer_sequence;
|
||||
using std::make_index_sequence;
|
||||
using std::index_sequence_for;
|
||||
|
||||
using std::swap;
|
||||
// C++17 [utility.as_const] */
|
||||
#if __cpp_lib_as_const >= 201510
|
||||
using std::as_const;
|
||||
|
|
|
@ -94,18 +94,7 @@ extern "C" {
|
|||
#define MBED_SUB3_IMM "IL" // SUB or ADD, 12-bit immediate
|
||||
#endif
|
||||
|
||||
// ARM C 5 inline assembler recommends against using LDREX/STREX
|
||||
// for same reason as intrinsics, but there's no other way to get
|
||||
// inlining. ARM C 5 is being retired anyway.
|
||||
|
||||
#ifdef __CC_ARM
|
||||
#pragma diag_suppress 3732
|
||||
#define DO_MBED_LOCKFREE_EXCHG_ASM(M) \
|
||||
__asm { \
|
||||
LDREX##M oldValue, [valuePtr] ; \
|
||||
STREX##M fail, newValue, [valuePtr] \
|
||||
}
|
||||
#elif defined __clang__ || defined __GNUC__
|
||||
#if defined __clang__ || defined __GNUC__
|
||||
#define DO_MBED_LOCKFREE_EXCHG_ASM(M) \
|
||||
__asm volatile ( \
|
||||
".syntax unified\n\t" \
|
||||
|
@ -131,14 +120,7 @@ extern "C" {
|
|||
)
|
||||
#endif
|
||||
|
||||
#ifdef __CC_ARM
|
||||
#define DO_MBED_LOCKFREE_NEWVAL_2OP_ASM(OP, Constants, M) \
|
||||
__asm { \
|
||||
LDREX##M newValue, [valuePtr] ; \
|
||||
OP newValue, arg ; \
|
||||
STREX##M fail, newValue, [valuePtr] \
|
||||
}
|
||||
#elif defined __clang__ || defined __GNUC__
|
||||
#if defined __clang__ || defined __GNUC__
|
||||
#define DO_MBED_LOCKFREE_NEWVAL_2OP_ASM(OP, Constants, M) \
|
||||
__asm volatile ( \
|
||||
".syntax unified\n\t" \
|
||||
|
@ -167,14 +149,7 @@ extern "C" {
|
|||
)
|
||||
#endif
|
||||
|
||||
#ifdef __CC_ARM
|
||||
#define DO_MBED_LOCKFREE_OLDVAL_3OP_ASM(OP, Constants, M) \
|
||||
__asm { \
|
||||
LDREX##M oldValue, [valuePtr] ; \
|
||||
OP newValue, oldValue, arg ; \
|
||||
STREX##M fail, newValue, [valuePtr] \
|
||||
}
|
||||
#elif defined __clang__ || defined __GNUC__
|
||||
#if defined __clang__ || defined __GNUC__
|
||||
#define DO_MBED_LOCKFREE_OLDVAL_3OP_ASM(OP, Constants, M) \
|
||||
__asm volatile ( \
|
||||
".syntax unified\n\t" \
|
||||
|
@ -207,15 +182,7 @@ extern "C" {
|
|||
/* Bitwise operations are harder to do in ARMv8-M baseline - there
|
||||
* are only 2-operand versions of the instructions.
|
||||
*/
|
||||
#ifdef __CC_ARM
|
||||
#define DO_MBED_LOCKFREE_OLDVAL_2OP_ASM(OP, Constants, M) \
|
||||
__asm { \
|
||||
LDREX##M oldValue, [valuePtr] ; \
|
||||
MOV newValue, oldValue ; \
|
||||
OP newValue, arg ; \
|
||||
STREX##M fail, newValue, [valuePtr] \
|
||||
}
|
||||
#elif defined __clang__ || defined __GNUC__
|
||||
#if defined __clang__ || defined __GNUC__
|
||||
#define DO_MBED_LOCKFREE_OLDVAL_2OP_ASM(OP, Constants, M) \
|
||||
__asm volatile ( \
|
||||
".syntax unified\n\t" \
|
||||
|
@ -252,14 +219,7 @@ extern "C" {
|
|||
* implementations the same.
|
||||
*/
|
||||
#if MBED_EXCLUSIVE_ACCESS_ARM
|
||||
#ifdef __CC_ARM
|
||||
#define DO_MBED_LOCKFREE_CAS_WEAK_ASM(M) \
|
||||
__asm { \
|
||||
LDREX##M oldValue, [ptr] ; \
|
||||
SUBS fail, oldValue, expectedValue ; \
|
||||
STREX##M##EQ fail, desiredValue, [ptr] \
|
||||
}
|
||||
#elif defined __clang__ || defined __GNUC__
|
||||
#if defined __clang__ || defined __GNUC__
|
||||
#define DO_MBED_LOCKFREE_CAS_WEAK_ASM(M) \
|
||||
__asm volatile ( \
|
||||
".syntax unified\n\t" \
|
||||
|
@ -288,16 +248,7 @@ extern "C" {
|
|||
)
|
||||
#endif
|
||||
#else // MBED_EXCLUSIVE_ACCESS_ARM
|
||||
#ifdef __CC_ARM
|
||||
#define DO_MBED_LOCKFREE_CAS_WEAK_ASM(M) \
|
||||
__asm { \
|
||||
LDREX##M oldValue, [ptr] ; \
|
||||
SUBS fail, oldValue, expectedValue ; \
|
||||
BNE done ; \
|
||||
STREX##M fail, desiredValue, [ptr] ; \
|
||||
done: \
|
||||
}
|
||||
#elif defined __clang__ || defined __GNUC__
|
||||
#if defined __clang__ || defined __GNUC__
|
||||
#define DO_MBED_LOCKFREE_CAS_WEAK_ASM(M) \
|
||||
__asm volatile ( \
|
||||
".syntax unified\n\t" \
|
||||
|
@ -336,19 +287,7 @@ done: \
|
|||
* (This is the operation for which STREX returning 0 for success
|
||||
* is beneficial.)
|
||||
*/
|
||||
#ifdef __CC_ARM
|
||||
#define DO_MBED_LOCKFREE_CAS_STRONG_ASM(M) \
|
||||
__asm { \
|
||||
retry: ; \
|
||||
LDREX##M oldValue, [ptr] ; \
|
||||
SUBS fail, oldValue, expectedValue ; \
|
||||
BNE done ; \
|
||||
STREX##M fail, desiredValue, [ptr] ; \
|
||||
CMP fail, 0 ; \
|
||||
BNE retry ; \
|
||||
done: \
|
||||
}
|
||||
#elif defined __clang__ || defined __GNUC__
|
||||
#if defined __clang__ || defined __GNUC__
|
||||
#define DO_MBED_LOCKFREE_CAS_STRONG_ASM(M) \
|
||||
__asm volatile ( \
|
||||
".syntax unified\n\t" \
|
||||
|
|
|
@ -101,7 +101,7 @@ do { \
|
|||
#elif defined(__cplusplus) && defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) \
|
||||
&& (__GNUC__*100 + __GNUC_MINOR__) > 403L
|
||||
#define MBED_STATIC_ASSERT(expr, msg) __extension__ static_assert(expr, msg)
|
||||
#elif !defined(__cplusplus) && defined(__GNUC__) && !defined(__CC_ARM) \
|
||||
#elif !defined(__cplusplus) && defined(__GNUC__) \
|
||||
&& (__GNUC__*100 + __GNUC_MINOR__) > 406L
|
||||
#define MBED_STATIC_ASSERT(expr, msg) __extension__ _Static_assert(expr, msg)
|
||||
#elif defined(__ICCARM__)
|
||||
|
|
|
@ -33,7 +33,7 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Timeval definition for non GCC_ARM toolchains */
|
||||
#if !defined(__GNUC__) || defined(__CC_ARM) || defined(__clang__)
|
||||
#if !defined(__GNUC__) || defined(__clang__)
|
||||
struct timeval {
|
||||
time_t tv_sec;
|
||||
int32_t tv_usec;
|
||||
|
|
|
@ -26,7 +26,7 @@ extern "C" {
|
|||
|
||||
#if DEVICE_SEMIHOST
|
||||
|
||||
#if !defined(__CC_ARM) && !defined(__ARMCC_VERSION)
|
||||
#if !defined(__ARMCC_VERSION)
|
||||
|
||||
#if defined(__ICCARM__)
|
||||
static inline int __semihost(int reason, const void *arg)
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
// Warning for unsupported compilers
|
||||
#if !defined(__GNUC__) /* GCC */ \
|
||||
&& !defined(__CC_ARM) /* ARMCC */ \
|
||||
&& !defined(__clang__) /* LLVM/Clang */ \
|
||||
&& !defined(__ICCARM__) /* IAR */
|
||||
#warning "This compiler is not yet supported."
|
||||
|
@ -71,9 +70,9 @@
|
|||
* @endcode
|
||||
*/
|
||||
#ifndef MBED_ALIGN
|
||||
#if __cplusplus >= 201103 && !defined __CC_ARM
|
||||
#if __cplusplus >= 201103
|
||||
#define MBED_ALIGN(N) alignas(N)
|
||||
#elif __STDC_VERSION__ >= 201112 && !defined __CC_ARM
|
||||
#elif __STDC_VERSION__ >= 201112
|
||||
#define MBED_ALIGN(N) _Alignas(N)
|
||||
#elif defined(__ICCARM__)
|
||||
#define MBED_ALIGN(N) _Pragma(MBED_STRINGIFY(data_alignment=N))
|
||||
|
@ -94,7 +93,7 @@
|
|||
* @endcode
|
||||
*/
|
||||
#ifndef MBED_UNUSED
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define MBED_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
#define MBED_UNUSED
|
||||
|
@ -112,7 +111,7 @@
|
|||
* @endcode
|
||||
*/
|
||||
#ifndef MBED_USED
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define MBED_USED __attribute__((used))
|
||||
#elif defined(__ICCARM__)
|
||||
#define MBED_USED __root
|
||||
|
@ -187,9 +186,7 @@
|
|||
* MBED_COMPILER_BARRIER();
|
||||
* }
|
||||
*/
|
||||
#ifdef __CC_ARM
|
||||
#define MBED_COMPILER_BARRIER() __memory_changed()
|
||||
#elif defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
|
||||
#define MBED_COMPILER_BARRIER() asm volatile("" : : : "memory")
|
||||
#else
|
||||
#error "Missing MBED_COMPILER_BARRIER implementation"
|
||||
|
@ -238,7 +235,7 @@
|
|||
* @endcode
|
||||
*/
|
||||
#ifndef MBED_PURE
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define MBED_PURE __attribute__((const))
|
||||
#else
|
||||
#define MBED_PURE
|
||||
|
@ -257,7 +254,7 @@
|
|||
* @endcode
|
||||
*/
|
||||
#ifndef MBED_NOINLINE
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define MBED_NOINLINE __attribute__((noinline))
|
||||
#elif defined(__ICCARM__)
|
||||
#define MBED_NOINLINE _Pragma("inline=never")
|
||||
|
@ -279,7 +276,7 @@
|
|||
* @endcode
|
||||
*/
|
||||
#ifndef MBED_FORCEINLINE
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define MBED_FORCEINLINE inline __attribute__((always_inline))
|
||||
#elif defined(__ICCARM__)
|
||||
#define MBED_FORCEINLINE _Pragma("inline=forced")
|
||||
|
@ -305,7 +302,7 @@
|
|||
#define MBED_NORETURN [[noreturn]]
|
||||
#elif __STDC_VERSION__ >= 201112
|
||||
#define MBED_NORETURN _Noreturn
|
||||
#elif defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM)
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#define MBED_NORETURN __attribute__((noreturn))
|
||||
#elif defined(__ICCARM__)
|
||||
#define MBED_NORETURN __noreturn
|
||||
|
@ -333,7 +330,7 @@
|
|||
* @endcode
|
||||
*/
|
||||
#ifndef MBED_UNREACHABLE
|
||||
#if (defined(__GNUC__) || defined(__clang__)) && !defined(__CC_ARM)
|
||||
#if (defined(__GNUC__) || defined(__clang__))
|
||||
#define MBED_UNREACHABLE __builtin_unreachable()
|
||||
#else
|
||||
#define MBED_UNREACHABLE while (1)
|
||||
|
@ -371,7 +368,7 @@
|
|||
#else
|
||||
#define MBED_FALLTHROUGH
|
||||
#endif
|
||||
#elif defined (__GNUC__) && !defined(__CC_ARM)
|
||||
#elif defined (__GNUC__)
|
||||
#define MBED_FALLTHROUGH __attribute__((fallthrough))
|
||||
#else
|
||||
#define MBED_FALLTHROUGH
|
||||
|
@ -391,9 +388,7 @@
|
|||
* @endcode
|
||||
*/
|
||||
#ifndef MBED_DEPRECATED
|
||||
#if defined(__CC_ARM)
|
||||
#define MBED_DEPRECATED(M) __attribute__((deprecated))
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define MBED_DEPRECATED(M) __attribute__((deprecated(M)))
|
||||
#else
|
||||
#define MBED_DEPRECATED(M)
|
||||
|
@ -430,17 +425,15 @@
|
|||
* @return Address of the calling function
|
||||
*/
|
||||
#ifndef MBED_CALLER_ADDR
|
||||
#if (defined(__GNUC__) || defined(__clang__)) && !defined(__CC_ARM)
|
||||
#if (defined(__GNUC__) || defined(__clang__))
|
||||
#define MBED_CALLER_ADDR() __builtin_extract_return_addr(__builtin_return_address(0))
|
||||
#elif defined(__CC_ARM)
|
||||
#define MBED_CALLER_ADDR() __builtin_return_address(0)
|
||||
#else
|
||||
#define MBED_CALLER_ADDR() (NULL)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MBED_SECTION
|
||||
#if (defined(__GNUC__) || defined(__clang__)) || defined(__CC_ARM)
|
||||
#if (defined(__GNUC__) || defined(__clang__))
|
||||
#define MBED_SECTION(name) __attribute__ ((section (name)))
|
||||
#elif defined(__ICCARM__)
|
||||
#define MBED_SECTION(name) _Pragma(MBED_STRINGIFY(location=name))
|
||||
|
@ -464,7 +457,7 @@
|
|||
#endif
|
||||
|
||||
#ifndef MBED_PRINTF
|
||||
#if defined(__GNUC__) || defined(__CC_ARM)
|
||||
#if defined(__GNUC__)
|
||||
#define MBED_PRINTF(format_idx, first_param_idx) __attribute__ ((__format__(__printf__, format_idx, first_param_idx)))
|
||||
#else
|
||||
#define MBED_PRINTF(format_idx, first_param_idx)
|
||||
|
@ -472,7 +465,7 @@
|
|||
#endif
|
||||
|
||||
#ifndef MBED_PRINTF_METHOD
|
||||
#if defined(__GNUC__) || defined(__CC_ARM)
|
||||
#if defined(__GNUC__)
|
||||
#define MBED_PRINTF_METHOD(format_idx, first_param_idx) __attribute__ ((__format__(__printf__, format_idx+1, first_param_idx == 0 ? 0 : first_param_idx+1)))
|
||||
#else
|
||||
#define MBED_PRINTF_METHOD(format_idx, first_param_idx)
|
||||
|
@ -480,7 +473,7 @@
|
|||
#endif
|
||||
|
||||
#ifndef MBED_SCANF
|
||||
#if defined(__GNUC__) || defined(__CC_ARM)
|
||||
#if defined(__GNUC__)
|
||||
#define MBED_SCANF(format_idx, first_param_idx) __attribute__ ((__format__(__scanf__, format_idx, first_param_idx)))
|
||||
#else
|
||||
#define MBED_SCANF(format_idx, first_param_idx)
|
||||
|
@ -488,7 +481,7 @@
|
|||
#endif
|
||||
|
||||
#ifndef MBED_SCANF_METHOD
|
||||
#if defined(__GNUC__) || defined(__CC_ARM)
|
||||
#if defined(__GNUC__)
|
||||
#define MBED_SCANF_METHOD(format_idx, first_param_idx) __attribute__ ((__format__(__scanf__, format_idx+1, first_param_idx == 0 ? 0 : first_param_idx+1)))
|
||||
#else
|
||||
#define MBED_SCANF_METHOD(format_idx, first_param_idx)
|
||||
|
@ -498,9 +491,7 @@
|
|||
// Macro containing the filename part of the value of __FILE__. Defined as
|
||||
// string literal.
|
||||
#ifndef MBED_FILENAME
|
||||
#if defined(__CC_ARM)
|
||||
#define MBED_FILENAME __MODULE__
|
||||
#elif defined(__GNUC__)
|
||||
#if defined(__GNUC__)
|
||||
#define MBED_FILENAME (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __builtin_strrchr(__FILE__, '\\') ? __builtin_strrchr(__FILE__, '\\') + 1 : __FILE__)
|
||||
#elif defined(__ICCARM__)
|
||||
#define MBED_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
|
||||
|
|
|
@ -146,18 +146,7 @@ static void powerdown_scb(uint32_t vtor)
|
|||
// SCB->CPACR - Implementation defined value
|
||||
}
|
||||
|
||||
#if defined (__CC_ARM)
|
||||
|
||||
__asm static void start_new_application(void *sp, void *pc)
|
||||
{
|
||||
MOVS R2, #0
|
||||
MSR CONTROL, R2 // Switch to main stack
|
||||
MOV SP, R0
|
||||
MSR PRIMASK, R2 // Enable interrupts
|
||||
BX R1
|
||||
}
|
||||
|
||||
#elif defined (__GNUC__) || defined (__ICCARM__)
|
||||
#if defined (__GNUC__) || defined (__ICCARM__)
|
||||
|
||||
void start_new_application(void *sp, void *pc)
|
||||
{
|
||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
/** \ingroup mbed-os-internal */
|
||||
/** \addtogroup platform-internal-api */
|
||||
/** @{*/
|
||||
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
extern uint32_t Image$$RW_m_crash_data$$ZI$$Base[];
|
||||
extern uint32_t Image$$RW_m_crash_data$$ZI$$Size;
|
||||
#define __CRASH_DATA_RAM_START__ Image$$RW_m_crash_data$$ZI$$Base
|
||||
|
|
|
@ -97,7 +97,7 @@ asm(" .global __use_full_stdio\n");
|
|||
|
||||
using namespace mbed;
|
||||
|
||||
#if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
|
||||
#if defined(__MICROLIB)
|
||||
// Before version 5.03, we were using a patched version of microlib with proper names
|
||||
extern const char __stdin_name[] = ":tt";
|
||||
extern const char __stdout_name[] = ":tt";
|
||||
|
@ -560,7 +560,7 @@ std::FILE *fdopen(FileHandle *fh, const char *mode)
|
|||
* */
|
||||
extern "C" FILEHANDLE PREFIX(_open)(const char *name, int openflags)
|
||||
{
|
||||
#if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
|
||||
#if defined(__MICROLIB)
|
||||
// Before version 5.03, we were using a patched version of microlib with proper names
|
||||
// This is the workaround that the microlib author suggested us
|
||||
static int n = 0;
|
||||
|
@ -1635,8 +1635,6 @@ extern "C" WEAK void *__aeabi_read_tp(void)
|
|||
return __section_begin("__iar_tls$$DATA");
|
||||
}
|
||||
#endif
|
||||
#elif defined(__CC_ARM)
|
||||
// Do nothing
|
||||
#elif defined (__GNUC__)
|
||||
struct _reent;
|
||||
// Stub out locks when an rtos is not present
|
||||
|
|
Loading…
Reference in New Issue