Implement template member of non-template class in cpp file - c++

I have a class:
// A.h
class A
{
void foo();
template <class T> void bar( T someVar );
}
#include "A.tcpp"
When I build it, I get linker errors. However, if the whole class would be a template, then the above example would build perfectly fine. So my question is:
How do I stick to the pattern of having ALL definitions in the cpp file, when having template member functions as opposed to having a template class?

If you are going to split a a class that has template functions and non template functions into a header file and a tcpp file then you only put the template definitions in the tcpp file. The non template definitions still needs to go into a regular cpp file.
Putting the non template code in the tcpp file includes it back into the header file and then that means it gets defined in every translation unit it gets included into.
In this case that means you should have
// A.h
class A
{
void foo();
template <class T> void bar( T someVar );
}
#include "A.tcpp"
// A.tcpp
template <class T> void A::bar( T someVar ) { some code; }
// A.cpp
#include "A.h"
void A::foo() { some code; }

I found the solution, it is not as nice as I would like, but it will do in my case. We can insert the following line at the end of the tcpp file:
template void A::bar<int>( int );
// And so on, for all types that should be supported.
It is called function template instantiation.

Related

Cannot force instantiation of specialized template

In a static library I declared a template in Class.h then I specialized some methods in Class.cpp. I want to use this class in a project linking to this library.
I put the specialization in a .cpp file to avoid errors like "already declared" (???) end at the end of the same .cpp I declared the existence of the specialization once everything is known for this class. Here is the code:
Class.h
#ifndef __CLASS_H__
#define __CLASS_H__
template<class T>
class Class
{
public:
~Class(){}
Class(){}
//...
void method1()
{ /* unspecialized job here */ }
};
#endif
Class.cpp
#include "Class.h"
template<>
void Class<bool>::method1()
{
/* Specialized job for bool here */
}
// Declare that the class is specialized for bool
template class Class<bool>;
Now, in my project using the library, when I try to instantiate an object of class Class<bool>, it still use the unspecialized method.
What is the problem? Is the use of "template" at the end of the .cpp file correct?
I use gcc 4.8/4.9 on Kubuntu/Raspbian if it has an importance and I use C++11.
The template specializations
template<>
void Class<bool>::method1()
{
/* Specialized job for bool here */
}
// Declare that the class is specialized for bool
template class Class<bool>;
are seen only in Class.cpp. If Class<bool> is used anywhere else in your code, those specializations are not visible there. Hence, the generic class template is used to instantiate Class<bool>.
If you want the specializations to be visible to all the files where Class<bool> is used, move them to Class.h. At that point, Class.cpp won't be necessary any more unless it has code other than the lines above.
You need to use extern templates for the specialization to be effective.
In your cpp you have the specialization and this line:
template struct MyClass<bool>;
Then add to the header:
extern template struct MyClass<bool>;
Now the compiler will be told to not instantiate the template but to pick up the instantiated one in your cpp.

Redeclaration error for a templated function

I have a setup where a templated function is inheriting another templated function.
template <typename DataType>
class ClassBase
{
virtual void InitModel(const cv::Mat& data) {};
}
template <typename DataType>
class ClassDerived : public ClassBase<DataType>
{
void InitModel(const cv::Mat& data) {};
}
Now I try to implement two specializations and one general templating for InitModel in ClassDerived in an implementation file
template<>
void ClassDerived<float>::InitModel(const cv::Mat& data)
{
// initialize some things
}
template<>
void ClassDervied<cv::Vec3b>::InitModel(const cv::Mat& data)
{
// initialize some things
}
template<typename DataType>
void ClassDerived<DataType>::InitModel(const cv::Mat& data)
{
// initialize some things
}
Before I wrote this, I did not have any specializations and it was working fine.
As soon as I added specialization, I get an error saying there was a redeclaration of the specification function. The weird part is that the redeclaration points out to the same line no. in the same file.
Since it was working fine before specialization, I expect the file isn't being read twice.
So, why would such an error start popping up as soon as the specializations are added ?
The error is :
/other/workspace/perception/perception_kit/object_detection/include/perception_kit/object_detection/grimson_GMM_templated_impl.tpp:129:
multiple definition of
`perception_kit::GrimsonGMMGen::InitModel(cv::Mat const&)'
CMakeFiles/test_obj.dir/src/object_detection_templated_test_platform.cpp.o:/other/workspace/perception/perception_kit/object_detection/include/perception_kit/object_detection/grimson_GMM_templated_impl.tpp:129:
first defined here
Is the problem because I am trying to derive a templated class or something else ?
Now I understand that for some, it might be a trivial problem but I have spent considerable time before I posted it here.
The base class is in BaseClass.h (its implemented as an abstract class)
The derived class declaration is in DerivedClass.h
The derived class declaration is in DerivedClass.tpp and is included in DerivedClass.h
You already defined the base template code inline in the header (with an empty body) so you can't redefine it again later. I suspect that's the source of your problem here, NOT the specializations.
You need to declare that you have specializations for those types. Otherwise, when the compiler in a different translation unit instantiates the template it will generate code for the member functions based on the primary template. When you try to link those generated functions with your specializations the linker will see multiple definitions of the specializations.
// Header
template <typename T>
struct test {
void f() {}
};
template <>
void test<int>::f(); // Declare the specialization
// Implementation (cpp, not included by client code)
template <>
void test<int>::f() { ... }
Note that function specializations are no longer templates, but regular functions. If different translation units include the definition of the function, then they will generate the code in multiple translation units. If you want to do that, then you can skip the declaration of the specialization and provide the definition directly, but you will need to make it inline:
// Implementation (if in header/included by user code)
template <>
inline void test<int>::f() { ... }

Define template in header file and definition in a cpp file within derived class [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why should the implementation and the declaration of a template class be in the same header file?
I am trying to define a template in a header file and the definition of it in a cpp file and the template should be defined within a derived class. So this is what I got:
Header file:
#ifndef ........
#define .....
template <class mytypename>
class abcBaseClass:public abcDerivedClass{
public:
mytypename getvalue(char*)
};
#endif
Source file:
mytypename abcDerivedClass<mytypename>::getvalue(char* name){
}
I just wanted to know if this is the correct way of doing it?.
This is what I am trying to achieve... The final way I want to make the call is
double x = a->getvalue<double>(char)
Similar questions have been asked many times on SO already.
But anyways...
First of all, you made some syntax errors.
Instead of
#ifndef ........
#define .....
template <class typename>
class abcBaseClass:public abcDerivedClass{
public:
typename getvalue(char*);
};
#endif
it should be something like this.
#ifndef ........
#define .....
template <typename T>
class abcBaseClass:public abcDerivedClass{
public:
T getvalue(char*);
};
// Definition follow in this file!
// For reasons or work-arounds, read below.
#endif
Also, both the template declarations and definitions should go into the same file.
One exception is when you instantiate that template to some type in the source file at where the template definition is.
Something like this.
#include "this_template.h"
template <typename T>
// all sorts of definitions...
// Explicit instantiate this template!!!!
template class abcBaseClass<Your_Type_Goes_Here>;
Note, a fundamental flaw with this approach is that, you can only use the type you explicitly instantiate in this source file everywhere else in your program. Attempting to instantiate this template with some other type will cause the linker complain about not able to find the matching definition.
If you insist on both the template being generic and having the definition of your template class somewhere else.
You can put the definition into another header file, just call it something like this_template_impl.h and include this_template.h in this_template_impl.h
Then, in your source file, instead of #include "this_template.h", you write #include "this_template_impl.h
You can put the definition in a .cpp file, but it's more trouble and not the way templates are usually done.
You need some extra code in the .cpp to convince the compiler to generate the functions with the necessary template parameter filled in. One way is to just use the function somehow:
mytypename abcDerivedClass<mytypename>::getvalue(char* name){
}
void dummy()
{
abcDerivedClass<double> temp;
temp->getvalue(NULL);
}
There's no need to actually call the dummy function, just having it there (after the template definition) is sufficient.
I'm sure there's another way to explicitly instantiate a template, but since I don't do this I can never remember.
NO this isn't the correct way:
It should be done this way:
#ifndef ........
#define .....
template <class T>
class abcBaseClass:public abcDerivedClass{
public:
T getvalue(char*)
};
#endif
and in the .cpp file:
template
T abcBaseClass::getvalue(char * ch){
}
The reason your code isn't correct is because typename is a C++ keyword. And must throw an error during compilation
You can also use:
#ifndef ........
#define .....
template <typename T>
class abcBaseClass:public abcDerivedClass{
public:
T getvalue(char*)
};
#endif
and in the C++ file:
template<class T>
T abcBaseClass<T>::getvalue(char * ch){
}

Template linking problem C++

I have a template class definition that needs to be in the cpp file. Adopting from http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13, I did something like this:
// File "foo.cpp"
#include <iostream>
#include "foo.h"
template<typename T> void foo()
{
std::cout << "Here I am!\n";
}
template void foo<int>();
I instantiate the template from the .cpp file. However, I need different types like foo(string) etc and I realized that I could only instantiate it once. How could I fix it?
Thanks.
You should be able to instantiate foo for each type you need.
template void foo<int>();
template void foo<double>();
template void foo<std::string>();
This is somewhat onerous, which is the reason many libraries tend to provide template function implementations in header files, so that any instantiation can be available to any cpp file which includes the header.
The template specialization should be in a separate translation unit (.cpp file) and the template (generic) definition in a header file.
In the foo.h
add the definition
template <typename T> void foo ()
{
std::cout << "Here I am! << std::endl;
}
In the foo.cpp use it
foo <int> ()
foo <std::string> ();

Where to define C++ class member template function and functors that instantiate it?

I have a class Foo which is used in a small standalone project. It has a class definition in Foo.h with the implementation for the class' member functions in an implementation file Foo.cpp.
First question - one of the member functions of class Foo is a template method Foo::doSomething(), is it correct that the implementation of this method should appear with the declaration of the function in Foo.h ?
The template parameter which Foo::doSomething() will be instantiated with is one of two Functor types - class CalcA and CalcB.
Should I:
(A) put the defintion and implementation of the two Functor classes all together in Foo.cpp (where they are actually used by the implementation of other Foo member functions to call Foo::doSomething).
(B) put the definition and implementation of the two Functor classes in Foo.h.
(C) should I put split the definition and implementation of the two Functors across Foo.h and Foo.cpp as would be done with an ordinary class?
General rule:
If foo::doSomething() is used outside foo.cpp (i.e. if it's public or protected, usually), it must go in the header.
If not, putting in in the cpp file is perfectly ok, and even a good idea (as it keeps the clutter away from the header file).
So, if the functors are only used in the cpp file, by all means put the template function there too. One can always refactor things later if this changes.
First you must understand templates mechanism. Templates are not compiled, they are instantiated when they are used and then their instantiation is compiled. So the compiler needs to have the full template definition in each module using the template function, in order to instantiate them first according to the parameters you've passed.
To solve your problem, there are three solutions but you'll see that they both lead to the same result.
Either you implement your whole templates in your header file inside the class definition (we use to suffix them with .hxx instead of .h in order to precise they're containing templates definitions):
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T& t) {
t.doSomething();
}
};
#endif
Or you can externalize the definition from the class, but still in the header file:
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T&);
};
template <class T>
void Foo::bar(const T& t) {
t.doSomething();
}
#endif
Finally, you can implement template methods bodies in an external file (prefixed with .cxx for the same reason). It will contain methods' bodies but won't include "Foo.hxx". Instead, it's "Foo.hxx" that will include "Foo.cxx" after the class definition. This way, when the compiler resolves the #include directive, it finds the whole template definition in the same module, allowing it to instantiate it:
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T&);
};
#include "Foo.cxx"
#endif
// Foo.cxx
template <class T>
void Foo::bar(const T& t) {
t.doSomething();
}
The choice between these 3 ways to implement templates is rather a matter of readability (and taste).
Second and third are equivalent in terms of generated code, but I'd rather not use the cxx file solution, because it often leads to stupid errors when you forget to invert the include.
Moreover, well-known C++ libraries like STL or Boost propose their code in header files only, which is a sign of good design. By using external definition inside headers, you clarify the definition of your class. You also prevent the compiler to automatically inline methods, which can sometimes lead to poor results according to Herb Sutter http://www.gotw.ca/gotw/033.htm
My default would be to put the definition for the member function templates right in the .h file, like this:
class Foo
{
public:
template<typename T> void DoSomething(T t);
};
// ... later...
template<typename T>
void Foo::DoSomething(T t)
{
// ...
}
If this is suboptimal for a particular case, then I'd take more heroic measures. Starting with #include-ing a .inc file with the definition at the end of the .h file, or possibly even doing explicit instantiations in the .cpp files where I needed the member function templates to be used.
The template method definition should indeed be in the header file of it the class it belongs to.
Like this:
class MyClass
{
template <typename T>
void foo(const T&)
{
// Definition
}
};
Or like this (note that the template method definition can be included from separate file after the class declaration)
class MyClass
{
template <typename T> void foo(const T&);
};
template <typename T>
void MyClass::foo(const T&)
{
// Definition
}
The rest is depends on the style you agreed on and your needs.
I would put the functor declaration (or even the definition if they are simple) into the header if I use them not only in Foo or if Foo has them as class member.