Include header file of template type - c++

I'm writing a template class, let's say
template <class T>
class bla {
bla() ;
~bla() ;
};
template <class T>
bla<t>::bla(){}
template <class T>
b<t>::~b(){}
This works fine as long as T is int, char, and so on ... but in case that it will be a custom class MyClass, it will requiere the headerfile MyClass.h to be included, or am I wrong?
Question: How can this be done in a template-ish way, i.e. something like
#include "T.h"
Cheers!

When you use bla<MyClass> you need to have included the definition of bla and the definition of MyClass. It isn't necessary that MyClass is known when bla is defined. The magic about this is called "two-phase name look-up": while compiling the template definition all names not depending on the template parameter are looked up. During the second phase, when the template is instantiated, all remaining names are looked up in the context of the instantiation.

Well, it is the other way round. If you have a class MyClass that you want to use in one of your modules (translation units in C++), then you will include the template container (the source code you put above, lets name it container.h), and then create the data structure.
// main.cpp
#include "container.h"
#include "myclass.h"
int main()
{
bla<MyClass> foo;
// lots of more things...
}
Maybe the problem is that you don not know how to divide your code in modules. A simple rule of thumb is to put each class in a single module, each module with a .h file (the interface, in which all declaration lie), and the .cpp file (the implementation file, where roughly you write the inside of methods).
Hope this helps.

Related

best practices: include .cpp file in main instead of .h file when using templates? [duplicate]

I have some template code that I would prefer to have stored in a CPP file instead of inline in the header. I know this can be done as long as you know which template types will be used. For example:
.h file
class foo
{
public:
template <typename T>
void do(const T& t);
};
.cpp file
template <typename T>
void foo::do(const T& t)
{
// Do something with t
}
template void foo::do<int>(const int&);
template void foo::do<std::string>(const std::string&);
Note the last two lines - the foo::do template function is only used with ints and std::strings, so those definitions mean the app will link.
My question is - is this a nasty hack or will this work with other compilers/linkers? I am only using this code with VS2008 at the moment but will be wanting to port to other environments.
The problem you describe can be solved by defining the template in the header, or via the approach you describe above.
I recommend reading the following points from the C++ FAQ Lite:
Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file?
How can I avoid linker errors with my template functions?
How does the C++ keyword export help with template linker errors?
They go into a lot of detail about these (and other) template issues.
For others on this page wondering what the correct syntax is (as did I) for explicit template specialisation (or at least in VS2008), its the following...
In your .h file...
template<typename T>
class foo
{
public:
void bar(const T &t);
};
And in your .cpp file
template <class T>
void foo<T>::bar(const T &t)
{ }
// Explicit template instantiation
template class foo<int>;
Your example is correct but not very portable.
There is also a slightly cleaner syntax that can be used (as pointed out by #namespace-sid, among others).
However, suppose the templated class is part of some library that is to be shared...
Should other versions of the templated class be compiled?
Is the library maintainer supposed to anticipate all possible templated uses of the class?
An Alternate Approach
Add a third file that is the template implementation/instantiation file in your sources.
lib/foo.hpp - from library
#pragma once
template <typename T>
class foo {
public:
void bar(const T&);
};
lib/foo.cpp - compiling this file directly just wastes compilation time
// Include guard here, just in case
#pragma once
#include "foo.hpp"
template <typename T>
void foo::bar(const T& arg) {
// Do something with `arg`
}
foo.MyType.cpp - using the library, explicit template instantiation of foo<MyType>
// Consider adding "anti-guard" to make sure it's not included in other translation units
#if __INCLUDE_LEVEL__
#error "Don't include this file"
#endif
// Yes, we include the .cpp file
#include <lib/foo.cpp>
#include "MyType.hpp"
template class foo<MyType>;
Organize your implementations as desired:
All implementations in one file
Multiple implementation files, one for each type
An implementation file for each set of types
Why??
This setup should reduce compile times, especially for heavily used complicated templated code, because you're not recompiling the same header file in each
translation unit.
It also enables better detection of which code needs to be recompiled, by compilers and build scripts, reducing incremental build burden.
Usage Examples
foo.MyType.hpp - needs to know about foo<MyType>'s public interface but not .cpp sources
#pragma once
#include <lib/foo.hpp>
#include "MyType.hpp"
// Declare `temp`. Doesn't need to include `foo.cpp`
extern foo<MyType> temp;
examples.cpp - can reference local declaration but also doesn't recompile foo<MyType>
#include "foo.MyType.hpp"
MyType instance;
// Define `temp`. Doesn't need to include `foo.cpp`
foo<MyType> temp;
void example_1() {
// Use `temp`
temp.bar(instance);
}
void example_2() {
// Function local instance
foo<MyType> temp2;
// Use templated library function
temp2.bar(instance);
}
error.cpp - example that would work with pure header templates but doesn't here
#include <lib/foo.hpp>
// Causes compilation errors at link time since we never had the explicit instantiation:
// template class foo<int>;
// GCC linker gives an error: "undefined reference to `foo<int>::bar()'"
foo<int> nonExplicitlyInstantiatedTemplate;
void linkerError() {
nonExplicitlyInstantiatedTemplate.bar();
}
Note: Most compilers/linters/code helpers won't detect this as an error, since there is no error according to C++ standard.
But when you go to link this translation unit into a complete executable, the linker won't find a defined version of foo<int>.
Alternate approach from: https://stackoverflow.com/a/495056/4612476
This code is well-formed. You only have to pay attention that the definition of the template is visible at the point of instantiation. To quote the standard, § 14.7.2.4:
The definition of a non-exported function template, a non-exported member function template, or a non-exported member function or static data member of a class template shall be present in every translation unit in which it is explicitly instantiated.
This should work fine everywhere templates are supported. Explicit template instantiation is part of the C++ standard.
That is a standard way to define template functions. I think there are three methods I read for defining templates. Or probably 4. Each with pros and cons.
Define in class definition. I don't like this at all because I think class definitions are strictly for reference and should be easy to read. However it is much less tricky to define templates in class than outside. And not all template declarations are on the same level of complexity. This method also makes the template a true template.
Define the template in the same header, but outside of the class. This is my preferred way most of the times. It keeps your class definition tidy, the template remains a true template. It however requires full template naming which can be tricky. Also, your code is available to all. But if you need your code to be inline this is the only way. You can also accomplish this by creating a .INL file at the end of your class definitions.
Include the header.h and implementation.CPP into your main.CPP. I think that's how its done. You won't have to prepare any pre instantiations, it will behave like a true template. The problem I have with it is that it is not natural. We don't normally include and expect to include source files. I guess since you included the source file, the template functions can be inlined.
This last method, which was the posted way, is defining the templates in a source file, just like number 3; but instead of including the source file, we pre instantiate the templates to ones we will need. I have no problem with this method and it comes in handy sometimes. We have one big code, it cannot benefit from being inlined so just put it in a CPP file. And if we know common instantiations and we can predefine them. This saves us from writing basically the same thing 5, 10 times. This method has the benefit of keeping our code proprietary. But I don't recommend putting tiny, regularly used functions in CPP files. As this will reduce the performance of your library.
Note, I am not aware of the consequences of a bloated obj file.
Let's take one example, let's say for some reason you want to have a template class:
//test_template.h:
#pragma once
#include <cstdio>
template <class T>
class DemoT
{
public:
void test()
{
printf("ok\n");
}
};
template <>
void DemoT<int>::test()
{
printf("int test (int)\n");
}
template <>
void DemoT<bool>::test()
{
printf("int test (bool)\n");
}
If you compile this code with Visual Studio - it works out of box.
gcc will produce linker error (if same header file is used from multiple .cpp files):
error : multiple definition of `DemoT<int>::test()'; your.o: .../test_template.h:16: first defined here
It's possible to move implementation to .cpp file, but then you need to declare class like this -
//test_template.h:
#pragma once
#include <cstdio>
template <class T>
class DemoT
{
public:
void test()
{
printf("ok\n");
}
};
template <>
void DemoT<int>::test();
template <>
void DemoT<bool>::test();
// Instantiate parametrized template classes, implementation resides on .cpp side.
template class DemoT<bool>;
template class DemoT<int>;
And then .cpp will look like this:
//test_template.cpp:
#include "test_template.h"
template <>
void DemoT<int>::test()
{
printf("int test (int)\n");
}
template <>
void DemoT<bool>::test()
{
printf("int test (bool)\n");
}
Without two last lines in header file - gcc will work fine, but Visual studio will produce an error:
error LNK2019: unresolved external symbol "public: void __cdecl DemoT<int>::test(void)" (?test#?$DemoT#H##QEAAXXZ) referenced in function
template class syntax is optional in case if you want to expose function via .dll export, but this is applicable only for windows platform - so test_template.h could look like this:
//test_template.h:
#pragma once
#include <cstdio>
template <class T>
class DemoT
{
public:
void test()
{
printf("ok\n");
}
};
#ifdef _WIN32
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT
#endif
template <>
void DLL_EXPORT DemoT<int>::test();
template <>
void DLL_EXPORT DemoT<bool>::test();
with .cpp file from previous example.
This however gives more headache to linker, so it's recommended to use previous example if you don't export .dll function.
This is definitely not a nasty hack, but be aware of the fact that you will have to do it (the explicit template specialization) for every class/type you want to use with the given template. In case of MANY types requesting template instantiation there can be A LOT of lines in your .cpp file. To remedy this problem you can have a TemplateClassInst.cpp in every project you use so that you have greater control what types will be instantiated. Obviously this solution will not be perfect (aka silver bullet) as you might end up breaking the ODR :).
There is, in the latest standard, a keyword (export) that would help alleviate this issue, but it isn't implemented in any compiler that I'm aware of, other than Comeau.
See the FAQ-lite about this.
Yes, that's the standard way to do specializiation explicit instantiation. As you stated, you cannot instantiate this template with other types.
Edit: corrected based on comment.
None of above worked for me, so here is how y solved it, my class have only 1 method templated..
.h
class Model
{
template <class T>
void build(T* b, uint32_t number);
};
.cpp
#include "Model.h"
template <class T>
void Model::build(T* b, uint32_t number)
{
//implementation
}
void TemporaryFunction()
{
Model m;
m.build<B1>(new B1(),1);
m.build<B2>(new B2(), 1);
m.build<B3>(new B3(), 1);
}
this avoid linker errors, and no need to call TemporaryFunction at all
Time for an update! Create an inline (.inl, or probably any other) file and simply copy all your definitions in it. Be sure to add the template above each function (template <typename T, ...>). Now instead of including the header file in the inline file you do the opposite. Include the inline file after the declaration of your class (#include "file.inl").
I don't really know why no one has mentioned this. I see no immediate drawbacks.
There is nothing wrong with the example you have given. But i must say i believe it's not efficient to store function definitions in a cpp file. I only understand the need to separate the function's declaration and definition.
When used together with explicit class instantiation, the Boost Concept Check Library (BCCL) can help you generate template function code in cpp files.

How to use a class as parameter in templates in C++

A:
I use something like this:
In Class1.h:
template <class T>
class Class1 : Database {
public:
Class1();
};
In Class1.cpp:
#include "Class1.h"
template <typename T>
Class1<T>::Class1(){
//Some code
}
Calling class:
#include "Class1.h"
Class1<Class2> *class1 = new Class1<Class2>();
If i run this, the linker is not able to find "Class1".
B:
When i use something like this:
#include "Class1.h"
template <> Class1<Class2>::Class1(){}
The linker is able to find it.
My problem is, that i need to use A in my code and not B.
That means i don't want to use:
template <> Class1<Class2>::Class1(){}
I Want to use ONLY:
template <typename T>
Class1<T>::Class1(){
//Some code
}
All tutorials say that i use it correctly and it has to work. Can anybody help me?
When you try to instantiate a specialization of a class template, the compiler needs to have access to every member definition, otherwise it is unable to generate the corresponding code (a C++ template is basically a copypasta factory on steroids).
Since you split the implementation details into a separate file, you cannot instantiate your specific specialization a.k.a. Class1<Class2>. I suppose you put the template <> Class1<Class2>::Class1() {} bit in the header file? If so, your code compiles because it has a full specialization for Class2 with an available constructor when you use it in your sample.
Schematically you have:
Template Header -> included in -> test sample cpp file
\-----------------------> included in -> Template Implementation cpp file
You can see that all the actual implementations for your template are not reachable within your test sample translation unit.
As said in comments, Class1 is a templated class, so you should put you contructor in the header file, not in a separated cpp file.
Otherwise, you can put the constructor in the cpp file where you use it, but only if you use it only in a single cpp file.
The problem is that when you write
Class1<Class2> *class1 = new Class1<Class2>();
you're asking the compiler to call (and construct) a constructor for Class1<Class2> but the compiler don't know how to construct it because it's defined in another file (the compiler, in this phase, see only "Class1.h"; doesn't know the content of "Class1.cpp").
Your solution B
template <> Class1<Class2>::Class1(){}
works because you're defining a constructor specialization for Class1<Class2>, so the compiler know it
Solution: delete
template <typename T>
Class1<T>::Class1(){
//Some code
}
from "Class1.cpp" and put it in "Class1.h".
p.s.: sorry for my bad English.

Template instantiaton in multiple files

I am currently implementing generic string related template class that does a lot of complex things. To optimize compile times I thought about implementing the functionality inside translation unit instead of header file and then instantiating types for UTF-8, UTF-16 and UTF-32. The bottleneck that I'm trying to figure out is, if it's possible to split the template class instantiating into multiple translation units, since what one group of member functions does is very complex code and it would make a lot of sense to separate that into it's own translation unit.
Here's example what I'm trying to do:
example.h
template <typename T>
class Example
{
public:
void test1();
void test2();
};
example_test1.cpp
template <typename T>
void Example::test1()
{
...
}
template class Example<uint8_t>;
template class Example<uint16_t>;
template class Example<uint32_t>;
example_test2.cpp
template <typename T>
void Example::test2()
{
...
}
template class Example<uint8_t>;
template class Example<uint16_t>;
template class Example<uint32_t>;
Obvious (and hacky) solution would be to create mini "unity build" that includes example_test1.cpp and example_test2.cpp, but that's bit cheap way to do it and there would be only one translation unit. I wonder if there's any better solution?
EDIT: And please, if your answer is to "put it inside header", then don't. That's not helping. The idea here is to optimize compile time by removing stuff from headers that doesn't need to be there. Our compile time is already very high because of the excessive usage of templates in headers. And also I don't need tips about how to optimize compile times using other ways. I know how to use precompiled headers, etc. If I could just get answers that are on topic.
What you are trying to do is called explicit instantiation and the correct syntax is following:
template class Example<uint8_t>;
template class Example<uint16_t>;
template class Example<uint32_t>;
If you really need to distinguish the methods into separate files, I would create a file example_instances.cpp for the code above, just to have it only once in the sources for better manageability. The code would be organized in the following way:
example.h
template <typename T>
class Example
{
public:
void test1();
void test2();
};
example_test1.cpp
#include "example.h"
template <typename T>
void Example::test1()
{
...
}
#include "example_instances.cpp"
example_test2.cpp
#include "example.h"
template <typename T>
void Example::test2()
{
...
}
#include "example_instances.cpp"
If you are discouraged from including .cpp files, put the instances into a separate header file. However, this one should be included after implementation unlike common header files (explicit instantiation of function template fails (g++)).
So you are trying to do compiller job. There is no instantation of member function of template classes if there is no call. So it is useless to define them in different translation units. Compiller do it without you and better than you. My advice is to put all your code into header file.

Defining methods of class with template parameters

File main2.cpp:
#include "poly2.h"
int main(){
Poly<int> cze;
return 0;
}
File poly2.h:
template <class T>
class Poly {
public:
Poly();
};
File poly2.cpp:
#include "poly2.h"
template<class T>
Poly<T>::Poly() {
}
Error during compilation:
src$ g++ poly2.cpp main2.cpp -o poly
/tmp/ccXvKH3H.o: In function `main':
main2.cpp:(.text+0x11): undefined reference to `Poly<int>::Poly()'
collect2: ld returned 1 exit status
I'm trying to compile above code, but there are errors during compilation. What should be fixed to compile constructor with template parameter?
The full template code must appear in one file. You cannot separate interface and implementation between multiple files like you would with a normal class. To get around this, many people write the class definition in a header and the implementation in another file, and include the implementation at the bottom of the header file. For example:
Blah.h:
#ifndef BLAH_H
#define BLAH_H
template<typename T>
class Blah {
void something();
};
#include "Blah.template"
#endif
Blah.template:
template<typename T>
Blah<T>::something() { }
And the preprocessor will do the equivalent of a copy-paste of the contents of Blah.template into the Blah.h header, and everything will be in one file by the time the compiler sees it, and everyone's happy.
If you use templates in C++, all implementations of functions that use templates need to be inside your header file. Or your compiler can't find the right (or any) version for a type.
See this questions for details.
The age old question of how do I define my template classes. A template isn't actually code, it is a template that you use to define code later. So, there are two possible solutions, if you know that there are only certain types of Poly that you are going to use, you can define them in the .cpp file.
#include "poly2.h"
Poly<int>;
template<class T>
Poly<T>::Poly() {
}
Or you can put all of the template definitions and declarations inside your header file. What I like to do is create a separate .hpp file and put the definitions in there. So I would do this:
poly2.h
template <class T>
class Poly {
public:
Poly();
};
#include "poly2-impl.hpp"
poly2-impl.hpp
template<class T>
Poly<T>::Poly() {
}
And the thing about templates is that you can include the header file in multiple translation files without previously defined errors.
See here for more information: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12
Usually, all you need to compile a source file is a bunch of function declarations, and you can link in the definitions later.
Unfortunately it's not quite that simple when templates come into the mix. Because templates must be instantiated when used, their definitions must be visible when used. main2.cpp cannot see the definition of Poly<int>::Poly(), so this function is not instantiated. It is thus missing from the object file and not linkable.
You should write function templates in header files so that they are available in all Translation Units in which you use them. It's not ideal, but without export (or performing explicit instantiation), there's not a whole lot you can do about it.

Storing C++ template function definitions in a .CPP file

I have some template code that I would prefer to have stored in a CPP file instead of inline in the header. I know this can be done as long as you know which template types will be used. For example:
.h file
class foo
{
public:
template <typename T>
void do(const T& t);
};
.cpp file
template <typename T>
void foo::do(const T& t)
{
// Do something with t
}
template void foo::do<int>(const int&);
template void foo::do<std::string>(const std::string&);
Note the last two lines - the foo::do template function is only used with ints and std::strings, so those definitions mean the app will link.
My question is - is this a nasty hack or will this work with other compilers/linkers? I am only using this code with VS2008 at the moment but will be wanting to port to other environments.
The problem you describe can be solved by defining the template in the header, or via the approach you describe above.
I recommend reading the following points from the C++ FAQ Lite:
Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file?
How can I avoid linker errors with my template functions?
How does the C++ keyword export help with template linker errors?
They go into a lot of detail about these (and other) template issues.
For others on this page wondering what the correct syntax is (as did I) for explicit template specialisation (or at least in VS2008), its the following...
In your .h file...
template<typename T>
class foo
{
public:
void bar(const T &t);
};
And in your .cpp file
template <class T>
void foo<T>::bar(const T &t)
{ }
// Explicit template instantiation
template class foo<int>;
Your example is correct but not very portable.
There is also a slightly cleaner syntax that can be used (as pointed out by #namespace-sid, among others).
However, suppose the templated class is part of some library that is to be shared...
Should other versions of the templated class be compiled?
Is the library maintainer supposed to anticipate all possible templated uses of the class?
An Alternate Approach
Add a third file that is the template implementation/instantiation file in your sources.
lib/foo.hpp - from library
#pragma once
template <typename T>
class foo {
public:
void bar(const T&);
};
lib/foo.cpp - compiling this file directly just wastes compilation time
// Include guard here, just in case
#pragma once
#include "foo.hpp"
template <typename T>
void foo::bar(const T& arg) {
// Do something with `arg`
}
foo.MyType.cpp - using the library, explicit template instantiation of foo<MyType>
// Consider adding "anti-guard" to make sure it's not included in other translation units
#if __INCLUDE_LEVEL__
#error "Don't include this file"
#endif
// Yes, we include the .cpp file
#include <lib/foo.cpp>
#include "MyType.hpp"
template class foo<MyType>;
Organize your implementations as desired:
All implementations in one file
Multiple implementation files, one for each type
An implementation file for each set of types
Why??
This setup should reduce compile times, especially for heavily used complicated templated code, because you're not recompiling the same header file in each
translation unit.
It also enables better detection of which code needs to be recompiled, by compilers and build scripts, reducing incremental build burden.
Usage Examples
foo.MyType.hpp - needs to know about foo<MyType>'s public interface but not .cpp sources
#pragma once
#include <lib/foo.hpp>
#include "MyType.hpp"
// Declare `temp`. Doesn't need to include `foo.cpp`
extern foo<MyType> temp;
examples.cpp - can reference local declaration but also doesn't recompile foo<MyType>
#include "foo.MyType.hpp"
MyType instance;
// Define `temp`. Doesn't need to include `foo.cpp`
foo<MyType> temp;
void example_1() {
// Use `temp`
temp.bar(instance);
}
void example_2() {
// Function local instance
foo<MyType> temp2;
// Use templated library function
temp2.bar(instance);
}
error.cpp - example that would work with pure header templates but doesn't here
#include <lib/foo.hpp>
// Causes compilation errors at link time since we never had the explicit instantiation:
// template class foo<int>;
// GCC linker gives an error: "undefined reference to `foo<int>::bar()'"
foo<int> nonExplicitlyInstantiatedTemplate;
void linkerError() {
nonExplicitlyInstantiatedTemplate.bar();
}
Note: Most compilers/linters/code helpers won't detect this as an error, since there is no error according to C++ standard.
But when you go to link this translation unit into a complete executable, the linker won't find a defined version of foo<int>.
Alternate approach from: https://stackoverflow.com/a/495056/4612476
This code is well-formed. You only have to pay attention that the definition of the template is visible at the point of instantiation. To quote the standard, § 14.7.2.4:
The definition of a non-exported function template, a non-exported member function template, or a non-exported member function or static data member of a class template shall be present in every translation unit in which it is explicitly instantiated.
This should work fine everywhere templates are supported. Explicit template instantiation is part of the C++ standard.
That is a standard way to define template functions. I think there are three methods I read for defining templates. Or probably 4. Each with pros and cons.
Define in class definition. I don't like this at all because I think class definitions are strictly for reference and should be easy to read. However it is much less tricky to define templates in class than outside. And not all template declarations are on the same level of complexity. This method also makes the template a true template.
Define the template in the same header, but outside of the class. This is my preferred way most of the times. It keeps your class definition tidy, the template remains a true template. It however requires full template naming which can be tricky. Also, your code is available to all. But if you need your code to be inline this is the only way. You can also accomplish this by creating a .INL file at the end of your class definitions.
Include the header.h and implementation.CPP into your main.CPP. I think that's how its done. You won't have to prepare any pre instantiations, it will behave like a true template. The problem I have with it is that it is not natural. We don't normally include and expect to include source files. I guess since you included the source file, the template functions can be inlined.
This last method, which was the posted way, is defining the templates in a source file, just like number 3; but instead of including the source file, we pre instantiate the templates to ones we will need. I have no problem with this method and it comes in handy sometimes. We have one big code, it cannot benefit from being inlined so just put it in a CPP file. And if we know common instantiations and we can predefine them. This saves us from writing basically the same thing 5, 10 times. This method has the benefit of keeping our code proprietary. But I don't recommend putting tiny, regularly used functions in CPP files. As this will reduce the performance of your library.
Note, I am not aware of the consequences of a bloated obj file.
Let's take one example, let's say for some reason you want to have a template class:
//test_template.h:
#pragma once
#include <cstdio>
template <class T>
class DemoT
{
public:
void test()
{
printf("ok\n");
}
};
template <>
void DemoT<int>::test()
{
printf("int test (int)\n");
}
template <>
void DemoT<bool>::test()
{
printf("int test (bool)\n");
}
If you compile this code with Visual Studio - it works out of box.
gcc will produce linker error (if same header file is used from multiple .cpp files):
error : multiple definition of `DemoT<int>::test()'; your.o: .../test_template.h:16: first defined here
It's possible to move implementation to .cpp file, but then you need to declare class like this -
//test_template.h:
#pragma once
#include <cstdio>
template <class T>
class DemoT
{
public:
void test()
{
printf("ok\n");
}
};
template <>
void DemoT<int>::test();
template <>
void DemoT<bool>::test();
// Instantiate parametrized template classes, implementation resides on .cpp side.
template class DemoT<bool>;
template class DemoT<int>;
And then .cpp will look like this:
//test_template.cpp:
#include "test_template.h"
template <>
void DemoT<int>::test()
{
printf("int test (int)\n");
}
template <>
void DemoT<bool>::test()
{
printf("int test (bool)\n");
}
Without two last lines in header file - gcc will work fine, but Visual studio will produce an error:
error LNK2019: unresolved external symbol "public: void __cdecl DemoT<int>::test(void)" (?test#?$DemoT#H##QEAAXXZ) referenced in function
template class syntax is optional in case if you want to expose function via .dll export, but this is applicable only for windows platform - so test_template.h could look like this:
//test_template.h:
#pragma once
#include <cstdio>
template <class T>
class DemoT
{
public:
void test()
{
printf("ok\n");
}
};
#ifdef _WIN32
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT
#endif
template <>
void DLL_EXPORT DemoT<int>::test();
template <>
void DLL_EXPORT DemoT<bool>::test();
with .cpp file from previous example.
This however gives more headache to linker, so it's recommended to use previous example if you don't export .dll function.
This is definitely not a nasty hack, but be aware of the fact that you will have to do it (the explicit template specialization) for every class/type you want to use with the given template. In case of MANY types requesting template instantiation there can be A LOT of lines in your .cpp file. To remedy this problem you can have a TemplateClassInst.cpp in every project you use so that you have greater control what types will be instantiated. Obviously this solution will not be perfect (aka silver bullet) as you might end up breaking the ODR :).
There is, in the latest standard, a keyword (export) that would help alleviate this issue, but it isn't implemented in any compiler that I'm aware of, other than Comeau.
See the FAQ-lite about this.
Yes, that's the standard way to do specializiation explicit instantiation. As you stated, you cannot instantiate this template with other types.
Edit: corrected based on comment.
None of above worked for me, so here is how y solved it, my class have only 1 method templated..
.h
class Model
{
template <class T>
void build(T* b, uint32_t number);
};
.cpp
#include "Model.h"
template <class T>
void Model::build(T* b, uint32_t number)
{
//implementation
}
void TemporaryFunction()
{
Model m;
m.build<B1>(new B1(),1);
m.build<B2>(new B2(), 1);
m.build<B3>(new B3(), 1);
}
this avoid linker errors, and no need to call TemporaryFunction at all
Time for an update! Create an inline (.inl, or probably any other) file and simply copy all your definitions in it. Be sure to add the template above each function (template <typename T, ...>). Now instead of including the header file in the inline file you do the opposite. Include the inline file after the declaration of your class (#include "file.inl").
I don't really know why no one has mentioned this. I see no immediate drawbacks.
There is nothing wrong with the example you have given. But i must say i believe it's not efficient to store function definitions in a cpp file. I only understand the need to separate the function's declaration and definition.
When used together with explicit class instantiation, the Boost Concept Check Library (BCCL) can help you generate template function code in cpp files.