| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SUPPORT_MIN_SEQUENCE_CONTAINER_H |
| #define SUPPORT_MIN_SEQUENCE_CONTAINER_H |
| |
| #include <initializer_list> |
| #include <vector> |
| |
| #include "test_iterators.h" |
| |
| template <class T, class Iterator = random_access_iterator<T*>, class ConstIterator = random_access_iterator<const T*>> |
| struct MinSequenceContainer { |
| using value_type = T; |
| using difference_type = int; |
| using size_type = unsigned int; |
| using iterator = Iterator; |
| using const_iterator = ConstIterator; |
| |
| explicit MinSequenceContainer() = default; |
| template <class It> |
| explicit MinSequenceContainer(It first, It last) : data_(first, last) {} |
| MinSequenceContainer(std::initializer_list<T> il) : data_(il) {} |
| iterator begin() { return iterator(data_.data()); } |
| const_iterator begin() const { return const_iterator(data_.data()); } |
| const_iterator cbegin() const { return const_iterator(data_.data()); } |
| iterator end() { return begin() + size(); } |
| const_iterator end() const { return begin() + size(); } |
| size_type size() const { return data_.size(); } |
| bool empty() const { return data_.empty(); } |
| |
| void clear() { data_.clear(); } |
| |
| template <class It> |
| iterator insert(const_iterator p, It first, It last) { |
| return from_vector_iterator(data_.insert(to_vector_iterator(p), first, last)); |
| } |
| |
| iterator insert(const_iterator p, T value) { |
| return from_vector_iterator(data_.insert(to_vector_iterator(p), std::move(value))); |
| } |
| |
| iterator erase(const_iterator first, const_iterator last) { |
| return from_vector_iterator(data_.erase(to_vector_iterator(first), to_vector_iterator(last))); |
| } |
| |
| iterator erase(const_iterator iter) { return from_vector_iterator(data_.erase(to_vector_iterator(iter))); } |
| |
| template <class... Args> |
| iterator emplace(const_iterator pos, Args&&... args) { |
| return from_vector_iterator(data_.emplace(to_vector_iterator(pos), std::forward<Args>(args)...)); |
| } |
| |
| private: |
| std::vector<T>::const_iterator to_vector_iterator(const_iterator cit) const { return cit - cbegin() + data_.begin(); } |
| |
| iterator from_vector_iterator(std::vector<T>::iterator it) { return it - data_.begin() + begin(); } |
| |
| std::vector<T> data_; |
| }; |
| |
| namespace MinSequenceContainer_detail { |
| |
| // MinSequenceContainer is non-allocator-aware, because flat_set supports |
| // such (non-STL) container types, and we want to make sure they are supported. |
| template <class T> |
| concept HasAllocatorType = requires { typename T::allocator_type; }; |
| static_assert(!HasAllocatorType<MinSequenceContainer<int>>); |
| |
| // MinSequenceContainer by itself doesn't support .emplace(), because we want |
| // to at least somewhat support (non-STL) container types with nothing but .insert(). |
| template <class T> |
| concept HasEmplace = requires(T& t) { t.emplace(42); }; |
| static_assert(!HasEmplace<MinSequenceContainer<int>>); |
| |
| } // namespace MinSequenceContainer_detail |
| |
| #endif // SUPPORT_MIN_SEQUENCE_CONTAINER_H |