1

So I was getting a linking error in my c++ project and a stackoverflow post mentioned that template methods need to also be defined in the header instead of the source file.

The code for that specific method is (after combinging the declaration / definition):

struct Timer {
  template <typename T>
  const long getDuration() const; 
};

template <typename T>
const long Timer::getDuration() const {
   long time = static_cast<long>(std::chrono::duration_cast<T>(end - start).count());

  return time > 0 ? time : 1L;
}

Now the explaination was that for templates, the compiler needed the definition in order to be able to process it but that does not seem to be the case all the time.

For example, this is code that to me looks similar as the code above however I can place the declaration in the header file and the definition in source file:

// Enity.hpp
class Entity {
  public:
    template <typename T>
    bool hasComponent() const;
}

// Entity.cpp
template <typename T>
bool Entity::hasComponent() const {
  return componentBitSet[getComponentTypeId<T>()];
}

I am still relatively new to modern c++ so I am trying to understand why in the first example I need the declaration and definition in the same file and in the second, they can be split out.

ryanzec
  • 27,284
  • 38
  • 112
  • 169
  • All of those are template declarations. Template declarations belong in header files. A template is not instantiated until it is used (the compiler takes care of that). – Eljay Jun 23 '18 at 22:29
  • @Eljay Isn't `template const long Timer::getDuration() const {...}` a definition? – HolyBlackCat Jun 23 '18 at 22:35
  • Yes, you can place the definition into the .cpp. But you'll get "undefined reference to ..." when you try to use the template, unless you do instantination in the same .cpp, as described in the link. – HolyBlackCat Jun 23 '18 at 22:37
  • @HolyBlackCat • unsure; from a language-lawyer standpoint (which I'm not one), I do not know what terminology the standard uses. – Eljay Jun 24 '18 at 00:35
  • @HolyBlackCat regarding your response to Eljay, that is indeed a definition, but that doesn't conflict with what they said as all definitions are declarations. That said, I don't quite get their point. – eerorika Jun 24 '18 at 00:37

2 Answers2

4

Why do I sometimes need to put c++ template function definitions in header file?

Because sometimes (quite often) you may want to instantiate the template in more than one translation unit.

however I can place the declaration in the header file and the definition in source file

Remember how including a file into another works. The pre-processor simply copies the included file into the source file.

Thus, if it were correct (and it is, in fact, correct) to put a template definition in a header file and include it into a source file , then of course it is also correct to put that definition directly into the source file - there is no difference to what the compiler sees (after pre-processing).

But remember that a template can only be instantiated in a translation unit where it has been defined - this is the consequence of the explanation that you paraphrased. So, if you attempted:

// Other.cpp
#include "Enity.hpp"

struct X {};

void foo {
    Entity e;
    e.hasComponent<X>();
}

It couldn't work since Other.cpp cannot instantiate Enity::hasComponent<X> without the definition of Enity::hasComponent.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

The reason you need to define the template in the header file is because the compiler generates code for the template depending on what types you call it with, when you call it.

If you put the definition in the source file, the compiler will know about the existence of the template, but will lack a definition (which could theoretically be anywhere) when it finds that you are calling the template, thus yielding an error.

Note that this error remains silent when you don't call the template, because the compiler does not have to generate code for it. Perhaps that is the reason you first did not encounter any errors when separating the definition from the declaration?

L. Kue
  • 473
  • 5
  • 19