I am trying to implement a custom std compliant container class with an iterator.
To do so, i started to define the public type definitions to be used by traits for the container class as well as the iterator.
I want to make it c++17 compliant and try to not use c++20 removed features or c++17 deprecated.
This is what i got:
template <typename T, typename Alloc = std::allocator<T>>
class container {
using allocator_type = Alloc;
using value_type = std::allocator_traits<Alloc>::value_type;
using pointer = std::allocator_traits<Alloc>::pointer;
using const_pointer = std::allocator_traits<Alloc>::const_pointer;
using reference = value_type&; // <-- here
using const_reference = const value_type&; // <-- here
using difference_type = std::allocator_traits<Alloc>::difference_type;
using size_type = std::allocator_traits<Alloc>::size_type;
class iterator;
};
template <typename T, typename Alloc = std::allocator<T>>
class container::iterator {
using value_type = std::allocator_traits<Alloc>::value_type;
using pointer = std::allocator_traits<Alloc>::pointer;
using const_pointer = std::allocator_traits<Alloc>::const_pointer;
using reference = value_type&; // <-- here
using const_reference = const value_type&; // <-- here
using difference_type = std::allocator_traits<Alloc>::difference_type;
using size_type = std::allocator_traits<Alloc>::size_type;
};
Do i have to define reference and const_reference types myself like i did in the example or is there another std way of doint it?
Another question would be how to define a const_iterator without duplicating my iterator.
Some say that i should template my iterator with the value type, some just write a new iterator.
If i would template i dont know how i would create the right type traits for it, so my function definitions for the std:
reference operator*() const
and pointer operator->() const
,
because reference
would be const_reference
and const_reference
would be technically const const_reference
.
For example:
template <typename T>
class container {
template <typename ValueType>
class iterator;
using iterator = iterator<T>;
using const_iterator = iterator<const T>;
};
template <typename ValueType>
class container::iterator {
public:
using value_type = ValueType;
using pointer = value_type*;
using const_pointer = const value_type*;
using reference = value_type&;
using const_reference = const value_type&;
reference operator*() const;
pointer operator->() const;
};
Yes. The allocator doesn't know how your container is implemented, so it cannot know how to define those type aliases.
With the magic of templates.
iterator<T>
vsiterator<const T>
.That's not a problem as long as
const_reference
isconst T&
because due to const folding rulesconst const_reference
is simplyconst T&
which is what you would want.