I'm trying to implement a RingBuffer in the style of the STL. This means I'm also implementing an iterator for it that has to work as either const or non-const. This is just the iterator part:
#include <iterator>
#include <type_traits>
template <typename T> class RingBuffer {
public:
class Iterator;
// actual RingBuffer implementation here
};
template <typename T, bool is_const=false>
class RingBuffer<T>::Iterator {
public:
typedef std::ptrdiff_t difference_type;
typedef T value_type;
typedef typename std::conditional<is_const, const value_type*, value_type*>::type pointer ;
typedef typename std::conditional<is_const, const value_type&, value_type&>::type reference ;
typedef std::random_access_iterator_tag iterator_category;
// a bunch of functions here
...
};
GCC 4.8.0 gives errors for every line where I try to access an iterator, saying something like
no type named 'type' in 'struct std::conditional<is_const, const int*, int*>'
Substituting int
for the type that RingBuffer<T>
has been instantiated with. I don't get it. is_const
has a default value. Why doesn't this work? And why doesn't GCC subsitute in false
in the error message, like it substituted int
for value_type
?
The solution is probably obvious but all the googling in the world didn't get me anywhere. Templates are still kind of confusing to me.
If you want Iterator
to also be templated by bool is_const
, you have to declare it as such:
template <typename T> class RingBuffer {
public:
template <bool is_const = false>
class Iterator;
// actual RingBuffer implementation here
};
template <typename T>
template <bool is_const>
class RingBuffer<T>::Iterator {
public:
typedef std::ptrdiff_t difference_type;
typedef T value_type;
typedef typename std::conditional<is_const, const value_type*, value_type*>::type pointer ;
typedef typename std::conditional<is_const, const value_type&, value_type&>::type reference ;
typedef std::random_access_iterator_tag iterator_category;
// a bunch of functions here
...
};
Explanation: Iterator
is a member of a class template, but in your original code, Iterator
itself was a non-template class. RingBuffer
had one template parameter, T
; Iterator
was a non-template class; there just wasn't anywhere for is_const
to appear. It will become clearer if we remove the outer class for a moment:
class Foo;
template <bool b = false>
class Foo
{
// something
};
I believe it's obvious the above wouldn't work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With