0

I am trying to implement a simple list with iterator for practice, however I have encountered a compile error that I don't fully understand I had not been able to fix it. When I try to make pointer in my Iterator class to a Node I get compilation error as follows:

use of class template requires template argument list

Here is my headre file that produces the compile error:

#ifndef _MY_LIST_H
#define _MY_LIST_H
#include <memory>



template<class T> 
class MyListItr;

template<typename T>
class MyList {
private:
    int _size;
    friend class MyListItr<T>;
public:
    class Node {
    private:
        T value;
    public:
        std::unique_ptr<MyList::Node> next{ nullptr };

        Node() = delete;
        Node(T& value, MyList::Node* next) :value(value), next(next) {};
        T getVal()const { return value; };
        void setVal(T value) { this->value = value; };
        ~Node() {};
    };

    std::unique_ptr<MyList::Node> head;
    MyList(const MyList<T>&) = delete;
    MyList& operator=(const MyList<T>) = delete;
    MyList() :_size(0), head(nullptr) {};
    int size()const { return _size; };
    void push_front(T);
    T pop_front();
    T front()const;
    void remove(T);
    MyListItr<T> begin() {return MyListItr(this->head); };
    MyListItr<T> end();
    typedef MyListItr<T> iterator;
    typedef MyList<T>::Node value_type;
    typedef MyList<T>::Node* pointer;
    typedef MyList<T>::Node difference_type;
    typedef MyList<T>::Node& reference;

};

template<typename T>
class MyListItr {
    MyList::Node* data;

public:
    MyListItr(MyList::Node*data) : data(data) {}

    bool operator!=(MyListItr<T>const&) const;
    MyListItr<T> operator++();
    T operator*();
};


#endif 

I would be gratefull for any help or direction as to where to look for any clues.

cigien
  • 57,834
  • 11
  • 73
  • 112
MarkusSPE
  • 81
  • 1
  • 10

2 Answers2

1

You class MyListItr needs to be

template<typename T>
class MyListItr {
    typename MyList<T>::Node* data;

public:
    MyListItr(typename MyList<T>::Node*data):data(data) {}
    // ...
};

Note that you need to use the typename keyword to tell the compiler that data you are using a type, and not a variable.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • Thanks, it works. I was trying to use `MyList::Node*` but did not realise that `typename` keyword was also needed. – MarkusSPE Apr 06 '20 at 18:51
  • Yeah, the compiler needs help to disambiguate. See [this](https://stackoverflow.com/q/610245/8372853) for a great explanation. – cigien Apr 06 '20 at 18:54
0

You must specify a template parameter in case when it cannot be automatically deduced (automatic template parameter deduction in class templates was introduced in C++17).

You have several lines, where you don't specify template parameters:

MyListItr<T> begin() { return MyListItr(this->head); /* Here you forget semicolon */};
MyList::Node* data;
MyListItr(MyList::Node*data):data(data) {}

You mast rewrite them like following:

MyListItr<T> begin() { return MyListItr<T>(this->head);};
typename MyList<T>::Node* data;
MyListItr(typename MyList<T>::Node*data):data(data) {}

In the first line compiler can't deduce template parameter of MyListItr by return type (I think, you thought, that if you have specified template parameter in return type, compiler can "remember" it), because, for instance, MyListItrs with different template parameter can be convertible to each other...

In other lines compiler knows nothing about MyList, because it is not quite clever to realize, that your list and its iterator should have the same template parameters. It is more about user-defined semantics.

You must write typename in second and third lines, because this type depends on template parameter. Here is some explanation: https://en.cppreference.com/w/cpp/language/dependent_name

Moreover, you'd better rename the argument in the following line, because it can have conflict with template parameter name:

bool operator!=(MyListItr<T> const& T_)const;

Furthermore, you can try to declare iterator inside the class of your list and it'll automatically bind types inside. In this case you can also hide Node from user code and declare it in private section.

Georgy Firsov
  • 286
  • 1
  • 13