Reputation: 3878
Part of the header file dlist.h is defined as:
#ifndef __DLIST_H__
#define __DLIST_H__
#include <iostream>
class emptyList {};
template <typename T>
class Dlist {
public:
bool isEmpty() const;
private:
struct node {
node *next;
node *prev;
T *o;
};
node *first; // The pointer to the first node (NULL if none)
node *last; // The pointer to the last node (NULL if none)
};
#include "dlist.cpp"
#endif
When I create a dlist.cpp file like this:
#include "dlist.h"
template <typename T>
bool Dlist<T>::isEmpty() const
{
return !first and !last;
}
I get the error message at line 4: redefinition of 'bool Dlist::isEmpty() const'
If I remove the #include "dlist.h"
I get the error at line 4: expected initializer before '<' token
Any help here? Is there something I'm doing wrong that's not allowing me to just define my functions from the dlist.h file? Thank you.
Upvotes: 3
Views: 280
Reputation: 227448
You have to put the implementation of the class template's member functions in the header file or in a file included by the header. The compiler needs access to this code in order to instantiate templates for any given type T
.
In your case, the problem seems to be that you are including the header in the .cpp
and vice versa. If you really want to keep declaration and implementation in separate files, I suggest changing the implementation's suffix from .cpp
to something else, e.g. .icpp
. Some build systems might try to compile an object file out of anything with a .cpp
suffix, and this would also result in error.
#include "dlist.h"
from dlist.cpp
.dlist.cpp
to something like dlist.icpp
. Why? Because many build systems automatically compile any file ending in .cpp
into an object file. And many programmers assume that a .cpp
file will be compiled into an object file.dlist.icpp
in dlist.h
, as is currently done for dlis.cpp
.Upvotes: 7
Reputation: 15232
Remove the #include "dlist.h"
and do not compile dlist.cpp itself.
You can also use something like this:
because dlist.h includes dlist.cpp and defines __DLIST_H__
:
#define __DLIST_H__
You can modify the dlist.cpp to
#ifdef __DLIST_H__
template <typename T>
bool Dlist<T>::isEmpty() const
{
return !first and !last;
}
#endif
This way you don't get a compiler error if you try to compile dlist.cpp. But I agee with the other answers it is better not to name this file .cpp.
Upvotes: 0
Reputation: 385204
The header file is defined for me, I'm not allowed to change it in any way
Then you'll need to remove the #include "dlist.h"
directive from the .cpp
(because you're already in dlist.h
, and thus creating a cyclic dependency), thus making everything completely backwards, because the header you were given is fscking stupid!
A .cpp
should never be #included
. Typically, if one must split template-related definitions into their own file, it should have some other extension. I strongly recommend you talk to the person who has emplaced this mandate on you and explain that their header is silly, confusing and non-conventional.
Upvotes: 2
Reputation: 709
Why do you include .cpp file in .h file? In 99% of cases you shouldn't do that.
Just add your code
template <typename T>
bool Dlist<T>::isEmpty() const
{
return !first and !last;
}
Instead of .cpp file include directive.
Upvotes: 1
Reputation: 500495
Instead of using #include "dlist.cpp"
in your header file, move the function definition into dlist.h
.
Upvotes: 1