Mampac
Mampac

Reputation: 333

How to address a typedefed inner class of a class template that itself is a template?

I have a syntactic question rather,

With the following iterator class inside of a vector class,

#include <memory>
#include <cstddef>
#include <iterator>

namespace ft { template <class T, class Alloc = std::allocator<T> > class vector; }

template <class T, class Alloc>
class   ft::vector
{
    public:
        typedef T                                           value_type;
        typedef typename allocator_type::reference          reference;
        typedef typename allocator_type::pointer            pointer;
        typedef ptrdiff_t                                   difference_type;
        template <class value_type>
        class   ptr_iterator : public std::iterator<std::random_access_iterator_tag, value_type>
        {
            public:
                ptr_iterator();
        };
        typedef ptr_iterator<value_type>                    iterator;
        typedef ptr_iterator<const value_type>              const_iterator;
};

How can I address the constructor of ptr_iterator outside of the declaration?

I tried this way:

template <class T, class Alloc>
ft::vector<T, Alloc>::iterator::iterator() {}

But it yields

Vector.hpp:120:1: error: specializing member 'ft::vector<T, Alloc>::ptr_iterator<T>::iterator' requires 'template<>' syntax
 ft::vector<T, Alloc>::iterator::iterator() {}

I attempted adding <> after both of the iterator words and replacing the second iterator word with ptr_iterator, but it still doesn't compile.

Can I still use the typedef without repeating both templates above the function signature?

Or is there a better design for the iterator declaration that'll allow me to define both iterator and const_iterator?

Upvotes: 2

Views: 127

Answers (1)

sigma
sigma

Reputation: 2963

For the out-of-line definition, you must unfortunately repeat the entire "signature" of all the nested templates, including constraints, if any. Cigien has given the right form:

template <class T, class Alloc>
template <class value_type>
ft::vector<T, Alloc>::ptr_iterator<value_type>::ptr_iterator() 
{}

Since this can be messy and error-prone, you can also define the nested class inline, or alternatively as a non-nested helper class. In libstdc++, the former approach is taken for the iterators of views, but the latter for containers like std::vector, for example:

      typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;
      typedef __gnu_cxx::__normal_iterator<const_pointer, vector>
      const_iterator;

Edit:

Oh dear, I'm not sure if it's even possible to define an operator like that! Since it's a free function, it doesn't need the nested template parameters and I would put it in the ft namespace. It would have to look like this:

namespace ft {
template <class T, class Alloc, class value_type>
bool operator==(
    typename vector<T, Alloc>::template ptr_iterator<value_type> const& lhs, 
    typename vector<T, Alloc>::template ptr_iterator<value_type> const& rhs)
{ return true; }
}

However, I've tried this code on Compiler Explorer and my compiler complains that it cannot deduce the parameter(s) of the vector class.

Upvotes: 1

Related Questions