Why is this happening???

Well, I hav made a Stack code for using it in a program of mine.
But after i separated the header files from the src file of the original Stack.hpp, i got strange problems like: undefined reference to Stack<int>:: Push(int&).

This got solved after i included Stack.cpp in my main.cpp.Which i dont want.

Heres my main.cpp: http://paste.debian.net/418311/
Stack.hpp: http://paste.debian.net/418312/
Stack.cpp: http://paste.debian.net/418313/

I want to include only Stack.hpp in the main.cpp,but thts when it gives me those errors.Also,Stack.cpp and Stack.hpp are in a folder called "include" in the root directory of the project. I also tried putting the Iinclude directive in the g++ compiler but it doesnt help.

Thnx in advance!!
If you are using an IDE, make sure all files has been added to the same project, and I don't think Stack.cpp should be located in the include directory.
Now,as you suggested,I hav put the Stack.cpp file in the root directory of the project.But when i change the #include statement from ".../Stack.cpp" to ".../Stack.hpp" it gives me the following errors:-
1
2
3
4
5
6
7
8
9
10

||=== Build: Debug in Stack (compiler: GNU GCC Compiler) ===|
obj/Debug/main.o||In function `main':|
/home/tina/C++_Workspace/Ma_Projects/My_Helper_Headers/Stack/main.cpp|36|undefined reference to `Stack<int>::push(int&)'|
/home/tina/C++_Workspace/Ma_Projects/My_Helper_Headers/Stack/main.cpp|41|undefined reference to `Stack<int>::size()'|
/home/tina/C++_Workspace/Ma_Projects/My_Helper_Headers/Stack/main.cpp|45|undefined reference to `Stack<int>::pop()'|
/home/tina/C++_Workspace/Ma_Projects/My_Helper_Headers/Stack/main.cpp|49|undefined reference to `Stack<int>::size()'|
/home/tina/C++_Workspace/Ma_Projects/My_Helper_Headers/Stack/main.cpp|50|undefined reference to `Stack<int>::~Stack()'|
||=== Build failed: 5 error(s), 0 warning(s) (0 minute(s), 40 second(s)) ===|


Pls help.
This is the g++ command: g++ -std=c++11 -Wall -o Stack main.cpp
The "undefined reference" is a linker error. Compilation has multiple steps.

First, compiler creates an object file from translation unit.
https://en.wikipedia.org/wiki/Translation_unit_%28programming%29
The unit is basically the .cpp file, but with all includes inserted (preprocessor assembles the unit according to directives for the compiler).

An object file must be created for each necessary translation unit. Your main.cpp and Stack.cpp are two separate units.
Libraries are essentially archives of object files that somebody else has already compiled and packaged.

The linker creates executable binary file by combining the object files that you give to it. If one object refers to code that it does not have (e.g main.o has a call for Stack::Push) then an object file or library containing the code of Stack::Push must also be in linker's command line arguments.


You, however, have a twist: Stack<int>::Push
Template.
When your main has a call to Push() of Stack<int>, the compiler first attempts to create source code for Stack<int>::Push from the templates available in the main.cpp's translation unit. It must see the templates. Object code is created according to the generated source.

Nothing in the Stack.cpp's translation unit is likely to instantiate the Stack<int> and thus the corresponding object file will lack that implementation. (There are ways to force stuff, particularly for libraries, but that is tricky.)


C++ has one definition rule (ODR). When you link, only one object file may contain code for any one entity. (Otherwise you get "multiple definitions" linker error.) The template-based code gets around ODR; the linker knows to discard all but one copy.

C++ standard had "extern template implementation" syntax, but since no compiler developer managed to make a decent implementation, it was removed.


Summary: template code cannot be in separate .cpp. It has to be included.


How to organize code into files then? That is a matter of style.
(Or not. MS Visual C++ used to accept member function implementations only within the template class definition.)
For example: put definition of class into Stack.hpp and include the file containing the class member implementations into the Stack.hpp after the definition. Then a user (main.cpp) sees all of Stack by including Stack.hpp

Naming the files and filename extensions.
There are no hard rules, but a (human) reader can guess more easily if you are systematic.
Build systems (including IDE's) can automate if you do use extensions that they are made to expect.
Well, i had the implementation and the header in the same file.
I hav tried putting the header and implementation in separate files for other projects,but didnt kno tht for templates its not implemented.
So, I hav o put the header and implementation in one file???Thnx.
You can do:
Foo.h
1
2
3
4
5
6
7
8
9
#ifndef foo_h
#define foo_h
template <typename T>
class Foo {
  void bar(T x);
};

#include <FooImp.h>
#endif 


FooImp.h
1
2
3
4
template <typename T>
void Foo<T>::bar(T x) {
  // code
}

The FooImp.h does not need include guards if only Foo.h includes it and there is only templates in it.
Hi,
Edit: Didn't see the previous 2 posts, while writing mine.

Some things:

Usually template code must go into a header file. So how you had it to start with :+) all in one hpp file. But here gives a detailed explanation:

https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl

Don't ever include a cpp file, well unless you are doing what's in the link above :+|

Always compile with a high level of warnings, at a minimum:

g++ -std=c++14 -Wall -Wextra -pedantic-errors *.cpp -o Stack

Here are a whole lot more handy ones that are still not turned on:

http://www.cplusplus.com/forum/general/183731/#msg899203

Try to get hold of clang++ , it's better IMO. http://llvm.org/

The command line options are almost the same, clang has a few extra ones :+), so you shouldn't have any trouble using it.

Hope all goes well :+)

Last edited on
Thnx IdeasMan for those links. :-)
Topic archived. No new replies allowed.