Advertisement

New to templates - Compiler can't find member name

Started by May 20, 2015 04:03 AM
4 comments, last by aregee 9 years, 7 months ago

I am trying to make a circular doubly linked list, and thought it was a good idea to implement it as a template, since I will be using this kind of lists in my project.

The problem is, that while I think to my understanding that I have done everything right, my compiler beg to differ.

The error messages I get are:

- "Unknown type name 'node'"

- "Expected member name or ';' after declaration specifiers"

I get these two messages for each of the offending lines, and everything seems right to me. I am sure there is something I am lacking in understanding or something.

My template class:


#include <stdio.h>

template <typename T>
class Node {

private:
    T *mData;
    
    Node<T> *mPreviousNode;
    Node<T> *mNextNode;
    
    Node<T> *mChildNode;
protected:
    
public:
    Node();
    ~Node();
};

template <typename T>
Node<T>::Node() {
    mData = nullptr;
    mPreviousNode = nullptr;
    mNextNode = nullptr;
    mChildNode = nullptr;
}

template <typename T>
Node<T>::~Node() { }

The header class with the offending lines:


#include <stdio.h>

class Path {
private:
    Node<Point> *mPointListHead; // <<---- THIS LINE,
    Node<Point> *mPointListTail; // <<---- AND THIS LINE
    
protected:

public:
    Path();
    ~Path();
    
    void addPoint(float x, float y, float z);
};

The Implementation for the class:


#include "Node.h"
#include "Point.h"
#include "Path.h"

Path::Path() {
    mPointListHead = nullptr;
    mPointListTail = nullptr;
}

Path::~Path() {
}

void Path::addPoint(float x, float y, float z) {
    printf("Adding point\n");
}

The header file for the Point class just for reference:


#include <stdio.h>

class Point {
private:
    float mX, mY, mZ;
    float mR, mG, mB, mA;
    
protected:
    
public:
    Point();
    Point(float x, float y, float z);
    Point(float x, float y, float z, float r, float g, float b, float a);
    ~Point();
};

The implementation of Point:


#include "Point.h"

Point::Point() : Point(0.0f, 0.0f, 1.0f) { }

Point::Point(float x, float y, float z) : Point(x, y, z, 1.0f, 1.0f, 1.0f, 1.0f) { }

Point::Point(float x, float y, float z, float r, float g, float b, float a) {
    mX = x; mY = y; mZ = z;
    mR = r; mG = g; mB = b; mA = a;
}

Point::~Point() {
    
}

Thanks for any help with this, and yes, I know that classes are private by default.

EDIT: The weird thing is that the "intellisense" (*) kind of thing sometimes seem to colour the keywords like it understand the names, but when I try to compile again, it forgets them again. When the names are in the colours that shows that the IDE knows the class names, I can also start typing and get the correct autocomplete suggestions. Also this goes away if I try to compile. I am using the latest Xcode by the way, but I am pretty sure it is me goofing up, not the IDE/compiler.

(*) I don't know what name Apple has for the "intellisense".

I had a feeling that the order or place I included header files had something to do with this issue. I tried to move the following lines from the implementation file to the header file:


#include "Node.h"
#include "Point.h"

It solved the problem even though everything should really be in scope anyway. That makes for a different question that I tried to research the other day:

I noticed that Xcode likes to put include files in the header file. I thought that they should be put in the implementation file, so I did look it up. It seems that most people agree that they should indeed be in the implementation file, but...

That leaves me two questions:

1. Why does Xcode put the #includes in the header file when they seemingly should be in the implementation file?

2. Can anyone kind, please link me to a good explanation what is 'best practice'?

Advertisement

That leaves me two questions:
1. Why does Xcode put the #includes in the header file when they seemingly should be in the implementation file?
2. Can anyone kind, please link me to a good explanation what is 'best practice'?

Maybe this will help:

A.h:


#include "B.h" // B.h must be included, otherwise everyone who #includes A.h would have to know to #include B.h before it.
class A
{
    B b;  // In order to use A, B must be fully declared, since A's size depends on B's size.
};

A.h:


class B; // We can avoid having to include B.h, and just use a fwd declaration
class A
{
    B *b; // Since b is just a pointer to B*, people can use A's declaration without B being fully declared..
};
If including a header file in an implementation will cause compile errors unless you include several others first, then those other headers should just be included in that header file. However, ideally you should make your headers so that those dependencies are as minimal as necessary.
As for your initial issue, are you sure you didn't include "Path.h" in some other implementation file? (i.e. other than Path.cpp).
In your case, since Path only contains pointers to Node<Point>, you should be able to get away with a fwd declaration.

In your Path class header, add forward declarations to Node and Point:


template<typename T> class Node;
class Point;

Right now, the header file is not self sufficient, meaning if you look at the header file alone without considering any other inclusions, it has no idea what Node and Point are. So your fix to move the #include statements of Node and Point to it works because now the header knows what Node and Point are.

As far as best practices goes, forward declare what you can, #include what you must.

devstropo.blogspot.com - Random stuff about my gamedev hobby

Regarding where to include the files:
Suppose you need to use the path class in multiple files. It would make sense if the header file itself would already include its dependencies so you should include point.h and node.h in the header file path.h
The way you did it before you would always have to include the dependencies (point.h and node.h) before including path.h

Edit: oh right i forgot about 1thing. As you only need pointers to the nodes its actually fine (and should imo be done that way) to just forward declare the type and include its header in the .cpp file

Thanks for your suggestions. I went with forward declaration. I did actually try to forward declare the template class, but it didn't occur to me that I needed to forward declare the Point class too. After I did both of those, everything compiles fine, and now I have lots of nice points showing up on my screen.

Now I will move on to make a scripted math library to move those dots around plus researching how I can make a fast 2D picking algorithm for a massive point cloud. Probably will be much fun to see it all in action.

EDIT: Strewya: Thanks for best practices. I always do forward declare functions, but that I in certain cases need to forward declare classes is a fairly new thing to me.

This topic is closed to new replies.

Advertisement