CCJ
CCJ

Reputation: 1719

using generic class members in a class

Building on my question here: C++ cannot establish handle reference to 'parent' object -- circular includes or undefined type errors I'd like to create a class (called Node) that has two generic typed members, a generic pointer to a type-to-be-determined parent object and a vector of generic pointers to the elements of a set of type-to-be-determined child objects. Objects which are to exist in a two-way tree structure will inherit from Node and can populate its parent and children members if necessary as that data becomes available. Here is what I have so far to that end for Node.h:

#include <vector>

#ifndef NODE_H_
#define NODE_H_

template<typename T> class parent{};
template<typename T2> class child{};
class Node{

private:
parent<T>* parent_ptr;
vector<child<T2>>* children_ptr;

public:
 //some accessor methods will go here to get and set the parent and children
};
#endif /*NODE_H_*/

obviously this is not the correct way to use templates in C++ as I am getting error C2065 "'T' is an undeclared identifier" and C4430 "missing type specifier - int assumed" errors. I've found some useful documentation on creating template classes and functions here: http://www.cprogramming.com/tutorial/templates.html but neither that tutorial nor any other docs I could find seem to cover using templates to declare generic class members inside a non-template class; I'm fairly sure that this (or something similar) is what I need to do for my use-case, so what is the proper way to declare and use generic member variables in a standard C++ class?

Upvotes: 1

Views: 3412

Answers (3)

Pyrce
Pyrce

Reputation: 8571

You should definitely spend some time understanding how templates work and start with something simple. It took years for me to be able to create complicated template objects without a lot of compiler error debugging and even longer how to design code structures that minimize that complexity.

But here's what I think you intended. You had too much information in your templating and just needed to drop the typenames to Parent and Child (or T and T2 if you want -- though those names are confusing).

#include <vector>

#ifndef NODE_H_
#define NODE_H_

template<typename Parent, typename Child>
class Node{

private:
Parent* parent_ptr;
std::vector<Child*> children_ptr;

public:
 //some accessor methods will go here to get and set the parent and children
};
#endif /*NODE_H_*/

Also as a side note, you may want a parent ownership situation, where parents own their children and free their memory when they are finished (if each child is owned by exactly 1 parent). In which case the vector would become:

vector<Child> children;

Otherwise you'll need to create a nice structure for how to delete the tree. An alternative is to use smart pointers which delete themselves once they are unused (good for abstract structures that are difficult to track). See Boost Smart Pointers or equivalent from later revisions of C++, though they need special care for circular references.

Upvotes: 3

KRyan
KRyan

Reputation: 7608

Your code should be written like this:

template<typename Parent, typename Child>
class Node
{
private:
    Parent* parent_ptr;
    vector<Child>* children_ptr;

public:
    //some accessor methods will go here to get and set the parent and children
};

The way you'd had it, only the (empty) parent class had the T template parameter, and only the (empty) child class had the T2 template parameter.

Also, I don't think you really want a pointer to a vector. It's possible you do, but that's a decidedly odd usage.

But really, I think it would make a lot more sense to simply use inheritance for this:

class Node
{
private:
    Node* parent_ptr; // a pointer to a Node, or any Node-derived object
    vector<Node*>* children_ptr; // a vector of pointers to Nodes or Node-derived objects

public:
    //some accessor methods will go here to get and set the parent and children
};

A vector of pointers is pretty annoying, though. I'd probably wrap my vector in a class that handles the memory allocation internally, or look up some of the C++11 STL smart pointer classes.

Upvotes: 1

pmr
pmr

Reputation: 59811

I don't see what you would need parent and node for besides adding additional information to the data you already contain. This is a typical case in a linked-list where you need to inject a next and prev pointer to maintain the structure.

When you are dealing with pointers already, this seems not necessary:

template<typename Parent, typename Child>
class Node {
  Parent* parent;
  std::vector<Child*> children;
};

To me that is still an awful lot of pointers and there is no object management yet.

Upvotes: 1

Related Questions