class template problem
/file: stack.h #include <iostream> using namespace std; #ifndef STACK_H #define STACK_H struct Node { string x; Node *next; }; typedef Node* Stack; template<class P> class Stack2{ public: void push(Stack* pstack, P); void pop(Stack& stack); P top(Stack& stack); bool is_empty(Stack stack); }; #endif
//file: stack.cpp #include "stack.h" template<class P> void Stack2<P>::push(Stack* pstack, P x){ Node* t; t=new Node; t->x=x; t->next=*pstack; *pstack=t; return; } template<class P> P Stack2<P>::top(Stack& stack){ return stack->x; } template<class P> bool Stack2<P>::is_empty(Stack stack){ stack= NULL; } template<class P> void Stack2<P>::pop(Stack& stack){ Node* p; p=new Node; p=stack->next; stack=p; return; }
//file:main.cpp #include <iostream> #include "stack.h" #include <vector> #include <string> using namespace std; int main(){ size_t i; Stack2<P> Stack2; Stack stack = 0; string arr[]= {"1","2","3","4"}; vector<string> x(arr, arr +4); cout<<"Original string vector \n"; for (i=0; i<x.size(); i++){ cout<<x[i]<<", ";} cout<<endl; for (i=0; i<x.size(); i++){ Stack2<P>.push(&stack,x[i]);} cout<<"After using the stack to hold the string in reverse order we get: \n"\ ; Node* p; p=stack; while (p !=0){ cout<<p->x<<", "; p=p->next; } cout<<endl; cout<<"After we use top() we get: \n"; cout<<Stack2<P>.top(stack)<<endl; cout<<"After we use pop() we get: \n"; Stack2<P>.pop(stack); Node* w; w=stack; while (w !=0){ cout<<w->x<<", "; w=w->next; } cout<<endl; }
errors: main.cpp: In function ‘int main()’: main.cpp:11: error: ‘P’ was not declared in this scope main.cpp:11: error: template argument 1 is invalid main.cpp:11: error: invalid type in declaration before ‘;’ token main.cpp:20: error: expected primary-expression before ‘.’ token main.cpp:31: error: expected primary-expression before ‘.’ token main.cpp:33: error: expected primary-expression before ‘.’ token make: *** [main.o] Error 1
should I declare the template in main? how should i pass that? Im kind of confused
class P replaces the string
i kind of fixed my code but it still doesn't work http://liveworkspace.org/code/c16eec13056615b082936a4d17882d9c
Are the 3 errors on liveworkspace your only errors at this point?
you know i got it working now at http://liveworkspace.org/code/a9c412a7e683439dfa35a9363749369d
but on my computer when i use the terminal and compile it i get Undefined symbols for architecture x86_64: "Stack2<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::push(Node**, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)", referenced from: _main in main.o "Stack2<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::top(Node*&)", referenced from: _main in main.o "Stack2<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::pop(Node*&)", referenced from: _main in main.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status make: *** [run] Error 1
Reads like you're using a 64-bit compiler reading 32-bit symbols.
what should I do then?
Have you tried compiling with g++?
i made a makefile
run: stack.o main.o g++ $(FLAGS) -o run stack.o main.o stack.o: stack.cpp stack.h g++ $(FLAGS) -c stack.cpp main.o: main.cpp stack.h g++ $(FLAGS) -c main.cpp clean: rm -f run *.o
hmm, why not try compiling from the commandline with g++, see if it gives you the same errors.
one sec
yeap same problem
A google search revealed: The solution here is that you need to have the definition of the templated function in the header file, not just the declaration. This is a limitation of C++'s templating system. If you are still getting the same error from the commandline, you might try adding the definition into your header file.
Seems the template is done at compile time rather than linking.
im kind of confused? so how should i give the definition of templated function?
You could create a header file for the template alone and #include it.
thats weird
It is, I cannot find a specific example in my book, however there is one here: http://www.cplusplus.com/forum/general/28838/ Seems this is not an uncommon problem.
but thats what i have in one file is: //file: stack.h #include <iostream> #include <vector> using namespace std; #ifndef STACK_H #define STACK_H struct Node { string x; Node *next; }; typedef Node* Stack; template <class P> class Stack2{ public: // Stack2(P x); void push(Stack* pstack, P x); void pop(Stack& stack); P top(Stack& stack); bool is_empty(Stack stack); private: vector<P> x; }; #endif
so should I still seperate the template from the struct node?
You should be able to create a header file with the full definition of your template in it, or one person suggests putting an implementation of the string method that is creating the error into a file you are including.
Can't you just define the functions you are declaring in your header file?
so I should have 2 headers? 1 for the template and other for the struct node
Arguably that appears to be the quickest solution, I cannot find an explicit example of doing this, nor does my book even address issues with a template.
so where should I include template.h in both stack.cpp and main.cpp ?
As I understand the process, yes.
//file:template.h #include <iostream> using namespace std; #ifndef TEMPLATE_H #define TEMPLATE_H template <class P> class Stack2{ public: // Stack2(P x); void push(Stack* pstack, P x); void pop(Stack& stack); P top(Stack& stack); bool is_empty(Stack stack); private: vector<P> x; }; #endif
template.h:10: error: ‘Stack’ has not been declared template.h:11: error: ‘Stack’ has not been declared template.h:12: error: ‘Stack’ has not been declared template.h:13: error: ‘Stack’ has not been declared template.h:15: error: ISO C++ forbids declaration of ‘vector’ with no type template.h:15: error: expected ‘;’ before ‘<’ token
Well you are including a class Stack that is not defined within the template file.
thats a struct Node
but then I had the same thing previously if i included the struct
Well, a little more research may be required. I have posed the question to a friend of mine that has many years programming experience over me.
Looking at this example though, they include the cpp file in the template.h // mytemplate.h #ifndef MYTEMPLATE_H_INCLUDED #define MYTEMPLATE_H_INCLUDED template <typename T> class MyTemplate { T AFunction(); }; #include "mytemplate.hpp" #endif // MYTEMPLATE_H_INCLUDED // mytemplate.hpp // looks just like a cpp file, but it isn't #include "whatever.h" #include "whateverelseyouneed.h" #include "mytemplate.h" // superfluous, but harmless template <typename T> T MyTemplate<T>::AFunction() { // ... }
thanks a lot for trying to help me, I really appreciate it
My pleasure, it helps me learn too. :)
if I include stack.h in a template.h i get the same error as ld: symbol(s) not found for architecture x86_64. but if I include stack.cpp in a template.h I get some weird long errors
Perhaps you do not need to remove any of your original declarations from the .h file. What do you get if you roll the changes back to the working model from livecode, then simply include that template.h file in your main.cpp. Does it still work on livecode and does it compile from the console?
all the functions acting as a template must be in a header file
Join our real-time social learning platform and learn together with your friends!