mbed-os/platform/cxxsupport/mstd_iterator

461 lines
10 KiB
Plaintext

/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MSTD_ITERATOR_
#define MSTD_ITERATOR_
/* <mstd_iterator>
*
* - includes toolchain's <iterator>
* - For ARM C 5, C++11/14 features:
* - std::begin, std::end, etc
* - std::make_reverse_iterator
* - std::move_iterator, std::make_move_iterator
* - For all toolchains, C++17/20 backports:
* - mstd::size
* - mstd::ssize
* - mstd::empty
* - mstd::data
*/
#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;
// omitting deprecated std::iterator
using std::input_iterator_tag;
using std::output_iterator_tag;
using std::forward_iterator_tag;
using std::bidirectional_iterator_tag;
using std::random_access_iterator_tag;
using std::advance;
using std::distance;
using std::next;
using std::prev;
using std::reverse_iterator;
using std::make_reverse_iterator;
using std::back_insert_iterator;
using std::back_inserter;
using std::front_insert_iterator;
using std::front_inserter;
using std::insert_iterator;
using std::inserter;
using std::move_iterator;
using std::make_move_iterator;
using std::istream_iterator;
using std::ostream_iterator;
using std::istreambuf_iterator;
using std::ostreambuf_iterator;
using std::begin;
using std::end;
using std::cbegin;
using std::cend;
using std::rbegin;
using std::rend;
using std::crbegin;
using std::crend;
#if __cpp_lib_nonmember_container_access >= 201411
using std::size;
using std::empty;
using std::data;
#else
// [iterator.container]
template <class C>
constexpr auto size(const C &c) -> decltype(c.size())
{
return c.size();
}
template <class T, size_t N>
constexpr size_t size(const T (&)[N]) noexcept
{
return N;
}
template <class C>
constexpr auto empty(const C &c) -> decltype(c.empty())
{
return c.empty();
}
template <class T, size_t N>
constexpr bool empty(T (&)[N]) noexcept
{
return false;
}
template <class E>
constexpr bool empty(initializer_list<E> il)
{
return il.size() == 0;
}
template <class C>
constexpr auto data(C &c) -> decltype(c.data())
{
return c.data();
}
template <class C>
constexpr auto data(const C &c) -> decltype(c.data())
{
return c.data();
}
template <class T, size_t N>
constexpr T *data(T (&array)[N]) noexcept
{
return array;
}
template <class E>
constexpr const E *data(initializer_list<E> il)
{
return il.begin();
}
#endif
// C++20
template <class C>
constexpr auto ssize(const C &c) -> common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>
{
return static_cast<common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>>(c.size());
}
template <class T, ptrdiff_t N>
constexpr ptrdiff_t ssize(const T (&)[N]) noexcept
{
return N;
}
}
#endif // MSTD_ITERATOR_