Hi all,
I'm new in C++ and I encounter a problem with a code I found on this forum.

I simply try to add an integer to a Generic Doubly-Linked list. However, when I launch the following code (main function)

DoubleLinked<int> dlist; 
dlist.push_back(1);

I got the following error :

"DoubleLinked<int>::push_back(int)", referenced from:
    _main in main.o
    ld: symbol(s) not found
    collect2: ld returned 1 exit status

Here is the code I used for the Generic Double-Linked list :

double_linked.h

#ifndef LINKED_LIST_H
#define LINKED_LIST_H

#include <iostream>

template <typename T> 
class DoubleLinked
{
	struct Node
	{
		T data;
		Node* prev;
		Node* next;
		Node(T t, Node* p, Node* n) : data(t), prev(p), next(n) {}
	};
	Node* head;
	Node* tail;
	
public:
	DoubleLinked() : head( NULL ), tail ( NULL ) {}
	bool empty() const { return ( !head || !tail ); }
	operator bool() const { return !empty(); }
	void push_back(T);
	void push_front(T);
	T pop_back();
	T pop_front();
	
	~DoubleLinked()
	{
		while(head)
		{
			Node* temp(head);
			head=head->next;
			delete temp;
		}
	}
};

#endif

double_linked.cpp

#include "double_linked.h"

template <typename T>
void DoubleLinked<T>::push_back(T data)
{
	tail = new Node(data, tail, NULL);
	if( tail->prev )
		tail->prev->next = tail;
	
	if( empty() )
		head = tail;
}

template <typename T>
void DoubleLinked<T>::push_front(T data)
{
	head = new Node(data, NULL, head);
	if( head->next )
		head->next->prev = head;
	
	if( empty() )
		tail = head;
}

template<typename T>
T DoubleLinked<T>::pop_back()
{
	if( empty() )
		throw("DoubleLinked : list empty");
	Node* temp(tail);
	T data( tail->data );
	tail = tail->prev ;
	
	if( tail )
		tail->next = NULL;
	else
		head = NULL ;
	
	delete temp;
	return data;
}

template<typename T>
T DoubleLinked<T>::pop_front()
{
	if( empty() )
		throw("DoubleLinked : list empty");
	Node* temp(head);
	T data( head->data );
	head = head->next ;
	
	if( head )
		head->prev = NULL;
	else
		tail = NULL;
	
	delete temp;
	return data;
}

Could someone help me?
Thanks in advance

The error is coming from your linker. This suggests that double_linked.cpp isn't being linked to main.cpp. How are you compiling this, and what does your main.cpp look like?

The error is coming from your linker. This suggests that double_linked.cpp isn't being linked to main.cpp. How are you compiling this, and what does your main.cpp look like?

My main.cpp is

#include <iostream>
#include "double_linked.h"
int main (int argc, char * const argv[]) 
{
DoubleLinked<int> dlist;
dlist.push_back(1);
return 0;
}

And how are you linking double_linked.cpp with main.cpp?

I develop with Xcode. I selected C++ console project. I don't use any special command to build my project.

I first thought the problem was linked with Xcode so I used this makefile:

CC = g++
CFLAGS = -Wall
EXEC_NAME = my_program
INCLUDES =
LIBS =
OBJ_FILES = double_linked.o main.o

all : $(EXEC_NAME)

clean :
	rm $(EXEC_NAME) $(OBJ_FILES)

$(EXEC_NAME) : $(OBJ_FILES)
	$(CC) -o $(EXEC_NAME) $(OBJ_FILES) $(LIBS)

%.o: %.cpp
	$(CC) $(CFLAGS) $(INCLUDES) -o $@ -c $<

%.o: %.cc
	$(CC) $(CFLAGS) $(INCLUDES) -o $@ -c $<

%.o: %.c
	gcc $(CFLAGS) $(INCLUDES) -o $@ -c $<

After running the program I obtained :

g++ -Wall  -o double_linked.o -c double_linked.cpp
g++ -Wall  -o main.o -c main.cpp
g++ -o my_program double_linked.o main.o 
Undefined symbols:
  "_main", referenced from:
      start in crt1.10.6.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

I develop with Xcode. I selected C++ console project. I don't use any special command to build my project.

I first thought the problem was linked with Xcode so I used this makefile:

CC = g++
CFLAGS = -Wall
EXEC_NAME = my_program
INCLUDES =
LIBS =
OBJ_FILES = double_linked.o main.o

all : $(EXEC_NAME)

clean :
	rm $(EXEC_NAME) $(OBJ_FILES)

$(EXEC_NAME) : $(OBJ_FILES)
	$(CC) -o $(EXEC_NAME) $(OBJ_FILES) $(LIBS)

%.o: %.cpp
	$(CC) $(CFLAGS) $(INCLUDES) -o $@ -c $<

%.o: %.cc
	$(CC) $(CFLAGS) $(INCLUDES) -o $@ -c $<

%.o: %.c
	gcc $(CFLAGS) $(INCLUDES) -o $@ -c $<

After running the program I obtained :

g++ -Wall  -o double_linked.o -c double_linked.cpp
g++ -Wall  -o main.o -c main.cpp
g++ -o my_program double_linked.o main.o 
Undefined symbols:
  "_main", referenced from:
      start in crt1.10.6.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

Sorry, I obtained the same error that Xcode prints :

g++ -Wall  -o main1.o -c main1.cpp
main1.cpp:43:2: warning: "/*" within comment
g++ -o my_program double_linked.o main1.o 
Undefined symbols:
  "DoubleLinked<int>::push_back(int)", referenced from:
      _main in main1.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
make: *** [my_program] Error 1

I'm surprised Narue didn't catch this, I guess goddesses are not infallible...

The error is due to the fact that you are trying to separate the function definitions from the function declarations of a class template. Templates are special in C++, they are not real compilable code, they are instructions to the compiler on how to generate code for a given template argument. So, if you try to compile the function definitions separately, the compiler has no template argument to substitute and produces no compiled code for those functions. It has to be that way because the compiler cannot foretell what types you will give as argument to the template in the future.

Anyways, long story short, you cannot separate the function definitions from the function declarations for class or function templates, and thus, you need to put the function definitions in the header file in which they are declared (either inlined or just below). So, the code you have in double_linked.cpp should be put at the end of the double_linked.h file (not completely at the end, of course, within the header guards).

I'm surprised Narue didn't catch this, I guess goddesses are not infallible...

The error is due to the fact that you are trying to separate the function definitions from the function declarations of a class template. Templates are special in C++, they are not real compilable code, they are instructions to the compiler on how to generate code for a given template argument. So, if you try to compile the function definitions separately, the compiler has no template argument to substitute and produces no compiled code for those functions. It has to be that way because the compiler cannot foretell what types you will give as argument to the template in the future.

Anyways, long story short, you cannot separate the function definitions from the function declarations for class or function templates, and thus, you need to put the function definitions in the header file in which they are declared (either inlined or just below). So, the code you have in double_linked.cpp should be put at the end of the double_linked.h file (not completely at the end, of course, within the header guards).

Thank you so much! This a thing I will NEVER forget !
Thanks again

This article has been dead for over six months. Start a new discussion instead.