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?