2

I keep receiving a redefinition error during compilation, I've been trying to figure it out but I just couldn't solve the issue. ''DoubleNode.h''

#ifndef DOUBLENODE_
#define DOUBLENODE_

template<class ItemType>
class DoubleNode
{
private:
   ItemType item;
   DoubleNode<ItemType>* next; // Pointer to next node
   DoubleNode<ItemType>* previous; // Pointer to previous node

public:
   DoubleNode();        // Default Constructor
   DoubleNode(const ItemType& anItem);          // Parameterized Constructor
   DoubleNode(const ItemType& anItem, DoubleNode<ItemType>* nextNodePtr, DoubleNode<ItemType>* previousNodePtr);
   void setItem(const ItemType& anItem);
   void setNext(DoubleNode<ItemType>* nextNodePtr);
   void setPrevious(DoubleNode<ItemType>* previousNodePtr);
   ItemType getItem() const ;
   DoubleNode<ItemType>* getNext() const ;
   DoubleNode<ItemType>* getPrevious() const ;
}; // end Node

#include "DoubleNode.cpp"
#endif

'' DoubleNode.cpp''

#include "DoubleNode.h"
//#include <cstddef>

template<class ItemType>
DoubleNode<ItemType>::DoubleNode() : next(nullptr), previous(nullptr)
{
} 

template<class ItemType>
DoubleNode<ItemType>::DoubleNode(const ItemType& anItem) : item(anItem), next(nullptr), previous(nullptr)
{
} // end constructor

template<class ItemType>
DoubleNode<ItemType>::DoubleNode(const ItemType& anItem, DoubleNode<ItemType>* nextNodePtr, DoubleNode<ItemType>* previousNodePtr) :item(anItem), next(nextNodePtr), previous(previousNodePtr)
{
} // end constructor

template<class ItemType>
void DoubleNode<ItemType>::setItem(const ItemType& anItem)
{
   item = anItem;
} // end setItem

template<class ItemType>
void DoubleNode<ItemType>::setNext(DoubleNode<ItemType>* nextNodePtr)
{
   next = nextNodePtr;
} // end setNext

// set previous pointer
template<class ItemType>
void DoubleNode<ItemType>::setPrevious(DoubleNode<ItemType>* previousNodePtr)
{
    previous = previousNodePtr;
}

template<class ItemType>
ItemType DoubleNode<ItemType>::getItem() const
{
   return item;
} // end getItem

template<class ItemType>
DoubleNode<ItemType>* DoubleNode<ItemType>::getNext() const
{
   return next;
} // end getNext

template<class ItemType>
DoubleNode<ItemType>* DoubleNode<ItemType>::getPrevious() const
{
   return previous;
} // end getNext

The compiler constantly tells me that I redefined my constructors, I've done a similar project with just a single node before, which looks very similar but I did not receive the same error. Can someone explain to me what I'm missing or what I'm doing wrong? I've tried figuring out what a redefinition compile error means but I still haven't been able to pinpoint to exactly what I'm doing wrong in this project. I'm trying to create a node where it can traverse forward and backward.

  • 4
    Why are you doing "#include "DoubleNode.cpp" in your .h file? – cigien Mar 31 '20 at 18:08
  • When working with templates, you generally should just use single file for them. No need to split them in `.h` and `.cpp`, when the `.h` includes the `.cpp`. It's very odd. – ChrisMM Mar 31 '20 at 18:09
  • 3
    Splitting a template into a header and implementation file isn't that unusual. While the conventional extension is .tpp for template implementation files, there's nothing (technically) wrong with using .cpp. Just make sure you're not _also_ trying to compile DoubleNode.cpp as a separate compilation unit. – Miles Budnek Mar 31 '20 at 18:10
  • @JohnFilleau & @cigien one of the tutors from my class told me to include that in because when I try to compile I would get this error -> C:\Users\PC\Documents\CPP\linked>g++ doublenode.cpp -o test c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../libmingw32.a(main.o):(.text.startup+0xc0): undefined reference to `WinMain@16' collect2.exe: error: ld returned 1 exit status – Dennies Anwar Mar 31 '20 at 18:13
  • @DenniesAnwar You should not be compiling DoubleNode.cpp. It is `#include`d into DoubleNode.h, and is not a standalone compilation unit. – Miles Budnek Mar 31 '20 at 18:19
  • Wow I totally didn't realize this was a template. So much for RTFQ. – JohnFilleau Mar 31 '20 at 18:24
  • @MilesBudnek I'm still pretty new to programming, how would I check to see if the code works when I try to call it with another class – Dennies Anwar Mar 31 '20 at 18:26
  • `#include "DoubleNode.cpp"` - Ehh, *why*? – Jesper Juhl Mar 31 '20 at 18:28
  • Your IDE is probably auto-compiling every `.cpp` file it can find. I think the easiest solution would just be to rename `DoubleNode.cpp` to `DoubleNode.tpp`, which is generally the extension you use for template definitions. Unless you're using a Makefile on the command line? – JohnFilleau Mar 31 '20 at 18:28
  • @DenniesAnwar I'm not sure what you're getting at. To use `DoubleNode`, you just create an instance of a class instantiated from `DoubleNode` in some file where you `#include "DoubleNode.h"` (i.e. `DoubleNode myNode;`) – Miles Budnek Mar 31 '20 at 18:32
  • It's actually not that bad of an idea to put template definitions into a separate file that is directly included from the header itself at the end. For this to work, you should remove `#include "DoubleNode.h"` at the top of the implementation file and make sure to not compile the implementation file as a standalone. Typically you would give this file a `.tpp` extension to distinguish it from both `.hpp` and `.tpp`. See here for more info: https://stackoverflow.com/questions/44774036/ But keep in mind that this is _only_ for templates. – alter_igel Mar 31 '20 at 19:14

1 Answers1

3

Do not compile DoubleNode.cpp as a standalone compilation unit. It is not one.

The full definition of a class or function template must be available at the point of use. That means that both the class template definition and the definition of all of its members must get #included into any compilation unit that uses that template.

That's what the #include "DoubleNode.cpp" at the end of DoubleNode.h accomplishes.


Side note: The conventional file extension for this type of template implementation file is .tpp, not .cpp. I would recommend changing it to DoubleNode.tpp to avoid confusion, both by readers and possibly by IDEs and other dev tools.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
  • Or, just don't put the definitions into a separate file. It's not necessary. – eerorika Mar 31 '20 at 19:16
  • More reading on `.tpp` template implementation files: https://stackoverflow.com/questions/44774036/why-use-a-tpp-file-when-implementing-templated-functions-and-classes-defined-i And yes, it does add complexity but you gain being able to hide details and see a cleaner template interface. – alter_igel Mar 31 '20 at 19:19