Bob John
Bob John

Reputation: 3878

Defining templated functions in .cpp from .h (getting error)

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

Answers (5)

juanchopanza
juanchopanza

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.

  1. Remove #include "dlist.h" from dlist.cpp.
  2. (optional) rename 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.
  3. (only if step 2 taken) include the re-named dlist.icpp in dlist.h, as is currently done for dlis.cpp.

Upvotes: 7

wimh
wimh

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

Lightness Races in Orbit
Lightness Races in Orbit

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

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

NPE
NPE

Reputation: 500495

Instead of using #include "dlist.cpp" in your header file, move the function definition into dlist.h.

Upvotes: 1

Related Questions