0

Is it possible to have a generic function declaration in a header file and the subsequent definition in a definition file?

I'd like to do something like this

HEADER FILE:

#ifndef PROCEDURES_H
#define PROCEDURES_H
template<class T>
T max(const T&, const T&);
#endif

DEFINITION FILE:

#include "procedures.h"
template<class T>
T max(const T& left, const T& right)
{
    return left > right ? left : right;
}

This results in a linker error.

Of course if I just put everything in the header it works fine.

Mars
  • 4,677
  • 8
  • 43
  • 65
  • Classic case of answering your own question?! – Kerrek SB Nov 03 '13 at 23:00
  • `max` is *not* a "generic function". It is a *template*. That error in perception may underpin the entirety of your confusion. – Kerrek SB Nov 03 '13 at 23:01
  • Would you be happy with the classic solution of `#include-`ing your definition file at the bottom of your header file? You could establish a convention like all your defintion files have extension `.hpp` or `.tpp`. But really, you should read a little about _template instantiation_ and why this doesn't work. – NicholasM Nov 03 '13 at 23:01
  • @NicholasM. So if my definition file is `procedures.cpp` I would `#include "procedures.cpp"` at the bottom of my header file? – Mars Nov 03 '13 at 23:03
  • Essentially, yes. By convention, I would not use the `.cpp` extension. Please see the accepted answer here: http://stackoverflow.com/questions/3526299/c-templates-declare-in-h-define-in-hpp – NicholasM Nov 03 '13 at 23:05

1 Answers1

3

You can put template definitions into implementation (i.e., non-header) files. However, the compiler probably won't do the instantiation for you. The compiler will only implicitly instantiate what is used when the definition is seen. Instead, you would need to do the instantiation yourself. I found it useful in the past to have three kinds of files:

  1. Header files which declare function templates or member function templates.
  2. Template definition files which are pretty much like header files but define the [member] function templates declared in their respective header.
  3. Source files which would include the template definition files as necessary and explicitly instantiate the [member] function templates.

Whether explicit instantiation is feasible for a specific template depends on how many different instantiations are actually being used. It is probably not feasible for algorithms or class templates like std::vector<T> but it is certainly feasible, e.g., for the IOStream templates which have just two instantiations.

Here are a few more details on to organize sources involving templates.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380