I'm writing a template class that uses a std::multimap as a member, and getting compile errors.
LocTree.h:
#pragma once
#include <map>
template <class Loc, class T>
class LocTree
{
public :
typedef std::multimap<typename Loc, typename T> TreeType;
LocTree( void );
~LocTree( void ) { };
private :
TreeType db;
};
LocTree.cpp:
#include "StdAfx.h"
#include "LocTree.h"
LocTree< class Loc, class T>::LocTree()
{
}
The compile error (from VC2005) :
Error 1 error C2079: 'std::pair<_Ty1,_Ty2>::first' uses undefined class 'Loc' c:\program files (x86)\microsoft visual studio 8\vc\include\utility 53
Error 2 error C2079: 'std::pair<_Ty1,_Ty2>::second' uses undefined class 'T' c:\program files (x86)\microsoft visual studio 8\vc\include\utility 54
I know I could put the function definitions in the .h but I'm hoping to keep them separate, if it's legal to do so. How do I fix this (probably newbie) problem?
Your constructor definition should be:
template<class Loc, class T>
LocTree<Loc,T>::LocTree()
{
}
Also, hoping to keep them separate... - don't - you're wasting your time. The only way to keep them separate is to have a definition in a different header which you also include. So, technically, they are separate, but the implementation is still visible.
Two points. The first is: what is:
typedef std::multimap<typename Loc, typename T> TreeType;
supposed to mean? I don't see what the typename are doing in there; I
think you just want:
typedef std::multimap<Loc, T> TreeType;
Second, when defining a member function of a class template outside of the
class, the syntax is:
template <typename Loc, typename T>
LocTree<Loc, T>::LocTree()
{
}
In other words, you have to repeat the template<...> clause. (Whether
you use typename or class in the <...> is indifferent. Since it
doesn't have to be a class, Most people I know prefer typename, since
this corresponds closer to what is meant.)
As for keeping the implementation separate: templates in C++ are
somewhat broken in this respect. You can't avoid the compiler
dependency. You still do want to keep the implementation separate from
the definition, however. The usual technique is to put the template
implementation in a separate file (.tcc, for example), and include
this from the header.
Keeping the implementation of a template separate is not a trivial thing to do.
In general it cannot be done. That is, it cannot be done where the templated parameters may be "anything".
For a specific limited subset of templated parameters it is possible to do, for example if you have a template like:
template< bool B > class Foo;
You can then specify:
extern template class Foo<true>;
extern template class Foo<false>;
and this is called "instantiating" the templates, and specifying to the compiler that there are implementations for values true and false, implemented elsewhere.
This can also be done where the templated parameters are types and are limited to a specific subset.
Within the compilation unit you then define the template implementations and then instantiate the templates once again using the same as above but without the word "extern".
I have done this in production code in a case where you are creating a member function to set a parameter value for a database stored-procedure call where only a very limited subset of parameter types are permitted. If your types are a very limited subset then go ahead and do the same if this helps decouple the code and hide a lot of implementation detail (in the case where the implementation is then done in a database, it is well worth doing).
There is an "in-between" ground where you provide the implementation in another header, often I have seen _i.h or similar for this convention and then you instantiate the templates in ones, including this header only when necessary. Thus if you create a class Foo then in the header use the "extern" declaration for my foo class in Foo.h and in Foo.cpp, #include the _i.h file for the implementation and the instantiation.
As for the syntax, in the template implementation file use:
template<class Loc, class T>
LocTree<Loc,T>::method(...)
{
...
}
Related
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.
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.
I understand that template definitions should be put in the header file. Does this mean that all the definitions of the classes that the template uses (directly or indirectly) need to be put in the header files as well?
I have a template that has a lot of classes it depends on and thus have to put them all in the header file otherwise I will get "error LNK2019: unresolved external symbol ". Is there a better solution in terms of code organisation?
Example:
double inline MainFunction(double price, const Params& params)
{
Price<ModeEnum::NORMAL> pricer(price);
MethodOne<ModeEnum::NORMAL> methodOne;
return pricer.func(methodOne, params) ;
}
template<ModelEnum::Enum Mode>
struct Price
{
double price;
typedef double return_type;
Price(double price_) : price(price_){}
template<typename T> double func(const T& method, const Params& params) const
{
const typename T::PriceFactor factor(params);
return factor ..... ;
}
};
T::PriceFactor is actually class B that is a type definition defined in the tempalte MethodOne. Because of this, I have to put the constructor of class B and all (a lot) the functions and class that it uses in the header file.
The simple answer is this: all code needs to be visible to the compiler when the template gets instantiated. If the code isn't visible, the compiler won't do the instantiation and you'll need to provide an explicit instantiation. Whether an explicit instantiation is viable, depends on the nature of your template:
Templates which are applicable to many types, e.g., something like std::vector<T> probably want to be implemented entirely in a header. You may separate the declaration and the definition of function templates but there isn't much point in putting the parts into different files.
Templates which are applicable to few types, e.g., std::basic_ostream<cT> which is instantiated with char, wchar_t and maybe at some point with char16_t and char32_t probably want to be declared in a header and defined in another header which is not included automatically. Instead the header with the definitions is included only in special instantiation files where the class templates are explicitly instantiated.
Some templates give classes with different properties the same interface. That used to be the case with std::complex<T> which could be instantiated with float, double, and long double. For templates like these the header would only include the declarations and the definitions would go into a suitable translation unit.
One theme which is orthogonal to the above discussion is factoring out common parts, ideally into non-templates are into templates with fewer instantiations: it may very well be possible to take a very general interface but implement it in terms of a much more restrictive interface at the cost of somehow bridging the gap as part of the template implementation. In that case the "interesting" implementation may go into a source file rather than a header and the templates in the interface just adapt the passed in types to the actual implementation.
When mentioning above that code would be place into a source file this, obviously only applies to non-trivial code: simple forwarding functions probably should stay inline functions for performance reasons. However, these tend not to be the interesting function templates causing lots of dependencies.
For a more complete write-up on how to organize template code see this blog entry.
If its simple, I just put it all in one header:
//simple_template.h
#ifndef SIMPLE_TEMPLATE_H
#define SIMPLE_TEMPLATE_H
template <typename T>
class SomethingSimple
{
public:
T foo() { return T();}
};
#endif
If it is more complicated, I create an "inline header" (and use the naming convention from the google style guide) to get:
//complicated_template.h
#ifndef COMPLICATED_TEMPLATE_H
#define COMPLICATED_TEMPLATE_H
template <typename T>
class SomethingComplicated
{
public:
T foo();
};
#include "compilcated_template-inl.h"
#endif
//compilcated_template-inl.h
#ifndef COMPLICATED_TEMPLATE_INL_H
#define COMPLICATED_TEMPLATE_INL_H
#include "complicated_template.h"
template <typename T>
T SomethingComplicated<T>::foo() {/*lots of code here*/; return T();}
#endif
This way, complicated_template.h is pretty readable, but anyone who uses the template can just include that header. For example,
//uses_template.h
#ifndef USES_TEMPLATE_H
#define USES_TEMPLATE_H
#include "complicated_template.h"
class something_using_complicated
{
private:
SomethingComplicated<int> something_;
};
Note: if the classes that use the template are also template classes then you're stuck with a header only library. This is why BOOST is mostly headers.
Suppose I've written class template declaration somewhere in collector.h:
template <class T, int maxElements>
class collector {
T elements[maxElements];
int activeCount;
public:
collector();
void process();
void draw();
};
and implementing its three methods in collector.cpp:
template <class T, int maxElements>
collector<T, maxElements>::collector(){
//code here
}
template <class T, int maxElements>
void collector<T, maxElements>::process(){
//code here
}
template <class T, int maxElements>
void collector<T, maxElements>::draw(){
//code here
}
Is there any way of not writing template <class T, int maxElements> and <T, maxElements>
for every function's implementation? Something like that:
template <class T, int maxElements>{
collector<T, maxElements>::collector(){
//code here
}
void collector<T, maxElements>::process(){
//code here
}
void collector<T, maxElements>::draw(){
//code here
}
}
Put the code inside the class definition in the header file.
[You'll probably wind up doing this anyway as soon as you try to build code that uses this class template. See here for background esp. the neglected answer from #Pavel Minaev.]
Nope, you gotta write the template header every time.
Typically, people implement template classes directly inline. They have to have their full source exposed to be used (unless you explicitly instantiate the lot, anyway) so there's little point doing otherwise.
Is there any way of not writing template and for every function's implementation?
No, short of defining template members inline in the class template's definition, there is no way to do that.
The direct answer to your question has been answered by many above.
To know more on whats the best practice, refer to chapter 6 of C++ Templates - The complete guide book. It talks about which is the best place to declare and/or define template class, functions, member functions: in a .h/hpp or .cpp files.
There's always copy & paste!
Unless you have a smart C++ template-aware linker closely coupled to your compiler, you'll have to put the code in-line in the header in any case and the problem goes away. You'll want to do that in any case if the code needs to be portable.
If you really must then there is the somewhat perverse pre-processor macro solution:
#define COLLECTOR_TEMPLATE template <class T, int maxElements>
Explicitly instantiate for all the types you expect to need in the .cpp file so the compiler can generate the code a priori the linker will match the references templkates to the pre-instantiated definitions (see http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13. You will however not be able to instantiate the template for new types.
For separate compilation of templates to work for arbitrarily instantiated classes, the compiler would have to embed the template source in the object file, then when the linker requires a particular instantiation to resolve a reference, it must then extract that source and pass it back to the compiler to generate the instantiated object code, which is then passed back to the linker. This requires the compiler and linker to work hand-in-glove, and for an object file format that supports template source embedding.
Most tool-chains do not support that, so you must either use in-line definition in the header, restrict use of the template to the same source file in which it is defined, or #include the .cpp containing the definition; all three of these are effectively the same thing - making the complete template definition visible to the compiler in a single compilation unit, but the first is the most conventional and flexible solution.
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.