Template woes

Templates really really confuse me.

I understand what they do, but in terms of implementing them I seem to get an unending parade of syntax errors.

I'm writing a program that evaluates a mathematical expression by converting it to a postfix expression, and I need a template of my node class. I need a character stack to perform the conversion from infix to postfix, and I need an integer stack to evaluate the postfix expression.

What I'm doing is having the stack be made of a linked list. Now, the stack itself doesn't care about the datatype...only the element in the node defines the datatype.

So I'm presuming that I only a need a template for my node class. Except I can't get it compile....or even come remotely close to compiling.

I made sure to get the logic stuff out of the way, so I know my program converts from infix to postfix correctly - I just need to build a template, which should be easy.

Here's my code...can you guys tell me what's wrong with it in terms of syntax for a template?


Thanks a lot in advance. You guys are real life savers.

And let me know if there's anything unclear about my question. It's hard for me to put myself in the shoes of someone who knows nothing about my program...let me know if there is something I didn't explain clearly enough.


Might be worth mentioning that this is all the .h file.... I just copy pasted my old .cpp file underneath the .h file, since I'm making a template.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#ifndef NodeStack_h
#define NodeStack_h

#include <stdio.h>
#include <stdlib.h>
#include <string>

template <typename T>

class NodeStack
{
        public:
                // default constructor
                NodeStack();

                // constructor that takes in elements
                NodeStack(T Element);

                // destructor
                ~NodeStack();
      
               //accessor function to retrieve the data member prev
                NodeStack * getPrev();

                // accessor function to set the data member prev
                void setPrev (NodeStack * prev);

                // accessor function to set the data member element
                void setElement(T Element);

                //accessor function to retrieve the data member Element
                T getElement();

                // display the data in the node
                void display();


        private:
                T Element;
                NodeStack * prev; // prev pointer (since this is a stack)
};
#endif

NodeStack:: NodeStack()
{
        prev = NULL;
        Element = ' ';
}

NodeStack:: NodeStack(T Element)
{
        prev = NULL;
        this -> Element = Element;
}

NodeStack:: ~NodeStack()
{
        prev = NULL;
}

void NodeStack:: setPrev(NodeStack * prev)
{
        this -> prev = prev;
}

NodeStack * NodeStack:: getPrev()
{
        return (prev);
}

T NodeStack:: getElement()
{
        return (Element);
}

void NodeStack:: display()
{
        cout << "Element: " << Element << endl;
}
  
Last edited on
Let's look at the first error:
1
2
3
test.cc:44:1: error: expected a class or namespace
NodeStack:: NodeStack()
^


or, in another compiler
test.cc:44:1: error: invalid use of template-name ‘NodeStack’ without an argument list

This line attempts to declare a out-of-line constructor for a class called "NodeStack", but there is no such class. There is a template, which can produce a NodeStack<int> or a NodeStack<std::string>, etc. If you want to define a default constructor for every possible NodeStack<T>, that's what you would write:

1
2
template<typename T>
NodeStack<T>:: NodeStack()


Note that it goes into the header file, not into a cpp file.
It goes into the header file? My entire file is a header - I have no .cpp file for this.

Are you saying my code should look more like this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#ifndef NodeStack_h
#define NodeStack_h

#include <stdio.h>
#include <stdlib.h>
#include <string>

template <typename T>

class NodeStack
{
        public:
                // default constructor
                NodeStack();

                // constructor that takes in elements
                NodeStack(T Element);

                // destructor
                ~NodeStack();
      
               //accessor function to retrieve the data member prev
                NodeStack * getPrev();

                // accessor function to set the data member prev
                void setPrev (NodeStack * prev);

                // accessor function to set the data member element
                void setElement(T Element);

                //accessor function to retrieve the data member Element
                T getElement();

                // display the data in the node
                void display();


        private:
                T Element;
                NodeStack * prev; // prev pointer (since this is a stack)
};
#endif

NodeStack<T>:: NodeStack()
{
        prev = NULL;
        Element = ' ';
}

NodeStack<T>:: NodeStack(T Element)
{
        prev = NULL;
        this -> Element = Element;
}

NodeStack<T>:: ~NodeStack()
{
        prev = NULL;
}

void NodeStack<T>:: setPrev(NodeStack * prev)
{
        this -> prev = prev;
}

NodeStack * NodeStack<T>:: getPrev()
{
        return (prev);
}

T NodeStack<T>:: getElement()
{
        return (Element);
}

void NodeStack<T>:: display()
{
        cout << "Element: " << Element << endl;
}
Last edited on
It goes into the header file? My entire file is a header - I have no .cpp file for this.

Oh, then you have to extend the header guard to include the code you must have copied from a .cpp file.

Your new code now generates the diagnostic:

1
2
3
test.cc:44:11: error: use of undeclared identifier 'T'
NodeStack<T>:: NodeStack()
          ^

or
1
2
test.cc:44:11: error: ‘T’ was not declared in this scope
test.cc:44:12: error: template argument 1 is invalid


as the compilers are reminding you, T is an unknown name. You missed out the template<typename T> that would declare T as a type template parameter
I missed out the template<typename T>??

That's exactly what's confusing me - I have it in line 8, don't I?
Lines 8 - 41 are a declaration statement:
template<typename T> class NodeStack {.../*T used here*/...};

T here is just a placeholder. It says, that whenever someone makes a NodeStack<whatever>, any time T appears between { and } will be replaced by whatever

After the semicolon, the statement ends, and T is free to be used for something else, you could have written int T = 1; on line 42 for example.

You could begin your constructor as

1
2
template<typename CoolTypeName>
NodeStack<CoolTypeName>:: NodeStack()

and it would mean the same thing
Ok, thanks for helping me!

It should look like this, then?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#ifndef NodeStack_h
#define NodeStack_h

#include <stdio.h>
#include <stdlib.h>
#include <string>

template <typename T>

class NodeStack
{
        public:
                // default constructor
                NodeStack();

                // constructor that takes in elements
                NodeStack(T Element);

                // destructor
                ~NodeStack();
      
               //accessor function to retrieve the data member prev
                NodeStack * getPrev();

                // accessor function to set the data member prev
                void setPrev (NodeStack * prev);

                // accessor function to set the data member element
                void setElement(T Element);

                //accessor function to retrieve the data member Element
                T getElement();

                // display the data in the node
                void display();


        private:
                T Element;
                NodeStack * prev; // prev pointer (since this is a stack)
};
#endif

template<typename T>

NodeStack<T>:: NodeStack()
{
        prev = NULL;
        Element = ' ';
}

NodeStack<T>:: NodeStack(T Element)
{
        prev = NULL;
        this -> Element = Element;
}

NodeStack<T>:: ~NodeStack()
{
        prev = NULL;
}

void NodeStack<T>:: setPrev(NodeStack * prev)
{
        this -> prev = prev;
}

NodeStack * NodeStack<T>:: getPrev()
{
        return (prev);
}

T NodeStack<T>:: getElement()
{
        return (Element);
}

void NodeStack<T>:: display()
{
        cout << "Element: " << Element << endl;
}
Oh my god....I really don't think there is anything in C++ more frustrating than templates.

What the hell am I supposed to do???

I have template <typename T> on line 44....it's right there. The compiler is telling me T is undefined.

How else could I define it??

I think it's just the damn syntax. I have no idea what the syntax is supposed to be, and everything I look at looks completely different and does not even apply to my particular code....this is hell.
Last edited on
When you write

1
2
const int a = 1;
int b = 2;

Do you expect b to be a const int?

Templates are the same way, each function has to begin with the keyword template if it is supposed to be a template.
Topic archived. No new replies allowed.