KeyC0de
KeyC0de

Reputation: 5257

What is the complete interface of a C++ standard compatible library container?

I'm trying to understand the C++ standard library. If I want to build a new kind of container fully compatible with latest C++17 standards (excluding polymorphic allocator support as I'm not that clear on that yet), with full compatibility with iterators, what is the complete set of member functions and types I must provide?

Take a sequence container like std::vector for example. In other words, say I want to provide everything that std::vector provides. Also considering allocator support.

Of course I also want to provide iterators, exactly as std::vector does it (I don't want to delegate to it; I want from the ground up remake), so I suppose I will need two nested iterator classes, one for iterator and one for const_iterator.

I've come up with the following:

template <class T, class Alloc = std::allocator_traits<T>>
class StdLibClass
{
public:
    using allocator_type = Alloc;
    using value_type = typename Alloc::value_type;
    using reference = typename Alloc::reference;
    using const_reference = typename Alloc::const_reference;
    using difference_type = typename Alloc::difference_type;
    using size_type = typename Alloc::size_type;

    class Iterator
    {
    public:
        using difference_type = typename Alloc::difference_type;
        using value_type = typename Alloc::value_type;
        using reference = typename Alloc::reference;
        using pointer = typename Alloc::pointer;
        using iterator_category = std::random_access_iterator_tag;  // or another Iterator tag you want

        Iterator();
        Iterator(const Iterator&);
        ~Iterator();

        Iterator& operator=(const Iterator&);
        bool operator==(const Iterator&) const;
        bool operator!=(const Iterator&) const;
        bool operator<(const Iterator&) const;
        bool operator>(const Iterator&) const;
        bool operator<=(const Iterator&) const;
        bool operator>=(const Iterator&) const;

        Iterator &operator++();
        Iterator operator++(int);
        Iterator &operator--();
        Iterator operator--(int);
        Iterator &operator+=(size_type);
        Iterator operator+(size_type) const;
        friend Iterator operator+(size_type, const Iterator&);
        Iterator &operator-=(size_type);
        Iterator operator-(size_type) const;
        difference_type operator-(Iterator) const;

        reference operator*() const;
        pointer operator->() const;
        reference operator[](size_type) const;
    };

    class ConstIterator
    {
    public:
        using difference_type = typename Alloc::difference_type;
        using value_type = typename Alloc::value_type;
        using reference = typename const Alloc::reference;
        using pointer = typename const Alloc::pointer;
        using iterator_category = std::random_access_iterator_tag;  // or another Iterator tag you want

        ConstIterator();
        ConstIterator(const ConstIterator&);
        ConstIterator(const Iterator&);
        ~ConstIterator();

        ConstIterator& operator=(const ConstIterator&);
        bool operator==(const ConstIterator&) const;
        bool operator!=(const ConstIterator&) const;
        bool operator<(const ConstIterator&) const;
        bool operator>(const ConstIterator&) const;
        bool operator<=(const ConstIterator&) const;
        bool operator>=(const ConstIterator&) const;

        ConstIterator &operator++();
        ConstIterator operator++(int);
        ConstIterator &operator--();
        ConstIterator operator--(int);
        ConstIterator &operator+=(size_type);
        ConstIterator operator+(size_type) const;
        friend ConstIterator operator+(size_type, const ConstIterator&);
        ConstIterator &operator-=(size_type);
        ConstIterator operator-(size_type) const;
        difference_type operator-(ConstIterator) const;

        reference operator*() const;
        pointer operator->() const;
        reference operator[](size_type) const;
    };

    using ReverseIterator = std::reverse_iterator<Iterator>;
    using ConstReverseIterator = std::const_reverse_iterator<ConstIterator>;

    StdLibClass();
    ~StdLibClass();
    StdLibClass(const StdLibClass&);
    StdLibClass& operator=(const StdLibClass&);
    StdLibClass(const StdLibClass&&);
    StdLibClass& operator=(const StdLibClass&&);

    bool operator==(const StdLibClass&) const;
    bool operator!=(const StdLibClass&) const;
    bool operator<(const StdLibClass&) const;
    bool operator>(const StdLibClass&) const;
    bool operator<=(const StdLibClass&) const;
    bool operator>=(const StdLibClass&) const;

    Iterator begin();
    ConstIterator begin() const;
    ConstIterator cbegin() const;
    Iterator end();
    ConstIterator end() const;
    ConstIterator cend() const;
    ReverseIterator rbegin();
    ConstReverseIterator rbegin() const;
    ConstReverseIterator crbegin() const;
    ReverseIterator rend();
    ConstReverseIterator rend() const;
    ConstReverseIterator crend() const;

    reference front();
    const_reference front() const;
    reference back();
    const_reference back() const;

    template <class... TArgs>
    void emplace_front(TArgs &&...);
    template <class... TArgs>
    void emplace_back(TArgs &&...);
    void push_front(const T&);
    void push_front(T&&);
    void push_back(const T&);
    void push_back(T&&);
    void pop_front();
    void pop_back();
    reference operator[](size_type);
    const_reference operator[](size_type) const;
    reference at(size_type);
    const_reference at(size_type) const;

    template <class... TArgs>
    Iterator emplace(ConstIterator, TArgs&&...);
    Iterator insert(ConstIterator, const T&);
    Iterator insert(ConstIterator, T&&);
    Iterator insert(ConstIterator, size_type, T&);
    template <class Iter>
    Iterator insert(ConstIterator, Iter, Iter);
    Iterator insert(ConstIterator, std::initializer_list<T>);
    Iterator erase(ConstIterator);
    Iterator erase(ConstIterator, ConstIterator);
    void clear();
    template <class Iter>
    void assign(Iter, Iter);
    void assign(std::initializer_list<T>);
    void assign(size_type, const T&);

    void swap(StdLibClass &);
    size_type size() const;
    size_type max_size() const;
    bool empty() const;

    Alloc get_allocator() const;
};

// possibly want to specialize std::swap for the class too
namespace std
{

template <>
void swap<T, StdLibClass<T, Alloc>>(StdLibClass<T, Alloc>&, StdLibClass<T, Alloc>&);

} // namespace std

int main()
{

    return 0;
}

Some I've found in webpages around the internet, others I've found by digging the standard library headers. Is there some member or some other concept I'm missing?

Upvotes: 1

Views: 223

Answers (1)

eike
eike

Reputation: 1334

I think, depending on the kind of container you want to implement, the new standard requirements (standard concepts) added in C++20 are a good place to look for the required interface of a standard container.

Example for Container and especially AllocatorAwareContainer

Upvotes: 2

Related Questions