/* 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_ /* * * - includes toolchain's * - 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 #include #ifdef __CC_ARM #include // size_t namespace std { template struct initializer_list; // [iterator.operations] template ForwardIterator next(ForwardIterator x, typename iterator_traits::difference_type n = 1) { advance(x, n); return x; } template BidirectionalIterator prev(BidirectionalIterator x, typename iterator_traits::difference_type n = 1) { advance(x, -n); return x; } // [reverse.iter.make] template reverse_iterator make_reverse_iterator(Iterator i) { return reverse_iterator(i); } // [move.iterators] template class move_iterator { Iterator current; using R = typename iterator_traits::reference; public: using iterator_type = Iterator; using iterator_category = typename iterator_traits::iterator_category; using value_type = typename iterator_traits::value_type; using difference_type = typename iterator_traits::difference_type; using pointer = Iterator; using reference = conditional_t::value, remove_reference_t &&, R>; // [move.iter.op.const] constexpr move_iterator() : current() { } constexpr explicit move_iterator(Iterator i) : current(i) { } template constexpr move_iterator(const move_iterator &u) : current(u.base()) { } // [move.iter.op=] template move_iterator &operator=(const move_iterator &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(*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 bool operator==(const move_iterator &x, const move_iterator &y) { return x.base() == y.base(); } template bool operator!=(const move_iterator &x, const move_iterator &y) { return !(x == y); } template bool operator<(const move_iterator &x, const move_iterator &y) { return x.base() < y.base(); } template bool operator<=(const move_iterator &x, const move_iterator &y) { return !(y < x); } template bool operator>(const move_iterator &x, const move_iterator &y) { return y < x; } template bool operator>=(const move_iterator &x, const move_iterator &y) { return !(x < y); } // [move.iter.nonmember] template auto operator-(const move_iterator &x, const move_iterator &y) -> decltype(x.base() - y.base()) { return x.base() - y.base(); } template move_iterator operator+(typename move_iterator::difference_type n, const move_iterator &x) { return x + n; } template constexpr move_iterator make_move_iterator(Iterator i) { return move_iterator(i); } // [iterator.range] template constexpr auto begin(C &c) -> decltype(c.begin()) { return c.begin(); } template constexpr auto begin(const C &c) -> decltype(c.begin()) { return c.begin(); } template constexpr auto end(C &c) -> decltype(c.end()) { return c.end(); } template constexpr auto end(const C &c) -> decltype(c.end()) { return c.end(); } template constexpr T *begin(T (&array)[N]) noexcept { return array; } template constexpr T *end(T (&array)[N]) noexcept { return array + N; } template constexpr auto cbegin(const C &c) noexcept(noexcept(std::begin(c))) -> decltype(std::begin(c)) { return std::begin(c); } template constexpr auto cend(const C &c) noexcept(noexcept(std::end(c))) -> decltype(std::end(c)) { return std::end(c); } template constexpr auto rbegin(C &c) -> decltype(c.rbegin()) { return c.rbegin(); } template constexpr auto rbegin(const C &c) -> decltype(c.rbegin()) { return c.rbegin(); } template constexpr auto rend(C &c) -> decltype(c.rend()) { return c.rend(); } template constexpr auto rend(const C &c) -> decltype(c.rend()) { return c.rend(); } template reverse_iterator rbegin(T (&array)[N]) { return reverse_iterator(array + N); } template reverse_iterator rend(T (&array)[N]) { return reverse_iterator(array); } template reverse_iterator rbegin(initializer_list il) { return reverse_iterator(il.end()); } template reverse_iterator rend(initializer_list il) { return reverse_iterator(il.end()); } template constexpr auto crbegin(const C &c) -> decltype(std::rbegin(c)) { return std::rbegin(c); } template 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 constexpr auto size(const C &c) -> decltype(c.size()) { return c.size(); } template constexpr size_t size(const T (&)[N]) noexcept { return N; } template constexpr auto empty(const C &c) -> decltype(c.empty()) { return c.empty(); } template constexpr bool empty(T (&)[N]) noexcept { return false; } template constexpr bool empty(initializer_list il) { return il.size() == 0; } template constexpr auto data(C &c) -> decltype(c.data()) { return c.data(); } template constexpr auto data(const C &c) -> decltype(c.data()) { return c.data(); } template constexpr T *data(T (&array)[N]) noexcept { return array; } template constexpr const E *data(initializer_list il) { return il.begin(); } #endif // C++20 template constexpr auto ssize(const C &c) -> common_type_t> { return static_cast>>(c.size()); } template constexpr ptrdiff_t ssize(const T (&)[N]) noexcept { return N; } } #endif // MSTD_ITERATOR_