I have a class Base in base.h, which has a template function
class Base {
template <typename T> void test(T a);
}
this template is supposed to read in int or double type, and I have class Derived, which is derived from class Base
I tried to call function test in class Derived, but I have the linker error.
In the end, I realised that if in base.cpp, I add
void test(int a);
void test(double a);
there will be no compiler error. This solution seems awkward, is there a better solution? Thank you
C++ templates must be defined (given a complete function body) in the same translation unit (.CPP file plus all included header files) where they are used. In your header file, all you have done is declared (given the name and signature of) the function. The result is that when you include base.h, all the compiler sees is:
class Base {
template <typename T> void test(T a);
}
This declares but does not define the function. To define it, you must include a function body:
class Base {
template <typename T> void test(T a)
{
// do something cool with a here
}
}
The reason why this is required is that the C++ compiler generates code for templates on an "as-needed" basis. For example, if you call:
Base obj;
obj.test< int >( 1 );
obj.test< char >( 'c' );
The compiler will generate two sets of machine code based on the Base::test template, one for an int and one for a char. The limitation here is that the definition of the Base::test template must be in the same translation unit (.CPP file), or else the compiler will not know how to build the machine code for each version of the Base::test function. The compiler only operates on one translation unit at a time, so it has no idea whether or not you've defined Base::test< T > in some other CPP file. It can only work with what it has at hand.
This is quite different from the way generics work in C#, Java, and similar languages. Personally I like to think of templates as a text macro that gets expanded by the compiler as needed. That forces me to keep in mind that the complete body of the template function needs to be included in any CPP file where it is used.
You must fully define the template function test before it can be used. The easiest way to do that is just to write your function body in the header in base.h:
class Base {
template <typename T> void test(T a)
{
... function body here
}
}
if you declare template function in base class which means it take the template argument at compile time but if u try to access through derived class which is runtime implementation so template request at compile time which ur providing at runtime is not possible ,and main thing c++ does not support this.
Related
I have some header file with declared template class and template function:
print.h:
template<typename T> struct Printer {
static void print();
};
template<typename T> void print();
In the implementation file, I have some base implementation of Printer, some specializations of it, and implementation of the function print that calls Printer<T>::print.
print.cpp
template<typename T> void Printer<T>::print() {
cout << "base";
}
template<> struct Printer<int> {
static void print() {
cout << "int";
}
};
template<> struct Printer<bool> {
static void print() {
cout << "bool";
}
};
template<typename T> void print() {
return Printer<T>::print();
}
In another file, I add one more specialization of Printer and a call of function print after it.
another.cpp
template<> struct Printer<char> {
static void print() {
cout << "char";
}
};
void printChar() {
print<char>();
}
Which Printer<T>::print does printChar call? Base or specialization Printer<char>? Can I change the behavior of printChar in this way?
(print.cpp is compiled first)
I compiled this code in a single file in the same order and called printChar. The output is 'char'. But I am not sure that it will work in different files as I described. Because for me it looks like it opens the ability to extend existing code by something like a cheating injection. But maybe it is OK to practice (Swift is based on a similar kind of extensions). If it works, Is it ok to practice it?
I'm not sure which previous usages you're referring to. I see only one usage of print<char>, after the specialization of print<char>.
Templates work kind of like #define, they stamp out definitions on-demand as needed. So the right template specialization definition had better be available at the time the code needs to be stamped out, which by the way takes place independently per TU. And these definitions must be identical across TU's.
See [temp.expl.spec]/pp.6-7:
6 If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.
7 The placement of explicit specialization declarations ... can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.
So as long as print<char> is instantiated after the specialization of print<char> in every translation unit where it is used (including implicit instantiations), the program is fine. The printChar() case is OK. But if print<char> happens to be instantiated in any other TU, the program would become ill-formed NDR.
For this reason all specializations are usually bundled (included) in the same header file that declares the primary template. It might increase compile times but can save a lot of headache during program development and maintenance later on.
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.
this might be question that someone asked before but i can't find it...
i have a class in a .hpp file :
class A{
public:
A(){//constructor}
~A(){//destructor}
//some public methods and arguments
template<typename Type>
void func(Type t){//do something for numbers}
private:
//some private methods and arguments
}
The template method should work for int, double... but not for string. Thus in my .hpp file, I defined what func does for numbers and in my .cpp file I wrote :
template<>
void A::func(std::string t){ // do something in that case}
But when I use the function func with std::string, the program calls the methods for numbers... So I replaced the .hpp file by :
class A{
public:
A(){//constructor}
~A(){//destructor}
//some public methods and arguments
template<typename Type>
void func(Type t){//do something for numbers}
void func(std::string s);
private:
//some private methods and arguments
}
and my .cpp file became :
void A::func(std::string t){ // do something in that case}
and then everything works !
my question is, is this the correct way to do that ?
That's not a partial specialization (there are no template parameters left un-specialized) it's an explicit specialization.
Templates must be visible to the code that uses them, if you don't declare the specialization in the header file then code that tries to call A::func with a string will instantiate the primary template (the one for numbers) and use that, because they don't know the `string specialization even exists.
So you must (at least) declare the specialization in the header in order for it to be usable outsde the .cpp file:
template<>
void A::func(std::string t);
However your alternative using an overload is simpler and is perfectly acceptable. It works because the overload for string is declared in the header, so code that calls it knows which function to call.
Overloading is a good approach for many purposes. However, I suspect your original template approach could be made to work too if you add a specialization for const char * as well. That way, you could pass in string literals without it resolving to the numbers version.
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.