Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template (.tpp) file include guards

When writing templated classes, I like to move the implementation into a different file (myclass.tpp) and include it at the bottom of the main header (myclass.hpp).

My Question is: do I need include guards in the .tpp file or is it sufficient to have them in the .hpp file?

Example code:

myclass.hpp

#ifndef MYCLASS_HPP
#define MYCLASS_HPP

template<typename T>
class MyClass
{
public:
    T foo(T obj);
};

//include template implemetation
#include "myclass.tpp"

#endif

myclass.tpp

#ifndef MYCLASS_TPP //needed?
#define MYCLASS_TPP //needed?

template<typename T>
T MyClass<T>::foo(T obj)
{
    return obj;
}

#endif //needed?
like image 215
perivesta Avatar asked Jan 25 '19 09:01

perivesta


1 Answers

Do I need include guards in the .tpp file or is it sufficient to have them in the .hpp file?

Include guards are never needed: they're just terribly useful, cheap, non-disruptive and expected. So Yes, you should protect both files with header guards:

  • Terribly useful: they allow you to declare a dependency from multiple files without keeping track of which files have already been included.
  • Cheap: this is just some precompilation tokens.
  • Non-disruptive: they fit well with most use-cases of #include (I've had a colleague who didn't know how to write macros so he #included implementation files facepalm).
  • Expected: developers know what they are and barely notice them; on the contrary a header file missing include guards wakes us up and adds to the global wtf/line counter.

I take the opportunity to highlight the comment from StoryTeller:

I'd go a step further and add a descriptive #error directive if the hpp guard is not defined. Just to offer a little protection from people including the tpp first.

Which will translate to:

#ifndef MYCLASS_TPP
#define MYCLASS_TPP

#ifndef MYCLASS_HPP
#error __FILE__ should only be included from myclass.hpp.
#endif // MYCLASS_HPP

template<typename T>
T MyClass<T>::foo(T obj)
{
    return obj;
}

#endif // MYCLASS_TPP

Notice: if a translation unit first #include <myclass.hpp> and then #include <myclass.tpp>, no error is fired and everything is fine.

like image 123
YSC Avatar answered Sep 24 '22 12:09

YSC