When we make a class we declare its functions in a header files and define them in a source file... then the header file can be included in the main file to use the class...
But if we declare a template class in header files and define it in the .cpp file and then if we include the header file in the main(containing int main) file then why does a linker error crop up... and the error does not crop up if we included the .cpp file(containing the header file ) in the main file... any answers plz?
Templates don't actually produce any object code at the point where the compiler reads their source code; they're (typically) only "instantiated" when something actually uses the template. So if you define a template function in one source file, and call it from another, the code for the template function doesn't get compiled at all: it's not in the first object file since nothing there needed it, and it's not in the second object file since the compiler didn't have access to the function's definition.
You define template functions in header files so that in each translation unit where something calls the template function, the compiler has access to its code and can compile a copy of it specialized with the appropriate template arguments.
Alternatively, you can use explicit instantiation: you define the template function in a .cpp file, and also tell the compiler exactly which types that it should compile the function for. This is harder to maintain, because you have to keep track of which instantiations are needed by the rest of the program. If something calls foo<float>(), but you've only explicitly instantiated foo<int>() and foo<char>(), you get a missing-symbol error.
You shouldn't #include a .cpp file from another .cpp file. Just put the template function definitions in the header together with their declarations.
A template is neither a class nor a function. Its a pattern that compiler uses to generate classes or functions.
Very nicely explained in HERE
Related
I do not understand the difference between .h, .hpp and .cpp files in the Point Cloud Library. Here is an example with the bilateral filter, they say that:
include/pcl/filters/bilateral.h - will contain all definitions;
include/pcl/filters/impl/bilateral.hpp - will contain the templated implementations;
src/bilateral.cpp - will contain the explicit template instantiations.
I understand the general concept of header file and implementation, but why are there two headers file? What's the difference between the templated implementation and the explicit template instantiation?
At this moment I am working with the Kmeans class and the .hpp is not used, instead they just have the implementation in a .cpp file and they include an .h file. Why? Moreover, in kmeans.h file they give the implementation of some public member functions, not just setters and getters. I can't find the rationale behind this code.
Thank you!
Consider that only the .h is the header file, the one that contains the definitions and the one you should include.
The implementations are in both the hpp and the cpp files.
hpp: contains the generic templates template<class T>,
cpp: contains non template functions or explicit instantiations template<pcl::PointXYZ>
Both files .h and .hpp can be merged in same file but is clearer to separate them.
I am reading caffe code and find it split C++ class Template code into hpp and cpp files. For example, Net.cpp includes the template class Net implementation code and Net.hpp includes the definition. But I remembered it is not possible to split a template class into hpp and cpp files, how does caffe make this work?
Thank you.
As you noted, template definitions cannot be split up as easily from the declarations without jumping through some hoops.
One common pattern is to split them up in different files for the human reader but essentially they are still defined all in one header. For example
Foo.h
#pragma once
template <typename T>
void Foo(); // declaration
#include "Foo.inl"
Foo.inl
template <typename T>
void Foo()
{
// actual definition
}
Notice that the last thing in the .h file is to actually include the full contents of the .inl file. As far as the compiler is concerned, all of the template definitions are contained in the header to solve the initial problem you mentioned. But to the human reader, the declarations and definitions are separated.
you can not "usually" separate the template definition and deceleration. when the compiler instantiate the template it need to know exactly the definition and the declaration of the members that are used in the context. so if you only include the header file the compiler doesn't know how to instantiate the template for the template parameter.
A solution other than the one that coryKramer mentioned is after the full definition (in the .cpp file) explicitly instantiate the template for the template parameters that you need, this way the template is already instantiated for the values that you would like to use (at this point we have the full declration and definition of template). However, note that if the template is need to be instantiated for other values you may encounter errors as compiler doesn't know how to do this process if the template is not fully defined in that file!
This is the method that is used in caffe via INSTANTIATE_CLASS(Net) macro at the end of .cpp file.
While making a template linked list, rather than having the files list.h and list.cpp, we create list.h and list.cpp.h. The .cpp.h file contains the implementation for the linked list class. At the end of list.h, before the #ENDIF, we #include "list.cpp.h".
I understand that by making the .cpp file a header file we are able to avoid compiling it, but how does this work? We have needed to compile implementations that rely on using "template < class T >" in the past, so why do we not have to compile this implementation file?
Edit: My question was marked as a duplicate with a link to Why can templates only be implemented in the header file? , which I had already read. That question does not answer why the template implementation does not need to be compiled like a normal .cpp implementation file does. If we can avoid compiling implementations by making them header files, why do we not do that for every implementation? What are the downsides?
Does instantiating a template compile the code for each instance of that template? If my .cpp ever requires the use of a template in one of its functions, then why wouldn't I change it to a header file if it avoids this initial compilation?
I hope my question makes more sense.
Remember, a #include directive just pulls the contents of the header into the file that's currently being compiled. So the template does get compiled; it gets compiled in every translation unit that #includes the file where the template is defined. And when the template is used (later in that file) it gets instantiated.
In what you are saying, you are including the templates as header file, since your .h file includes the .ccp.h file in the end.
So this is a convention on your project, to seperate the normal .h and the template code in two files.
Hence the template code, in your case, is compiled into the regular .cpp code.
The reason why you would want to avoid that is "bloat" -- every .cpp file will create it's own copy of the template code used in that cpp-unit, so if if A.cpp and B.cpp both includes T.cpp.h, they may both create the same code if they use the same templates, and it takes a smart optimizer to remove all the duplication.
I have a templated "collection" class. I don't wan't the code be recompiled in every source file. But this collection should be used with DataTypes (class SpecialDataMember : DataMember) not defined on definition of the the template class.
This is why I can't force the instantiation in the template source file (throug moving the definitions to the source file and add template LinkCollection<DataMember>;), because the definitions of the template must be accessible in other source files ("SpecialDataMember.cpp").
Is it possible to make "SpecialDataMember.o" hold the code for LinkCollection<SpecialDataMember>. Every includer of SpecialDataMember.h should know I leave LinkCollection<SpecialDataMember> to the linker.
I see two options but I don't know if they work:
Make two template headers (with header guard) one with the definitions one without.
SpecialDataMember.h
// ..
include "LinkCollection.h"
// ..
SpecialDataMember.cpp
// ..
include "LinkCollectionImpl.h"
// ..
include "SpecialDataMember.h"
// ..
template LinkCollection<SpecialDataMember>;
All includers of "SpecialDataMember.h" will not know the definitions of the template so they will let the linker do his work.And the linker will find the instantiation of LinkCollection<SpecialDataMember> in SpecialDataMember.o. Is that correct?
But I would have to maintain two header Files. Is there a better way to gain this effect?
Use template derived classes
If I create a special class SpecialDataMemberLinkCollection : LinkCollection<SpecialDataMemberLink> in the "SpecialDataMember" header and source file, I could reference this special class instead and so the compiler knows there is an instantiation of that class and the base class template and leaves the work to the linker. Will this work as expect?
Is it possible to make "SpecialDataMember.o" hold the code for LinkCollection<SpecialDataMember>. Every includer of SpecialDataMember.h should know I leave LinkCollection<SpecialDataMember> to the linker.
Simple, just put:
extern template class LinkCollection<SpecialDataMember>;
in the header, which tells the compiler not to instantiate that template and leave it to another file.
Then in one SpecialDataMember.cpp file provide that instantiation:
template class LinkCollection<SpecialDataMember>;
I try to make a generic function in C++, that creating an array of a type which depends on usage (when calling it), like array of int or char.
This is the code in my header file:
template<class T>
T** makeArray(...);
This is in the .cpp file:
template<class T>
T** ClassA::makeArray(...){
//...
}
And this is how I call it in the main file:
char** charArr = cg.makeArray<char>(...);
//...
int** intArr = cg.makeArray<int>(...);
But when compiling, I get these errors:
undefined reference to `char** ClassA::makeArray<char>( ...
undefined reference to `int** ClassA::makeArray<int>( ...
What do the errors mean and how do I fix it?
You have to include the entire body of a C++ template function in the header.
This is because of the way that C++ templates work: template parameter substitution happens only when you actually use the template, and the entire template definition has to be visible at that time. Another way of looking at it is to say that you cannot compile and link to a templateFunction<T>—you can only compile a template function once it's been instantiated as a templateFunction<char> or whatever. For this reason, you cannot put template function definitions in .cpp files, but rather have to put them in .h files.
The compiler needs to have access to the entire template definition (not just the signature) in order to generate code for each instantiation of the template, so you need to move the definitions of the functions to your header.
This is called the inclusion model. Also read this FAQ
In general, you cannot have template definitions in a source file; they should be in the header file so that the compiler can see them.
This comes up over and over again here, so I can't be bothered to give the full explanation again; I recommend you read this from the C++ FAQ: Why can't I separate the definition of my templates class from its declaration and put it inside a .cpp file?.
[Incidentally, why are you returning a pointer-to-pointer? A pointer should be enough...]
If your code is using the template on a diferent cpp file, the template should go on the header file.