0

Why the code below does not compile with GCC 11.1?

#include <stdexcept>
#include <cassert>
#include <initializer_list>

template <class T, class Allocator = std::allocator<T>>
class ring
{
public:

    using value_type = T;
    using allocator_type = Allocator;
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;
    using reference = T &;
    using const_reference = const T &;
    using pointer = T *;
    using const_pointer = const T *;

private:

    template <class E>
    class ring_iterator
    {
    public:

        using iterator_category = std::random_access_iterator_tag;
        using value_type = E;
        using difference_type = std::ptrdiff_t;
        using reference = E &;
        using pointer = E *;

        ring_iterator() : m_pRing(nullptr), m_pos(0) {}
        
        ring_iterator(const ring_iterator& other) = default;
        ring_iterator(ring_iterator&& other) = default;

        ring_iterator& operator = (const ring_iterator& other) = default;
        ring_iterator& operator = (ring_iterator&& other) = default;

        pointer operator-> () const { return container().address<E>(m_pos); }

        reference operator* () const { return *m_pRing->address<E>(m_pos); }

    private:

        ring_iterator(const ring & r, std::size_t pos) : m_pRing(&r), m_pos(pos)
        {
        }

        const ring& container() const
        {
            return *m_pRing;
        }

        const ring * m_pRing;
        
        //It can't be a pointer because there is no
        //end pointer in a circular buffer, so we use an index.
        std::size_t m_pos;

        friend ring;
    };

private:

    template <class E>
    E * address(std::size_t pos) const
    {
        return nullptr;
    }

    template <class E>
    friend class ring_iterator;
};

using IntRing = ring<int>;

the error is

In member function ‘E* awl::ring<T, Allocator>::ring_iterator<E>::operator->() const’:
error: expected primary-expression before ‘>’ token
    pointer operator-> () const { return container().address<E>(m_pos); }

but it starts to compile if I replace

pointer operator-> () const { return container().address<E>(m_pos); }

with

pointer operator-> () const { const ring& r = container(); return r.address<E>(m_pos); }

what is the difference?

Dmitriano
  • 1,878
  • 13
  • 29

0 Answers0