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.
Related
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.
Currently, I am writing a few classes, all of which inherit from a base class and somehow enrich it. All of these classes use templates in order to take different elements as parameters (the classes are all variations of an abstract vector class). So I wrote all of the code in one big .hpp file because I read that splitting the code in .hpp and .cpp would cause linker problems (Splitting templated C++ classes into .hpp/.cpp files--is it possible?) and it wouldn't work.
So I was wondering, since it's not really clean and clear to have everything in a big .hpp file, should I split it and how would I do the splitting the right way in order to keep the code as intact as possible? Should I import the child classes into the base class? Do I have to forward declare all my classes in every .hpp file or not? How would the splitting interact with the templates.
If the code is necessary, I can add it. Just trying to keep it short if it isn't.
As far as splitting the code up, there is a technique for templated code where you can split up the declarations and definitions, at least visually (you'll see why I make that distinction in a moment). So you first start with the header, that will contain just your class and function declarations
Foo.h
template <typename T>
T some_foo(T x); // declaration
#include "Foo.inl"
Then you make a separate file for the implementation. Note that we #include this .inl file in our header, so as far as the compiler is concerned all of the code still exists in the header. Doing it this way is just for human readers, but this way you can split up the actual implementation code into separate files and just include them at the end of the header.
Foo.inl
<template <typename T>
T some_foo(T x) // definition
{
return x + 5;
}
Files:
header.hpp
something1.ipp
something2.ipp
something3.ipp
Content of header.hpp:
#ifndef COMPANY_PROJECT_HEADER_HPP
#define COMPANY_PROJECT_HEADER_HPP 1
#include "something1.ipp"
#include "something2.ipp"
#include "something3.ipp"
#endif
Easy peasy. #include is just a "copy-and-paste" operation so you can do what you like to arrange your files in a pleasing, and easy-to-maintain organisational structure.
All the files are headers, but I've given the "sub-headers" the extension .ipp to distinguish them.
So I wrote all of the code in one big .hpp file because I read that splitting the code in .hpp and .cpp would cause linker problems ... and it wouldn't work.
That only implies that you must not split the definition of the function templates from their declaration (or the definition of member function of a class template from the definition of the template). There is no reason to put the definition of all templates into a single header - which your post seems to imply that you did.
So I was wondering, since it's not really clean and clear to have everything in a big .hpp file, should I split it
Sure.
and how would I do the splitting the right way
Just be sure to keep the definitions of the templates in the same file that declared them - as described in the answers to the linked question. If you think that's messy, then you can put the definitions into another header and include that in the declaring header.
Do I have to forward declare all my classes in every .hpp file or not?
Only in headers that refer to the declarations, but don't need the complete definition.
In a project I'm working on, I have a fairly large templated class that I've implemented like this:
I have my header file
// MyBigClass.h
#ifndef MYBIGCLASS_H
#define MYBIGCLASS_H
template <typename T>
class MyBigClass {
/* -- snip -- */
};
#include "MyBigClass.cpp"
#include "MyBigClass_iterator.cpp"
#include "MyBigClass_complicatedFunctionality_1.cpp"
#include "MyBigClass_complicatedFunctionality_2.cpp"
#endif
And then all of my implementation files look basically like this:
// MyBigClass_foobar.cpp
template <typename T>
void MyBigClass<T>::member_1(){
/* -- snip -- */
}
template <typename T>
int MyBigClass<T>::member_2(int foo, T & bar){
/* -- snip -- */
}
// etc, etc
In main.cpp, I just include MyBigClass.h, and everything works and compiles fine. The reason I've split the implementation into many files is because I prefer working on three or four 200-400 line files, versus one 1200 line file. The files themselves are fairly logically organized, containing for example only the implementation of a nested class, or a group of interrelated member functions.
My question is, is this something that is done? I got a strange reaction when I showed this to someone the other day, so I wanted to know if this is a bad practice, or if there is a better, more usual way to accomplish something like this.
It's convention to generally not include cpp files (there are limited and exotic cases when this is done), that's probably the reason you got the weird looks.
Usually this separation is done by moving the implementation to an .impl or even a .h file instead of a cpp file.
And no, there's nothing wrong with separating the implementation of templates and including the file in the header.
So... include .cpp is a bad practice, but what prevent you from using header files instead of .cpp? boost use .ipp files for example...
Having worked on C/C++ projects with thousand or more files, this is the practice I've generally observed:
Keep the class definitions in the header file. Do not add any implementation in the header file. The exceptions being inline functions and templates. I'll come to that in the end.
Keep all of your function and method implementations in .c or .cpp files.
There are fundamental reasons of doing so.
.h files act as a reference point for anyone to use the classes/functions/ and other data structures and APIs you've implemented in your code. Anyone unaware of the class structure will refer the .h first.
You can distribute a library revealing only the .h file without revealing your actual implementation. Usually they come up with external APIs (again in .h files) which are the only entry points to any code within the library and can be used by 3rd parties if they wish to share the code.
If you include a .c or .cpp file in multiple places - you'll not see any errors during the compilation - but the linker will bail out complaining about duplicate symbols. Since it has more than one copy of all those functions/methods part of the .c/.cpp file you included.
Exceptions
Inline function implementations need to be present in .h files to be effective. There are cases when the compiler might automatically be able to decide that a piece of code can be inlined - but in some cases it requires the presence of the inline keyword. NOTE: I'm only talking about the latter here. The compiler will inline any function only if it sees the inline keyword. In other words if a .cpp has the following piece of code:
class A;
A.my_inline_method();
If my_inline_method() is not visible to the compiler as an inline function when compiling this cpp file, it will not inline this function.
Templates are similar to inline methods when it comes to compilation - when the code for a template needs to be generated by the compiler in the .cpp where it is used - it needs to know the entire implementation of that template. Since template code generation is compile-time and NOT runtime.
I've mentioned the more common philosophies behind this. Feel free to edit this answer to add more if I've missed.
More info on template stuff here: Why can templates only be implemented in the header file?
EDIT: Made changes based on #Forever's comment to avoid ambiguity.
I'm answering my own question to add that a somewhat standard extension for template implementation seems to be .tcc. It's recognized by github's syntax highlighter, and is also mentioned in the gcc man page:
C++ source files conventionally use one of the suffixes .C, .cc, .cpp, .CPP, .c++, .cp, or .cxx; C++ header files often use .hh, .hpp, .H, or (for shared template code) .tcc;
If I'm misunderstanding the intended use of the .tcc extension, please let me know and I will delete this answer!
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