1

I am trying to write a function for a class "LinkedList" which has its own class "Node". The class "LinkedList" is a template class. I am trying to write a function "Foo_do_something" which returns a pointer to "Node". Following is the code:

template <typename T>
class LinkedList{
public:
    class Node {
    public:
        T data;
        Node *next;
        Node *prev;

        Node(): next(nullptr), prev(nullptr) {}
        Node(const T & data): data(data), next(nullptr), prev(nullptr) {}
    };
public:
    Node* Foo_do_something();
};

template <typename T>
Node* LinkedList<T>::Foo_do_something(){
    std::cout<<"Hello";
    Node *ptr = new Node(100);
    return ptr;
}

With this code I get the error:

error: ‘Node’ does not name a type

I understood that this is because "Node" belongs to class "LinkedList" scope. So I need to somehow add that information. I tried the following code but that also throws error.

LinkedList<T>::Node* LinkedList<T>::Foo_do_something(){

I can understand that if I define the function inside the class then the problem can be solved. But I was trying to keep the implementation of the function separate. Is there any way to do that?

Tapojyoti Mandal
  • 742
  • 1
  • 5
  • 14

1 Answers1

4

As mentioned in the comments the correct form is:

typename LinkedList<T>::Node* LinkedList<T>::Foo_do_something() {

Recent compilers will also tell you that you need the typename if you try to compile it without that.

The reason LinkedList<T>:: is necessary is because the return type is parsed before the compiler gets to the LinkedList<T>::Foo_do_something and knows for which class you are defining a member function and thus where to look for Node.

Why typename is necessary is explained in this question. Basically, it tells the compiler that LinkedList<T>::Node is a type and not something else, before the template is instantiated. The compiler needs to know that in order to parse the definition correctly, but before it actually knows what T is, it cannot be sure whether ::Node refers to a type or a variable or a function, etc.

Alternatively you can use the trailing return type syntax, where lookup will already use the class context:

auto LinkedList<T>::Foo_do_something() -> Node* {
walnut
  • 21,629
  • 4
  • 23
  • 59