How does caffe split template class code into cpp and hpp files? - c++

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.

Related

Force template instantiation in another header

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>;

Inclusion of header files in case of templates.

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

Making a generic function in C++

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.

Multiple-File Template Implementation

With normal functions, the declaration and definition are often separated across multiple files like so:
// Foo.h
namespace Foo
{
void Bar();
}
.
// Foo.cpp
#include "Foo.h"
void Foo::Bar()
{
cout << "Inside function." << endl;
}
It is my understanding that this cannot be done with templates. The declaration and definition must not be separate because the appropriate form of the template is created "on-demand" when needed.
So, how and where are templates typically defined in a multiple-file project like this? My intuition is that it would be in Foo.cpp because that's where the "meat" of functions normally is, but on the other hand it's the header file that's going to be included.
You need to write definitions of templated methods in a .hxx file and include it at the end of your header file (.hh) in which you declare it. The .cc/.cpp is used to define non-templated methods.
So you'll have one .hh, one .hxx (included at the end of the .hh), and one .cc; so that including your templated class header file will include its definition too.
Example:
// list.hh
#IFNDEF LIST_HH
# DEFINE LIST_HH
template <typename T>
class List
{
void fun1(T a);
void fun2();
}
# include "list.hxx"
#ENDIF
// list.hxx
#IFNDEF LIST_HXX
# DEFINE LIST_HXX
# include "list.hh"
template <typename T>
void List::fun1(T a)
{
// ...
}
#ENDIF
// list.cc
#include "list.hh"
void List::fun2()
{
// ...
}
// anywhere.cc
#include "list.hh"
// ...
EDIT
There are several strategies to compile templates. The most common strategy is the one described above to let every user of the class template instantiate the code.
But, because the *.hh file includes the *.hxx file, each time a simple declaration of a template is needed, the full implementation comes with it. And if the implementation requires other declarations such as std::string, you force all the client code to parse the string header.
To avoid instantiations several times (time and space consuming), you can introduce a fourth type of file, *.hcc: files that must be compiled once for each concrete template parameter.
See Also Compile-Time Dependencies
EDIT2
Writing the template definition directly in the header file is called inclusion model. Doing so increases the cost of including the header. Not only because we added the definition of the template but because we included headers (, , whatever) which represent thousands of lines. A real problem for significant programs to compile (we are talking about hours of compilation here).
The separation model
Source
And my last argument: keep clear the header file so that it only contains the class declaration and its documentation. Like that, any other programmer is able to fastly read your header file: what is the public interface of this class, what does the documentation says.
Template code stays in the .hh file. There's no reason to make them separate files, though it is good practice to put the definitions after all the declarations.
When the compiler generates template code, it flags it so that the linker knows that the instantiation of a template in one compilation unit (i.e. .o file) is the exact same code as one in another unit. It will keep one and discard the rest, rather than bailing out with a "multiply defined symbol" error.
This is true of modern compilers with good template support. In the case of GCC, since 2.8. (I know, I wrote a lot of code for gcc 2.7.2.2 before they smartened the linker up and you had to jump through hoops to make templates build right.)
I'm disappointed that no answers mentioned that the C++ standard permits you to separate the definition from the declaration. It goes like this:
// Foo.h
export template<class T> T f();
// Foo.cpp
#include "Foo.h"
export template<class T> T f()
{
// blah blah
}
Unfortunately, almost no compilers support export. Comeau is one that does.
However, export is removed from C++ in C++0x.

c++ class with template cannot find its constructor

I have a problem I don't really understand. I have a class Node.
template<class T>
class node {
protected:
T _data;
public:
node(T data);
};
This is in "node.h" file. In "node.cpp" file, there is this constructor:
#include "node.h"
template<class T>
node<T>::node (T data) {
_data = data;
}
While the compiler finds no error, the linker (ld) tells me:
/usr/bin/ld: Undefined symbols:
node<int>::node(int)
the weird part... if I move the constructor from .cpp to .h file, everything works fine. Where is the problem?
The problem is that templates aren't classes - you don't normally write them in two separate files. Template classes are code that the compiler uses to generate classes. As such, your implementation code needs to effectively be inline, i.e., in the header as you discovered.
For a fuller explanation of why it has to be this way, see the C++ FAQ Lite.
As a general rule, you must put all template members inside of the header file. Templates are compiled in an as-used basis, and hence the entire definition needs to be available wherever they are used. Putting the code in the header file will solve that problem.
The only time you can put a template definition in a CPP file is when the template will only be used within that CPP file. The reason being is that it meets the standard that the entire definition is available for compilation.
Moving the contents of node.cpp to node.h will fix the problem.
Strange Scenarios
Then again, you can also put everything in a CPP file and include the CPP file. C++ is flexible in this way. I only mention this because I've seen in done before. I actually bruised my jaw when it hit the top of my desk.
When you use node<int>, you have not most likely included node.cpp. Therefore the compiler cannot instantiate the node<int>::node<int> constructor. Usually you put all the template code, including all the implementations of the methods, in the header file, or something included from it.
The commonly accepted practice is to put all of the implementation in the .h file, so that the classes can be generated from the template as needed.
If you know ahead of time which types your template will be instantiated with, you might be able to cheat a little. Just make sure your .cpp includes a use case for each type and method you will need. It is important that the use case come after the template code. E.g. for "node.cpp", use
#include "node.h"
template<class T>
node<T>::node (T data) {
_data = data;
}
void dummy(void)
{
node<int> intnode(0);
node<double> doublenode(0.0);
}
// You can put templates declaration in header and definition in source
// node.h or wherever you include file gets included
extern template class node<int>;
// node.cpp or where ever source file you want to use it
// But use it only once for each type of generated class
template class node<int>;
Unless there's a call to the function, the compiler won't output any code and the linker won't find it.
You should put the function in the header where it belongs.
implicit instantiation is turned off, you need
template class node<int>;
somewhere in your code (node.cpp maybe)
EDIT: bad answer, it's probably not the case.