How to compile a templated class (C++) in Eclipse? - c++

I'm trying to create a linked list class in Eclipse but I can't get it to compile properly.
Here is my .cc file (code snipet)
#include <iostream>
#include "list.h"
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
and here is my list.h file (code snipet)
#ifndef __LIST_H__
#define __LIST_H__
template <typename T>
class List {
public:
bool isEmpty();
private:
struct node {
node *following;
node *previous;
T *contents;
};
node *firstNode;
};
#include "list.cc"
#endif /* __LIST_H__ */
I try "Building All" in eclipse but I get the following error:
make all
Building file: ../list.cc
Invoking: Cross G++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"list.d" -MT"list.d" -o "list.o" "../list.cc"
../list.cc:13: error: redefinition of 'bool List<T>::isEmpty()'
../list.cc:13: error: 'bool List<T>::isEmpty()' previously declared here
make: *** [list.o] Error 1
Help please...thanks. I'll be happy to provide any clarifications needed
EDIT: I was given the .h file so I know that it is correct. I also know that I am supposed to have a .cc file called list.cc (it is included at the end of the .h file)

You need to change the extension of the file with the implementation.
The compiler will process this file for compilation and will process it twice, since you're including it in the header.
Your file looks like this:
#include <iostream>
#include "list.h"
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
which will become
#include <iostream>
#ifndef __DLIST_H__
#define __DLIST_H__
template <typename T>
class List {
public:
bool isEmpty();
private:
struct node {
node *following;
node *previous;
T *contents;
};
node *firstNode;
};
#include "dlist.cc"
#endif /* __DLIST_H__ */
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
which will in turn become
#include <iostream>
#ifndef __DLIST_H__
#define __DLIST_H__
template <typename T>
class List {
public:
bool isEmpty();
private:
struct node {
node *following;
node *previous;
T *contents;
};
node *firstNode;
};
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
#endif /* __DLIST_H__ */
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
So the function isEmpty() is defined twice.
Rename the file to dlist.impl.

Try putting the definition for List<T>::isEmpty() in the same file as the class is declared.

Given the unusual form of the header you've been supplied with, to test it you will need another source file. To start with the new source file (say test.cpp) can just #include "list.h", which will check for any syntax errors but will not yet instantiate your List template.
(Just compile test.cpp, not list.cc, since list.cc is indirectly included by test.cpp)

Related

Undefined reference to a function in a class defined in anther file while using typename

I have been stuck for a while now and am unable to figure out why I am getting this compile error.
Node.hpp
#ifndef H1
#define H1
template <typename T>
class Node{
private:
T data;
public:
T getData();
};
#endif
Node.cpp
#include "Node.hpp"
template<typename T>
T Node<T>::getData(){
return data;
}
main.cpp
#include <bits/stdc++.h>
#include "Node.hpp"
using namespace std;
int main()
{
Node<int> *n = new Node<int>();
cout << n->getData();
}
g++ main.cpp Node.cpp -std=c++17
O/P: main.cpp:(.text+0x24): undefined reference to `Node::getData()'collect2: error: ld returned 1 exit status
PS: I tried the same thing without any template (use a primitive datatype instead), I do not get any error. So this probably has got something to do with the typename. Would be great if someone could tell me what is wrong here.
Node.hpp
#ifndef H1
#define H1
template <typename T>
class Node{
private:
T data;
public:
T getData() { return data; }
};
//or define it here
#endif
Then no need for Node.cpp. You might want to consider returning a const reference if your use-case allows it as T now requires a copy constructor. Although maybe that's what you want, I don't know your use-case.
See Why can template only be defined in header files

getting multiple definition error when compiling source code

I have a simple c++ app:
node.h:
#include<iostream>
using namespace::std;
class Node
{
private:
int data;
Node *next;
public:
Node(int nodeData,Node *nextNode);
};
node.cpp:
#include "node.h"
Node::Node(int nodeData, Node *nextNode) {
data = nodeData;
next = nextNode;
}
linked_list.h
#include "node.h"
class LinkedList
{
private:
Node *head;
Node *tail;
int size;
public:
LinkedList();
int getSize();
};
linked_list.cpp:
#include "linked_list.h"
LinkedList::LinkedList()
{
size = 0;
}
int LinkedList::getSize() {
return size;
}
main.cpp:
#include <iostream>
#include "node.h"
#include "linked_list.h"
using namespace ::std;
int main()
{
cout << "This is main!\n";
return 0;
}
I am on linux, inside the projcet's directory, I open a terminal there and try to compile them by this command:
g++ *.cpp *.h -o app
but I get this error:
In file included from linked_list.h:1:0,
from main.cpp:3:
node.h:1:7: error: redefinition of ‘class Node’
class Node
^~~~
In file included from main.cpp:2:0:
node.h:1:7: note: previous definition of ‘class Node’
class Node
^~~~
I looked at some posts here on stackoverlfow but had no luck in solving my problem. I am new to c++, I know that the compiler thinks I am redefining class Node somewhere, but where is this somewhere so I can remove the definition?
Your linked_list.h includes node.h, so the compiler will see the definition in node.h twice while compiling main.cpp.
To avoid this problem, you should add "include guard" to your header files.
It should be like this:
node.h:
#ifndef NODE_H_GUARD // add this
#define NODE_H_GUARD // add this
#include<iostream>
using namespace::std;
class Node
{
private:
int data;
Node *next;
public:
Node(int nodeData,Node *nextNode);
};
#endif // add this
The macro name to define and check should be different for each headers.
Another way to avoid this problem is to adding #pragma once as the first lines of your headers if your compiler supports this.

How to properly build a template class that inherits from an interface and has a separate implementation file.

Here is the code for the question:
PlainInterface.h
/** PlainInterface.h */
#ifndef _PLAIN_INTERFACE
#define _PLAIN_INTERFACE
#include <vector>
template <class ItemType>
class PlainInterface{
public:
virtual int getSize () const = 0;
};
#endif
Plain.h
/** Plain.h */
#ifndef _PLAIN
#define _PLAIN
#include "PlainInterface.h";
template <class ItemType>
class Plain: public PlainInterface < ItemType > {
private:
std::vector<ItemType> a;
public:
Plain();
~Plain();
int getSize() const;
};
#include "Plain.cpp"
#endif
Plain.cpp
/* Plain.cpp */
#include <iostream>
#include "Plain.h"
//Constructors
template <class ItemType>
Plain<ItemType>::Plain() {
std::cout << "Created\n";
}
template <class ItemType>
Plain<ItemType>::~Plain() {
std::cout << "Destroyed\n";
}
template <class ItemType>
int Plain<ItemType>::getSize() const { return 0; }
So according to this question it said that you can either have all of the implementation in the header file, or put #include "Plain.cpp" at the end of the "Plain.h" file, or put the explicit instantiations at the end of the "Plain.cpp" file. I would like to keep the files seperate and not limit what is allowed into the templates. I tried the second option and it didn't work.
The errors that I am getting are that the constructor/deconstructor/getSize definitions in Plain.cpp are already defined. What am I doing wrong here?
You should remove #include "Plain.h" in your .cpp file, as you are creating a circular include otherwise.
Example:
//a.h
...
#include "b.cpp"
//b.cpp
#include "a.h"
a will include b, b will include a, and so on. This is probably why the second option you mentioned didn't work.
Here another answer that applies to your problem (I think): https://stackoverflow.com/a/3127374/2065501

Template error : undefined reference

I am trying to create a class linkedList using template but when I compile it the IDE gives an error :
undefined reference to `listType::add(int)
I am not understanding why ?
linkedList.h
#ifndef LINKEDLISTS_H_INCLUDED
#define LINKEDLISTS_H_INCLUDED
#include "struct.h"
template <class type1>
class listType
{
public:
void add(type1);
void print();
private:
node<type1> *head;
};
#endif // LINKEDLISTS_H_INCLUDED
LinkedList.cpp
#include "linkedLists.h"
#include "struct.h"
#include <iostream>
using namespace std;
template <class type1>
void listType<type1>::add(type1 temp)
{
node<type1> *t;
t->value=temp;
t->link=head;
head=t;
}
template <class type1>
void listType<type1>::print()
{
node<type1> *p;
p=head;
while(p!=NULL)
{
cout<<p->value<<endl;
p=p->link;
}
}
Struct.h
#ifndef STRUCT_H_INCLUDED
#define STRUCT_H_INCLUDED
template <class type1>
struct node
{
type1 value;
node *link;
};
#endif // STRUCT_H_INCLUDED
main.cpp
#include <iostream>
#include "linkedLists.h"
using namespace std;
int main()
{
listType <int> test;
test.add(5);
}
You can't have the implementation of templated classes and functions in the cpp file.
The code has to be in the header, so the including files can see the implementation, and instantiate the correct version with their template argument type.

C++ failed linkage, undefined reference [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can templates only be implemented in the header file?
Undefined reference to function template when used with string (GCC)
C++ templates, undefined reference
I feel I'm missing something linking a C++ project.
I'm not sure if the problem is in the header sources or includes so I made a minimal code sample to demonstrate it.
Main module
minmain.cpp:
#include <stdio.h>
#include <vector>
#include <string>
#include "nodemin.h"
using namespace std;
int main()
{
// Blist libs are included
Node<int>* ndNew = ndNew->Root(2);
return 0;
}
Header file
nodemin.h:
#ifndef NODETEMP_H_
#define NODETEMP_H_
using namespace std;
template<class T>
class Node
{
protected:
Node* m_ndFather;
vector<Node*> m_vecSons;
T m_Content;
Node(Node* ndFather, T Content);
public:
// Creates a node to serve as a root
static Node<T>* Root(T RootTitle);
};
#endif
node module
nodemin.cpp:
#include <iostream>
#include <string.h>
#include <vector>
#include "nodemin.h"
using namespace std;
template <class T>
Node<T>::Node(Node* ndFather, T Content)
{
this->m_ndFather = ndFather;
this->m_Content = Content;
}
template <class T>
Node<T>* Node<T>::Root(T RootTitle) { return(new Node(0, RootTitle)); }
Compile line:
#g++ -Wall -g mainmin.cpp nodemin.cpp
Output:
/tmp/ccMI0eNd.o: In function `main':
/home/******/projects/.../src/Node/mainmin.cpp:11: undefined reference to`Node<int>::Root(int)'
collect2: error: ld returned 1 exit status
I tried compiling into objects but the linking still failed.
Add template class Node<int>; to nodemin.cpp:
#include <iostream>
#include <string.h>
#include <vector>
#include "nodemin.h"
using namespace std;
template <class T>
Node<T>::Node(Node* ndFather, T Content)
{
this->m_ndFather = ndFather;
this->m_Content = Content;
}
template <class T>
Node<T>* Node<T>::Root(T RootTitle) { return(new Node(0, RootTitle)); }
template class Node<int>;