This is a text-only version of the following page on https://raymii.org:
---
Title       : 	C++ template definitions in a .cpp file (instead of a header file)
Author      : 	Remy van Elst
Date        : 	22-06-2019
URL         : 	https://raymii.org/s/snippets/Cpp_template_definitions_in_a_cpp_file_instead_of_header.html
Format      : 	Markdown/HTML
---



In this snippet I'll show you how to place your C++ template definitions
in a seperate `.cpp` file. I'd recommend you to just put template definitions in 
your header file, or a `.hpp` file, but if you really want to there is a trick to
get them in a seperate `.cpp` file. The trick is to explicitly instanciate every
template you're going to use at the end of the `.cpp` file. With many different
templates and types this becomes cumbersome, but for certain usecases it could
be useful. 

<p class="ad"> <b>Recently I removed all Google Ads from this site due to their invasive tracking, as well as Google Analytics. Please, if you found this content useful, consider a small donation using any of the options below:</b><br><br> <a href="https://leafnode.nl">I'm developing an open source monitoring app called  Leaf Node Monitoring, for windows, linux & android. Go check it out!</a><br><br> <a href="https://github.com/sponsors/RaymiiOrg/">Consider sponsoring me on Github. It means the world to me if you show your appreciation and you'll help pay the server costs.</a><br><br> <a href="https://www.digitalocean.com/?refcode=7435ae6b8212">You can also sponsor me by getting a Digital Ocean VPS. With this referral link you'll get $100 credit for 60 days. </a><br><br> </p>


### Template definitions

Small recap on templates. A template is not an actual class or function, but 
a "pattern" that the compiler uses to generate a family of classes or functions. 

In order for the compiler to generate the code, it must see both the template
definition (not just declaration) and the specific types/whatever used to "fill
in" the template. For example, if you're trying to use a `Foo<int>`, the compiler
must see both the `Foo` template and the fact that you're trying to make a
specific `Foo<int>`. [See here for more explanation][1].

Placing templates in your `.h` files might result in cluttered header files, it 
also could increase code bloat and the compiled binary size. (That however does
depend on how smart your compiler is). For the cluttering people often resort to
`.hpp` files. Which brings its own set of problems, for example with your build
system if you're doing something special.

The trick I found [here][2] is that you can place your template definitions in a 
seperate `.cpp` file and explicitly instanciate every form of that template that 
is going to be used in that `.cpp` file. 

If you don't instanciate all forms in your `.cpp` file you will get 
`undefined reference` errors, I'll show you an example later on.

The linker however does spew out the specific form so you can copy/paste it quickly.


### Example code

I've written a sample program with a class with one template function, one other class and the 
`main.cpp` file. This is the directory layout, you can ignore the `CMake` files:

    $ tree -L 1   
    .
    |-- CMakeLists.txt
    |-- TestClass1.cpp
    |-- TestClass1.h
    |-- TestClass2.cpp
    |-- TestClass2.h
    |-- cmake-build-debug
    `-- main.cpp

    1 directory, 6 files



#### TestClass1.h

This file contains the class with one template function. It does not contain the
template defintion, only the declaration. Normally you would define the entire template 
here but that's the part we don't want to in this example.

    #ifndef TESTCLASS1_H
    #define TESTCLASS1_H

    #include <iostream>

    class TestClass
            {
    private:
        bool m_bool1 { false };
        
    public:
        TestClass(bool bool1) : m_bool1(bool1) {}
        // just the template declaration
        template <typename T1, typename T2>
        void templateFunction(T1 var1, T2 var2);
        
    };

    #endif //TESTCLASS1_H


#### TestClass1.cpp

This is where the template is defined, and at the bottom, instanciated
explicitly for the types we're going to use in the code.


    #include <iostream>
    #include "TestClass1.h"
    //actual template definiton
    template <typename T1, typename T2>
    void TestClass::templateFunction (T1 var1, T2 var2) {
        std::cout << "var1: " << var1 << ", ";
        std::cout << "var2: " << var2 << ", ";
        std::cout << "m_bool1: " << m_bool1 << "\n";
    }

    // Here is the explicit instanciation
    template void TestClass::templateFunction<int, int>(int, int);
    template void TestClass::templateFunction<char const*, char const*>(char const*, char const*);


#### TestClass2.h

This is just another class where the template is used, as an example.


    #ifndef TESTCLASS2_H
    #define TESTCLASS2_H
    #include "TestClass1.h"

    class TestClass2 {
    private:
        bool m_abc1 {false};

    public:
        void printTest();
    };

    #endif //TESTCLASS2_H


#### TestClass2.cpp

Here is the definition of the above function, where the other template is called
with a `const char *`.

    #include "TestClass2.h"

    void TestClass2::printTest () {
        TestClass example(false);
        example.templateFunction ("abc", "def");
    };

#### main.cpp

It all comes together in the `main.cpp` file, one of both classes. I've used
two different methods of calling the class templated function, either explicitly
telling which types were using or just letting the compiler figure it out.

    #include <iostream>
    #include "TestClass1.h"
    #include "TestClass2.h"

    int main () {
        TestClass example1(true);
        example1.templateFunction<int, int> (1, 2);
        example1.templateFunction (3, 4);
        
        TestClass2 lala = TestClass2();
        lala.printTest ();
        return 0;
    }


Example output:

    var1: 1, var2: 2, m_bool1: 1
    var1: 3, var2: 4, m_bool1: 1
    var1: abc, var2: def, m_bool1: 0


### Error, undefined reference

The warning when you forget to instanciate a template, or in this example, 
uncommented one:

    //template void TestClass::templateFunction<int, int>(int, int);
    template void TestClass::templateFunction<char const*, char const*>(char const*, char const*);

Output:

    [100%] Linking CXX executable example
    CMakeFiles/folder.dir/main.cpp.o: In function `main':
    folder/main.cpp:7: undefined reference to `void TestClass::templateFunction<int, int>(int, int)'
    folder/main.cpp:8: undefined reference to `void TestClass::templateFunction<int, int>(int, int)'
    collect2: error: ld returned 1 exit status


If you would use the template with two `doubles` you would have to add this at 
the end of the file `TestClass1.cpp`:

    template void TestClass::templateFunction<double, double>(double, double);

### In the header file

If the template function for `TestClass1` was in the header file, it would look 
like this:

`TestClass1.h`:


    #ifndef TESTCLASS1_H
    #define TESTCLASS1_H

    #include <iostream>

    class TestClass {
    private:
        bool m_bool1 { false };
        
    public:
        TestClass(bool bool1) : m_bool1(bool1) {}
        // template declaration and definiton
        template <typename T1, typename T2>
        void templateFunction (T1 var1, T2 var2) {
            std::cout << "var1: " << var1 << ", ";
            std::cout << "var2: " << var2 << ", ";
            std::cout << "m_bool1: " << m_bool1 << "\n";
        }
    };

    #endif //TESTCLASS1_H


You would not need the `TestClass1.cpp` file. 

[1]: http://web.archive.org/web/20190621081506/https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl
[2]: http://web.archive.org/web/20190621081506/https://isocpp.org/wiki/faq/templates#separate-template-fn-defn-from-decl



---

License:
All the text on this website is free as in freedom unless stated otherwise. 
This means you can use it in any way you want, you can copy it, change it 
the way you like and republish it, as long as you release the (modified) 
content under the same license to give others the same freedoms you've got 
and place my name and a link to this site with the article as source.

This site uses Google Analytics for statistics and Google Adwords for 
advertisements. You are tracked and Google knows everything about you. 
Use an adblocker like ublock-origin if you don't want it.

All the code on this website is licensed under the GNU GPL v3 license 
unless already licensed under a license which does not allows this form 
of licensing or if another license is stated on that page / in that software:

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

Just to be clear, the information on this website is for meant for educational 
purposes and you use it at your own risk. I do not take responsibility if you 
screw something up. Use common sense, do not 'rm -rf /' as root for example. 
If you have any questions then do not hesitate to contact me.

See https://raymii.org/s/static/About.html for details.