Undefined reference to ClassName::ClassName - c++

I'm using Code::Blocks to build my project, which contains three files: main.cpp, TimeSeries.cpp, TimeSeries.h. TimeSeries.h provides declarations for the TimeSeries class as follows:
template<class XType, class YType> class TimeSeries {
public:
TimeSeries(void);
~TimeSeries(void);
};
Then TimeSeries.cpp contains:
#include "TimeSeries.h"
template<class XType, class YType>
TimeSeries<XType, YType>::TimeSeries(void) {
}
template<class XType, class YType>
TimeSeries<XType, YType>::~TimeSeries(void) {
}
And finally, main.cpp contains
#include "TimeSeries.h"
typedef TimeSeries<float, float> FTimeSeries;
int main(int argc, char** argv) {
FTimeSeries input_data;
return 0;
}
When building with C::B, I get the following error:
undefined reference to `TimeSeries<float, float>::TimeSeries()'
What can I do?
Thanks,
CFP.

Basically all templated code should be defined in a header, otherwise it will not be built since nothing uses it in the compiled unit.
Each cpp file is compiled as a separate unit, and thus constructor and destructor are not compiled. The compiler has no way of knowing what type of template argument you will use in main.cpp when it compiles TimeSeries.cpp.

The reason for splitting code into header- and source-files is so that the declaration and the implementation are separated. The compiler can translate the source-file (compilation unit) into an object file, and other compilation-units that want to use the classes and functions just include the header-file, and link the object file. This way, the code has to be compiled only once, and can be reused by linking it.
The problem with templates is that, as long as there are no parameters provided for them, the compiler cannot compile them. The same template instantiated with different parameters results in different types. std::vector<int> and std::vector<float> are, from the compilers perspective, not related in any way. Because of this, template-classes usually have to reside completely in a header-file, because, when the template is used, the compiler needs the complete definition in order to generate the class depending on the parameters.
As #Gabriel Schreiber pointed out in his answer, you can tell the compiler that he should compile the template with a specific set of parameters, making that available to other compilation units just by linking. However, this does not make the template available for other parameter sets.

You need to add this in your .cpp-file (below the definitions):
template class TimeSeries<float, float>;
When the compiler compiles TimeSeries.cpp it doesn't know which for which types the template is need because it is used in another source file. You need to tell the compiler explicitly.
Read about Explicit Template Instantiation in your copy of the Stroustrup or on the internet.

Related

How to find duplicate definitions from template specializations?

I have a template class with a specialization, defined in another file. Therefore it is possible to generate two versions of the same class: one time by replacing the template parameter and one time using the specialization. My current understanding is, that this can lead to two instanciations of the same type to have different sizes in memory, resulting in segmentation faults.
I created a minimal example and the following code is to illustrate the question:
Create a template class:
// - templateexample.h ---------------
#ifndef TEMPLATEEXAMPLE_H
#define TEMPLATEEXAMPLE_H
template<typename T> class Example
{
public:
Example(){}
int doWork() {return 42;}
};
#endif
// -----------------------------------
Template specialization in another file:
// - templatespecialization.h --------
#ifndef TEMPLATESPECIALIZATION_H
#define TEMPLATESPECIALIZATION_H
#include "templateexample.h"
template<> class Example<int>
{
public:
Example() : a(0), b(1), c(2), d(3) {}
int doWork() {return a+b+c+d;}
private:
int a; //<== the specialized object will be larger in memory
int b;
int c;
int d;
};
#endif
// --------------------------------
Have a class which includes only the template class definition, but should include the specialization.
// - a.h --------------------------
#ifndef A_H
#define A_H
#include "templateexample.h"
class A
{
public:
Example<int> returnSmallExample();
};
#endif
// - a.cpp ------------------------
#include "a.h"
Example<int> A::returnSmallExample() {return Example<int>();}
// --------------------------------
The main class now knows two versions of Example<int> the one from A and the one from the templatespecialization.h.
// - main.cpp ---------------------
#include <iostream>
#include "a.h"
#include "templatespecialization.h"
int main()
{
A a;
Example<int> test = a.returnSmallExample();
std::cout<<test.doWork()<<std::endl;
}
// --------------------------------
Please note, this problem will only occur when compiling class A separately, this example from ideone outputs 6, whereas using separate files can result in a segmentation fauls, or output 42 (https://ideone.com/3RTzlC). On my machine the example compiles successfully and outputs 2013265920:
In the production version of the above example everything is build into a shared library which is used by main.
Question 1: Why doesn't the linker detect this problem? This should be easy to spot by comparing the size of objects.
Question 2: is there a way to examine the object files or the shared library to detect multiple implementations of the same type like in the example above?
Edit: please note: the code above is a minimal example to explain the problem. The reason for the situation is that the template class is from one library and I cannot edit the files from this library. Finally the whole thing is used all over the place in the executable and now I need to find out if the problem above occurs.
Edit: code above can be compiled like this:
#!/bin/bash
g++ -g -c a.cpp
g++ -g -c main.cpp
g++ -o test a.o main.o
You have different definition of the same template and its specializations in different translation units. This leads to One Definition Rule violation.
A fix would be to put the specialization in the same header file where the primary class template is defined.
Question 1: Why doesn't the linker detect this problem? This should be easy to spot by comparing the size of objects.
Different types may have the same size (e.g. double and int64_t), so, obviously, just comparing sizes of objects does not work.
Question 2: is there a way to examine the object files or the shared library to detect multiple implementations of the same type like in the example above?
You should use gold linker for linking your C++ applications, if you do not use it already. One nice feature of it is --detect-odr-violations command line switch which does exactly what you ask:
gold uses a heuristic to find potential ODR violations: if the same symbol is seen defined in two different input files, and the two symbols have different sizes, then gold looks at the debugging information in the input objects. If the debugging information suggests that the symbols were defined in different source files, gold reports a potential ODR violation. This approach has both false negatives and false positives. However, it is reasonably reliable at detecting problems when linking unoptimized code. It is much easier to find these problems at link time than to debug cases where the wrong symbol.
See Enforcing One Definition Rule for more details.
Question 1: Why doesn't the linker detect this problem? This should be easy to spot by comparing the size of objects.
Because this is not a linker's problem. In case of templates, the main declaration and all the other specializations (be it class or function) should be visible upfront.
Question 2: is there a way to examine the object files or the shared library to detect multiple implementations of the same type
like in the example above?
At least I am not aware of any.
To further simplify this situation, look at a similar broken code:
// foo.h
inline void foo () {
#ifdef FOO
return;
#else
throw 0;
#endif
}
// foo1.cpp
#define FOO
#include"foo.h"
// ... uses foo() with "return"
// foo2.cpp
#include"foo.h"
// ... uses foo() with "throw"
It's possible that you get different results based on the way of compilation being used.
Update:
Having multiple body definitions for a same function is undefined behavior. That's the reason why you are getting an awkward output like 2013265920 and the same happens in my machine as well. The output should be either 42 or 6. I gave you above example because with inline functions you can create such race conditions.
With my limited knowledge on linking stage, the responsibility undertaken by a typical linker is limited only till rejecting more than 1 non-inline functions definitions with the same signature. e.g.
// Header.h is included in multiple .cpp files
void foo () {} // rejected due to multiple definitions
inline void bar () {} // ok because `inline` keyword is found
Beyond that it doesn't check if the function body is similar or not, because that is already parsed during earlier stage and linker doesn't parse the function body.
Having said above, now pay attention to this statement:
template functions are always inline by nature
Hence linker may not get a chance to reject them.
The safest way is to #include the read-only header into your specialized header and include that specialized header everywhere.
I don't know of a way to do this by analysis of the compiled binary, but you could build a graph of your program's #include relationships — there are tools that can do this, such as Doxygen — and use it to look for files that (directly or indirectly) include the library header but not the specialization header.
You'd need to examine each file to determine whether it actually uses the template in question, but at least you can narrow down the set of files that you have to examine.
I think you managed to deceive the compiler. But I should note that in my humble opinion you understand conception of templates in a wrong way, particularly you are trying to mix up template specialization with inheritance.
I mean, template specialization must not add data members to class, the only aims are to define types for function parameters and class fields. If you want to change algorithms, i.e. rewrite code, or add new date members to class, you should define derived class.
Concerning "several-step" separate compilation and template class in library, C++ reference said (http://www.cplusplus.com/doc/oldtutorial/templates/):
Because templates are compiled when required, this forces a restriction for multi-file projects: the implementation (definition) of a template class or function must be in the same file as its declaration. That means that we cannot separate the interface in a separate header file, and that we must include both interface and implementation in any file that uses the templates.
Since no code is generated until a template is instantiated when required, compilers are prepared to allow the inclusion more than once of the same template file with both declarations and definitions in a project without generating linkage errors.

How come you can split non template classes in a .h interface and .cpp implementation?

I understand that if you attempt to split a templated class in a .h interface and a .cpp implementation, you get a linker error. The reason for this as mentioned in a popular post is "If the implementations were not in the header, they wouldn't be accessible, and therefore the compiler wouldn't be able to instantiate the template."
What I dont understand is that if the implementations inside a .cpp file are inaccessible in case of templated classes, what makes them accessible for non templated or just regular classes. How come we are able to split the interface and implementation for normal classes over a .h and .cpp file without getting a linker error?
Test.h
template<typename TypeOne>
TypeOne ProcessVal(TypeOne val);
Test.cpp
template<typename TypeOne>
TypeOne ProcessVal(TypeOne val)
{
// Process it here.
return val;
}
Main.cpp
void main()
{
int a, b;
b = ProcessVal(a);
}
This code gives linker error. A similar splitting of non templated classes does not give Linker error. I could post the code, but you get the idea.
In case of plain function, compiler generates code straightaway and adds generated code to compilation unit.
Test.cpp
int ProcessVal(int val)
{
// Process it here.
return val;
}
In case of the above code all the necessary information is known and C++ code of the function ProcessVal can be translated into machine instructions. As a result, object file (probably called Test.o) will contain ProcessVal symbol + corresponding code and linker can refer to it (to generate calls or to perform inlining).
On the other hand this piece of code:
Test.cpp
template<typename TypeOne>
TypeOne ProcessVal(TypeOne val)
{
// Process it here.
return val;
}
does not provide any output to compilation unit. Object file of this compilation unit (Test.o) will not contain any code for ProcessVal() function, because compiler does not know of what type TypeOne argument is going to be. You have to instantiate template to get its binary form and only this can be added to resulting binary.
When you have a template definition, nothing is added to the compilation unit, because the template argument could be many things, so you can't know from compile time what class to create, as stated in this answer.
With the non-templated case, you know what you have inside your class, you don't have to wait for a template argument to be given in order to really generate the actual class, thus the linker can see them (since they are compiled into the binary as doc's post puts it).
Basically, this goes back to the old C language. The .h files were intended to be done with the C preprocessor, and were literally textually included into the C source by the preprocessor. So if you had foo.h:
int i = 0;
and foo.c:
#include "foo.h"
int main(){ printf("%d\n", i);}
when the preprocessor was done, the compiler actually saw:
int i = 0;
int main(){ printf("%d\n", i);}
as the source file. There was no chance for a linker error, because the linker was never involved -- you just compiled one C file.
While the semantics of templates are a little more complicated now, the programming model is still the same: your .h file includes program text that is introduced to the program lexically, before actual final parsing and compilation takes place.
If you actually do want to have the implementation of a template function or a class in a separate C++ file, you can explicitly instantiate it for a certain type. For instance, in your particular example if you add this line to test.cpp, your code will successfully link
template int ProcessVal<int>(int val);

Templates and .cpp files

I am learning C++ and it hasn't been an enjoyable experience (compared to Java or VBA at least). I have the following code:
//This is in a number.h file
#pragma once
template <class T>
class number{
public:
T value1, value2, result;
public:
T add();
number(T value1_in, T value2_in);
};
//This is in a number.cpp file
template <class T>
number<T>::number(T value1_in, T value2_in){
value1 = value1_in;
value2 = value2_in;
}
template <class T>
T number<T>::add(){
result = value1 + value2;
return result;
}
//This is in main.cpp
#include "number.h"
#include <iostream>
using namespace std;
int main(){
int a = 2, b =3;
number<int> n1(a,b);
cout << n1.add();
system("pause");
return EXIT_SUCCESS;
}
Which of course gives me an error. Even though I am pretty sure it should work. More specifically I get a linker error. After 3 hours of looking at this I decided to include number.cpp in main.cpp and that magically made it work. What the hell is going on? I thought I only need to include the header file (I wrote a matrix class with a bunch of linear solvers for different algorithms before this and only included header files in the whole project). Is this C++ specific or compiler specific? (I am using Dev-C++ 4.9.9.2 which has Mingw I guess)
You do not have to put the entire definition into the header file; don't listen to what others tell you :-)
That is the conventional solution, and you and I will do it quite often, but it's not the only solution.
The other option is to simply place this line at the end of your number.cpp file, in order to force that particular template class to be instantiated and fully compiled there.
template class number<int>;
In short, there are two valid solutions. You can use this line, or you can copy the definition into the header file. Depending on context, one approach might be better than the other, but both are valid. See this answer of mine for a more comprehensive discussion of both approaches:
https://stackoverflow.com/a/8752879/146041
Templated classes or functions always need to stay in the header file.
The reason is that whenever you instantiate a template, the preprocessor (inside compiler) generates new code for exactly that kind of instantiation (e.g. number<double>). That's why the classes number<double> and number<int> will not share any relationship: They will be two completely different classes although both were generated from the same template.
For the compiler to be able to generate this code, it must know the whole template definition, not only its declaration. That's why a template needs to stay in the header in full.
Including the cpp file in your main.cpp did the trick, as it effectively became a header.
In C++, templates are just as their name suggests: templates for a class, function etc. As the concrete type of the template parameter is not known in advance, and the compiled object code depends on the actual parameter, they are not getting compiled (as normal classes and functions) until you use them in any other source file and the compiler gets to know what type should it substitute into the template parameter.
That's why all functions must be defined and implemented in the header file.
See the last section of this documentation or the answers for this similar question for further explanation.

Duplicate c++ template instantiations

Is it possible for the compiler to duplicate instantiations of a same template across several translation units?
For instance, if you have a.cpp which use a std:vector<int> inside a function, and same thing for b.cpp, is there a risk of having two times std::vector<int> in the final binary?
As sharptooth says, the final binary will only contain one instantiation. But the templates will still be instantiated everytime they are encountered in a compilation unit. If you want some compilation speed, in C++0x we get the extern templates. It works like normal extern variables, in that it has to be specified in at least one compilation unit, but the compiler wont instantiate the template in this unit. See here and this draft (14.7.2 [temp.explicit]) for more infos.
This can happen while the project is being compiled, so different .obj files will have copies of the same instantiation. When the binary is linked the linker will eliminate all redundant copies of an instantiation, so the end binary will have only one copy.
It is possible, but only if you explicitly instantiate them, but then you will get a linker errors :
// header.hpp
template< typename T >
class A
{
};
// source1.cpp
template class A< int >;
// source2.cpp
template class A< int >;
If you are not explicitly instantiating templates, then any decent linker will easily eliminate copies.
I think that the compiler uses the same mechanism as with member functions of ordinary classes. It can make them inline and I presume that it leaves information around that the linker uses to sort it out for the final binary.
The only difference is that the compiler 'writes' the definitions - that is the 'instantiation' of a template - but it manages to make exactly the same instantiation whilst compiling either of a.cpp or b.cpp

Templates and headers question

The compiler says it can't find the reference for the function when I do this:
// link.h
template <class T>
T *Link(T *&, T *(*)())
// link.cpp
template <class T>
T c:Link(T *&ChildNodeReference, T *(*ObjectCreator)()){
}
If I implement inside the class on the header it goes smoothly.
Please, I will work on the header until someone enlightens me about this.
There are somethings in C++ that are weirdly annoying. I know, there is a reason for this and etc. Even so, can't the compilers help you out about it -_-"
Templates are essentially semi-type-safe macros, hence the limitation.
Normal (non-template) functions can be compiled to native code residing object/library files, and then referenced with only a prototype available in the header, solely because there's only a single version of such a function.
With templates, C++ compiler has to compile each instantiation of the function separately. Obviously, it cannot do it "in advance", because the set of types for which you can instantiate the function is effectively unbounded (you can always define a new type in your code before calling the function). In fact, two instantiations of the same function template can be completely different. Consider this extreme case:
struct t1 {
template <int>
struct a {};
};
struct t2 {
enum { a = 123 };
};
enum { b = 456, c = 789 };
template <class T>
void foo() {
T::a<b>c;
}
Now if we call foo<t1>(), the statement inside it is a local variable declaration, because t1::a is a class template:
T::a<b> c;
But if we call foo<t2>(), the statement inside is an expression, because t2::a is an integral constant:
(T::a < b) > c;
This is just to show that compiler cannot meaningfully "compile" a template; it really has to mostly preserve the tokens.
Now, all that said, ISO C++ does actually provide the ability to separate declaration and definition of templates, so that they can be treated as normal functions, with declarations in .h files, and definitions in .cpp files. This is called "export templates", because you have to precede both declaration and definiton with keyword export:
// link.h
export template <class T>
T *Link(T *&, T *(*)());
// link.cpp
export template <class T>
T *Link(T *&ChildNodeReference, T *(*ObjectCreator)()) {
}
This is, however, a controversial feature of the Standard because of very high burden on implementation, and most popular implementations refuse to implement it; notably, g++, MSVC, and C++Builder do not implement it. The only compiler I know of that supports it is Comeau C++.
Programming non-template code or non-inlined functions in headers is a Bad Thing™. The reason you have cpp files is to prevent redefinition of the same function code more than once, amongst other things.
The difference with templates is that the compiler practically doesn't touch them until your code instantiates a specialisation of that template which is why they need to have their source inside the header.
When the compiler finds an instantiation of a template specialisation (say List<int>), it goes back to the included template code and compiles it with that specialisation, which is why you don't have issues with redefinition of function code.
What you don't seem to understand is that this doesn't apply to non-templated code. All non-template code is compiled as normal and thus CPP files are needed to only define the code once then link it all together.
If you define functions inside a header, your linker will not link the compiled translation units because they have defined the same function more than once.
Templated implementations (not only definitions) have to be available at compile time.
So, the full template code is normally put in the header file.
Template code must be in the header. Sorry, I completely missed that! (and I thought I'd been coding C++ for years :P)
You forgot the * for the return type. So implementation is not matching definition. Add it and it should work:
T *c:Link(T *&ChildNodeReference, T *(*ObjectCreator)())
{
}
Implementation must be too in the header file under the class definition in order to be available at compile time.