tags:

views:

203

answers:

2

I compiled the following cords with g++

#include <iostream>
#include <string>
using namespace std;
template<class T>
class Node<const char*>{
private:
  string x_;
  Node* next_;
public:
  Node (const char* k, Node* next):next_(next),x_(k){}
  string data(){return x_;}
  Node *get_next(){return next_;}
};

$ g++ -c node01.cc
node01.cc:5: error: ‘Node’ is not a template

What's wrong? I'm begginer for c++

+6  A: 

You're mixing up declarations and instantiations. When you declare a template, you don't specify a type immediately after its name. Instead, declare it like this:

template<class T>
class Node {
private:
  const T x_;
  Node *next_;
public:
  Node (const T& k, Node *next) : x_(k), next_(next) { }
  const T& data(){return x_;}
  Node *get_next(){return next_;}
};

Your original declaration also confuses string, const char *, and generic types that should be in terms of T. For a template like this, you probably want to let the user define the type of the member (x_). If you explicitly declare it as const char * or string, you're losing genericity by limiting what the user can use for T.

Notice that I changed the types of the instance variables, the parameters of the constructor and the return type of data() to be in terms of T, too.

When you actually instantiate a variable of the template type, you can provide a concrete type parameter, e.g.:

int main(int argc, const char **argv) {
    Node<char*> *tail = new Node<char*>("tail", NULL);
    Node<char*> *node = new Node<char*>("node", tail);
    // do stuff to mynode and mytail
}

Whenever you write the template name Node outside the template declaration, it's not complete until you provide a value for the parameter T. If you just say Node, the compiler won't know what kind of node you wanted.

The above is a little verbose, so you might also simplify it with a typedef when you actually use it:

typedef Node<char*> StringNode;
int main(int argc, const char **argv) {
    StringNode *tail = new StringNode("tail", NULL);
    StringNode *node = new StringNode("node", tail);
    // do stuff to mynode and mytail
}

Now you've built a linked list of two nodes. You can print out all the values in the list with something like this:

for (StringNode *n = node; n; n = n->get_next()) {
    cout << n->data() << endl;
}

If all goes well, this will print out:

node
tail
tgamblin
+2  A: 

Your class declaration should look like this:

template<class T>
class Node{
private:
  T x_;
  Node* next_;
public:
  Node (const T& k, Node* next):next_(next),x_(k){}
  T data(){return x_;}
  Node *get_next(){return next_;}
};

Notice how I removed all references to string or const char * and replaced them with the generic type T. Your class, since it is templated, should not refer to any specific type but should do everything in terms of the generic T type.

The const char * is specified later when you declare a Node variable. Or it could be any other type, not just const char *. The point is, when you're declaring the Node class you just use the generic type T in the code without reference to any specific type. You specify a specific type only when you actually use a Node.

Node<const char *> stringNode("foo", NULL);
Node<int>          intNode(5, NULL);

This has allowed us to have a single definition of the Node class but be able to use it to create both nodes where the data is a string and nodes where the data is an integer. Hooray templating!

John Kugelman