Using headers with a template class c++ [duplicate] - c++

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 5 years ago.
I am fairly new to c++ and have not had much experience with headers or templates, and I have not had any experience with them combined. So, I have run into problems trying to use the class I have created. My class definitions and headers are as follows:
J.h is the header file for the template class J.
#ifndef J_H
#define J_H
template<class t>
class J {
public:
void speak();
};
#endif
J.cpp has the function definitions for it's header.
#include "J.h"
#include <iostream>
template<class T> void J<T>::speak(){
std::cout << "Hello from j";
}
main.cpp has the main function and tries to use J.
#include "J.h"
int main(){
J<int> j;
j.speak();
}
My problem is that when I compile with g++ J.h J.cpp main.cpp, I get the error undefined reference to J<int>::speak(), but doing g++ J.h J.cpp runs without any error. I am very new to templates, so any help is appreciated. Thank you in advance.

Just put your implementation in the header file instead.
There was once standard that allow putting template implementation in its own source file (template export) but compiler supporting this feature was rare (Comeau was the only one I believe?).
IIRC, template export was even deprecated in C++1x.

Related

Defining a template in .h file, vs declaring in .h file and defining in .cpp file [duplicate]

This question already has answers here:
Storing C++ template function definitions in a .CPP file
(13 answers)
Why can templates only be implemented in the header file?
(17 answers)
Closed 3 years ago.
I have code that looks something like this (compiling using the Arduino IDE).
main sketch file:
#include "myHeader.h"
//setup stuff here, including setting up Serial & SerialBT
loop(){
CheckForMessages(&Serial); //Check USB first
CheckForMessages(&SerialBT); //Then check Bluetooth
}
myHeader.h:
#include "Arduino.h"
//other includes
template <class T> void CheckForMessages(T *port);
//declarations of other stuff
myHeader.cpp:
#include "myHeader.h"
template <class T> void CheckForMessages(T *port){
if(port->available() !=0){
//rest of function...
}
//definitions of other stuff
When I compile, I get the "undefined reference" errors for both calls to CheckForMessages in the main sketch file. This goes away if I move the definition of the template into the .h file.
I have no issues splitting the declaration and definition of functions in this way as far as I can tell, can anyone explain to me why it isn't working for my templates?

Solution to Multiple definition in C++

guys, this is my first question in StackOverflow so forgive me if make any mistake.
I am writing a small project which contains 2 source files and 3 header files.
// some_template_functions.h
#ifndef SOME_TEMPLATE_FUNCTION_H
#define SOME_TEMPLATE_FUNCTION_H
template <typename T>
int getvalue(string line, string key, T & val)
{
// method to get value (all the types except string) from line using key
}
template <>
int getvalue<string>(string line, string key, string &val)
{
// method to get some string from line using key, similar to getvale<int>
// but with slight difference to handle some special characters
}
#endif
//myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include "some_template_functions.h"
class MYCLASS
{
//declarations of constructors, member functions and members
double member_double;
string member_string;
}
#endif
//myclass.cpp
#include "myclass.h"
MYCLASS:MYCLASS()
{
// for each member
// using "getvalue" defined in "SOME_TEMPLATE_FUNCTION.H" to get the values
getvalue(line, key, member_double);
getvalue(line, key, member_string);
}
//main.cpp
#include "myclass.h"
#include "some_template_functions.h"
int main()
{
myclass A;
int some_value;
getvalue(line, key, value);
return 0;
}
I have no problem compiling the main.o and myclass.o but it is just when I was trying to link the two object files I got error message like:
myclass.cpp: multiple definition of int getvalue<std::basic_string><char, std::char_traits<char>, ...> and etc.
/tmp/cc22zEow.o:main.cpp: first defined here
collect2: ld returned 1 exit status
I know the reason probably is because I am including "some_template_function.h" in both myclass.h and main.cpp, each myclass.o and main.o is going to have its own definition of getvalue which is causing the problem. If I change
#include "some_template_functions.h"
to
#ifndef SOME_TEMPLATE_FUNCTIONS_H
#define SOME_TEMPLATE_FUNCTIONS_H
#endif
the constructors of MYCLASS is not goint to work.
I plan to expand the "some_template_functions.h" and its .cpp file in the future so if possible I would like to keep them separated from the other files. And because the way I am declaring function "getvalue" my attempt to move its definition to .cpp file was not working out for me very well.
I've tried to solve this problem for days but since I just start to learn C++ so far I could not get this right. So please, any suggestions will be appreciated! Thanks in advance!
The specialization of getvalue<std::string>(...) isn't a template and, thus, not implicitly inline. If you want to define this function in a header, e.g., because it is close to trivial and should be inlined, you'll need to mark it explicitly as inline. If the function does anything non-trivial it may be worth merely declaring the specialization in the header and defining it in a suitable translation unit.

including (STL) header files in a header [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
reincluding header in implementation
What I am wondering is that it is common practice to not use using namespace xxx in a header file as not to pollute the global namespace.
How does this go for #includes?
If I have foo.h and foo.cpp.:
//Foo.h
#ifndef FOO_H_
#define FOO_H_
#include <string>
class Foo
{
public:
Foo(std::string * a, std::string * b);
virtual ~Foo();
};
#endif /* FOO_H_ */
//Foo.cpp
#include <string>
#include <Foo.h>
Foo::Foo(std::string * a, std::string * b)
{
// TODO Auto-generated constructor stub
}
Foo::~Foo()
{
// TODO Auto-generated destructor stub
}
Would I really need to #include <string> in both files? Would including it only in the .h or .cpp suffice? (I know both will work, but what is advisable?)
edit, a bit more background information regarding my question.
If I would be using certain classes in my header file (either as variables or method arguments) I would forward declare them in the header file and only include the header file itself in the source file. But this will not work for most STL libs because you can't forward declare class-templates?
... because you can't forward declare class-templates?
class templates can be forward declared - like non template classes:
// forward declaration
template <typename T>
class C;
However, as #AlexandreC stated in comments, for std::string it would be quite complicated, because std::string is typedef from template <typename,typename,typename> basic_string;.
I write it would be complicated, if it would be allowed. And it is not allowed, see:
http://www.gotw.ca/gotw/034.htm
https://stackoverflow.com/a/10290176/1463922
According to the C++11 standard, 17.6.4.2.1:
The behavior of a C++ program is undefined if it adds declarations or
definitions to namespace std or to a namespace within namespace std
unless otherwise specified.
So, no choice but include <string> in header file for std::string.
For your main question - I would include in source and header files, unless I was pretty sure it would be always included in header file and never removed...

C++ Templates Declaration Order

I am trying to compile a minimal example which instantiates
a template class. The example compiles fine when a certain order
of declarations is kept, but fails otherwise.
temp.h:
#include <iostream>
template <bool display>
class test {
public:
void sayHi();
};
temp.cpp:
#include "temp.h"
template <bool display>
void test<display>::sayHi () {
if (display) std::cout << "Hi";
}
main.cpp:
#include <iostream>
#include "temp.h"
int main () {
test<true> myobject;
myobject.sayHi();
return 0;
}
This is the standard of how to include classes.
In GCC 4.4.6, this fails with the error
main.cpp:(.text+0x3a): undefined reference to `test::sayHi()'
However, the example compiles when I do a #include "temp.cpp" instead of #include "temp.h" in main.cpp
file, so that the compiler reads the class declaration in temp.h first, then
sees the content of temp.cpp and only afterwards the content of main.cpp.
When I use non-template classes, it works fine to include just .h files
in main.cpp -- what is going wrong here? Note that the temp.cpp is included
in my Makefile, so it definitely should not be forgotten by the compiler.
Thanks for any help.
See the C++ FAQ Lite entry [35.12] Why can't I separate the definition of my templates class from its declaration and put it inside a .cpp file?.
The definition (aka body) of the sayHi() method must be in the temp.h header, or in another included file; the full code is needed when you instantiate test<true>.
With templates, both declaration and definition must be in the same file. You can do this by either putting all your code in one file (and making the function definitions inline or not, it's up to you), or making the declaration and definitions seperate, but including the definitions file at the bottom of the .h file.
So it would be
tmp.h:
#include <iostream>
template <bool display>
class test {
public:
void sayHi();
};
#include "tmp.cpp"
and tmp.cpp and main.cpp remain the same (but you don't give tmp.cpp to the compiler to compile since it's included by tmp.h).
Many people name the files that have template function definitions in them with a .template extension instead of .cpp extension (it lets you know it's not to be compiled, plus it looks less weird than including a .cpp file), but you don't have to.

C++ (gcc): undefined reference to `Stack<int>::Stack(int)' [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why can templates only be implemented in the header file?
I've struggled with this for a while, and I've taken a look to several questions here, but being new to C++ I haven't been able to understand where I am wrong.
Here is the code, I took it from this page and tried to make it work, but so far I haven't been lucky:
stack.h
#ifndef STACK_H
#define STACK_H
template <class T>
class Stack {
public:
Stack(int n);
~Stack() { delete[] s; };
private:
T* s;
int _top;
int _size;
};
#endif // STACK_H
stack.cpp
#include "stack.h"
template <class T>
Stack<T>::Stack(int n) {
_size = n;
_top = -1;
s = new T[_size];
}
main.cpp
#include <iostream>
#include "stack.h"
using namespace std;
int main() {
Stack<int> s(10); // undefined reference to `Stack<int>::Stack(int)'
return 0;
}
When I compile (gcc 4.5.2) I get one error: undefined reference to Stack<int>::Stack(int). I've tried several things but without any real knowledge to support what I do. I will be really thankful if somebody can explain me what's going on.
You can only have a template class definition in a cpp file if it's a specialized definition - i.e. you know what T is.
Other than that, and your case belongs here, all definitions of your template class have to go in the header file. The compiler has to know about these each time a new instance is declared or defined because the type, and thus the behavior, changes. Definitions in a cpp file would mean a different translation unit, so the compiler couldn't possibly know about the behavior for every single T you try to apply to your template.
There is nothing to compile in "stack.cpp". Templates are only compiled when they are instantiated. Hence the linker cannot find this function which was never compiled.
You can't really separate declarations and implementations in header and source files with templates.
What you can do is copy-n-paste "stack.cpp" to the end of "stack.h". Alternatively include "stack.cpp" at the end of "stack.h", not the other way round, which achieves the same effect. In the latter case it might be wise to change the extension of the "cpp" file (see Including .cpp at end of template header file)
The compiler has to have all of the pertinent information when creating template classes and consequently templates are generally fully implemented in their header files.
There are several ways you could accomplish this, inline functions, defining the template functions in the header file, including your implementation in a separate file (at the end of your header file, with #include), etc.
Here's a similar question with more details.