/* * Copyright 2020 The Android Open Source Project * * 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. */ #pragma once #include #include #include #include #define FTL_ARRAY_TRAIT(T, U) using U = typename ArrayTraits::U namespace android::ftl { template struct ArrayTraits { using value_type = T; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using pointer = value_type*; using reference = value_type&; using iterator = pointer; using reverse_iterator = std::reverse_iterator; using const_pointer = const value_type*; using const_reference = const value_type&; using const_iterator = const_pointer; using const_reverse_iterator = std::reverse_iterator; template static pointer construct_at(const_iterator it, Args&&... args) { void* const ptr = const_cast(static_cast(it)); if constexpr (std::is_constructible_v) { // TODO: Replace with std::construct_at in C++20. return new (ptr) value_type(std::forward(args)...); } else { // Fall back to list initialization. return new (ptr) value_type{std::forward(args)...}; } } }; // CRTP mixin to define iterator functions in terms of non-const Self::begin and Self::end. template class ArrayIterators { FTL_ARRAY_TRAIT(T, size_type); FTL_ARRAY_TRAIT(T, reference); FTL_ARRAY_TRAIT(T, iterator); FTL_ARRAY_TRAIT(T, reverse_iterator); FTL_ARRAY_TRAIT(T, const_reference); FTL_ARRAY_TRAIT(T, const_iterator); FTL_ARRAY_TRAIT(T, const_reverse_iterator); Self& self() const { return *const_cast(static_cast(this)); } public: const_iterator begin() const { return cbegin(); } const_iterator cbegin() const { return self().begin(); } const_iterator end() const { return cend(); } const_iterator cend() const { return self().end(); } reverse_iterator rbegin() { return std::make_reverse_iterator(self().end()); } const_reverse_iterator rbegin() const { return crbegin(); } const_reverse_iterator crbegin() const { return self().rbegin(); } reverse_iterator rend() { return std::make_reverse_iterator(self().begin()); } const_reverse_iterator rend() const { return crend(); } const_reverse_iterator crend() const { return self().rend(); } iterator last() { return self().end() - 1; } const_iterator last() const { return self().last(); } reference front() { return *self().begin(); } const_reference front() const { return self().front(); } reference back() { return *last(); } const_reference back() const { return self().back(); } reference operator[](size_type i) { return *(self().begin() + i); } const_reference operator[](size_type i) const { return self()[i]; } }; // Mixin to define comparison operators for an array-like template. // TODO: Replace with operator<=> in C++20. template