I'm working on a library that is heavily using templates so I decided to make it a header-only library. Since declarations and implementations are in the same file, I can now do both at the same time. So I have a choice between these two styles:
// seperate declaration and implementation
template <typename T>
class Klass {
public:
void do_something();
};
template <typename T>
void Klass<T>::do_something()
{
// do something
}
// or both at the same time
template <typename T>
class Klass {
public:
void do_something()
{
// do something
}
};
I was wondering if there is a difference between these two for the compiler. If not which one would you recommend as a better practice?
Header File is the file where all the headers name are mentioned that going to be used or consumed in the main code file. On other hand Library is the file where the implementation code of each header is written down which is mentioned in the Header file.
Class definitions can be put in header files in order to facilitate reuse in multiple files or multiple projects. Traditionally, the class definition is put in a header file of the same name as the class, and the member functions defined outside of the class are put in a . cpp file of the same name as the class.
For example, header-only libraries sometimes increase code size & compilation times. "Having a header-only library also means you don't have to worry about different platforms where the library might be used": only if you don't have to maintain the library.
Header files can include any legal C source code. They are most often used to include external variable declarations, macro definitions, type definitions, and function declarations.
If you merge the definition and the implementation you will have problem solving cross/circular dependencies.
For example:
home.hpp
#ifndef HOME_HPP
# define HOME_HPP
# include <string>
# include "human.hpp"
template <typename T>
class Home
{
public:
Home()
:
color_("white"),
inhabitant_(this)
{
}
void set_color(const std::string& color)
{
color_ = color;
}
private:
std::string color_;
Human<T> inhabitant_;
};
#endif
human.hpp
#ifndef HUMAN_HPP
# define HUMAN_HPP
# include <string>
// Cannot include the other header here because it already includes us
//# include "house.hpp"
// So we do a forward declaration:
template<typename T>
class Home;
template <typename T>
class Human
{
public:
Human(Home<T>* house)
:
house_(house)
{
}
void paint(const std::string& color)
{
// Oops, we can't use House in our implementation
// because it is only forward declared
//house_->set_color(color);
}
private:
Home<T>* house_;
};
#endif
You cannot use the other object.
Whereas if you split your implementation in another file:
home.hpp
#ifndef HOME_HPP
# define HOME_HPP
# include <string>
# include "human.hpp"
template <typename T>
class Home
{
public:
Home();
void set_color(const std::string& color);
private:
std::string color_;
Human<T> inhabitant_;
};
#endif
home.ipp
#ifndef HOME_IPP
# define HOME_IPP
# include "home.hpp"
template<typename T>
Home<T>::Home()
:
color_("white"),
inhabitant_(this)
{
}
template<typename T>
void Home<T>::set_color(const std::string& color);
{
color_ = color;
}
#endif
human.hpp
#ifndef HUMAN_HPP
# define HUMAN_HPP
# include <string>
template<typename T>
class Home;
template <typename T>
class Human
{
public:
Human(Home<T>* house);
void paint(const std::string& color);
private:
Home<T>* house_;
};
#endif
human.ipp
#ifndef HUMAN_IPP
# define HUMAN_IPP
# include "human.hpp"
# include "house.ipp"
template<typename T>
Human<T>::Human(Home<T>* house)
:
house_(house)
{
}
template<typename T>
void Human<T>::paint(const std::string& color)
{
house_->set_color(color);
}
#endif
Things works more smoothly
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With