Suppose I have:
template <typename T>
class A
{
//Do something with T
};
I know that the compiler will generate a class A<T> for each different T defined in the code.
What if I have:
class B
{
template <typename T>
void f() { /* Do something with T */ }
};
Would there be only one definition of class B but multiple overloads of f() for each different T it's called with?
Yes, with every instantiation of f<T> there will be a definition of f() generated by compiler.
Depending on the compiler, the f() could be optimized due to inlining or it can just acquire that much space in the code segment.
However, I have seldom came across this kind of design where you have a non-static template member function (without any argument!) inside a non-template class.
Related
The title is a mouthful, but basically I wrote something like this:
enum EnumType{ValA, ValB};
template<EnumType> class A {};
template<>
class A<ValA>
{
private:
double param;
public:
A(double param);
};
template<>
A<ValA>::A(double param)
{
// Do Stuff
}
and when I try to compile it I get:
error: template-id 'A<>' for 'A<(EnumType)0u>::A(double)' does not
match any template declaration
Am I doing this wrong?
After searching online for similar cases, I tried to remove template<> (even though I don't understand why this would work), but then I get
multiple definition of 'A<(EnumType)0u>::A(double)'
I guess that I can replace template<> by inline (I tried and it compiles), but that doesn't feel like the proper way to do it (or if it is, I don't understand why).
Can someone explain to me what is wrong with what I wrote, why changing this seems to work, and what's the proper way to do it ?
Can someone explain to me what is wrong with what I wrote, why changing this seems to work, and what's the proper way to do it ?
The standard says:
Members of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntax.
Therefore, in your case you must use:
A<EnumType::ValA>::A(double param)
{
// Do Stuff
}
No template<> at all is just fine. That's because you are actually specializing a (special) member function (the constructor) of an explicitly specialized class template.
See it on coliru.
It would have been different if no explicit specialization was given.
As a minimal working example:
enum EnumType{ValA, ValB};
template<EnumType> class A
{
private:
double param;
public:
A(double param);
};
template<>
A<EnumType::ValA>::A(double)
{
// Do Stuff
}
int main() {
A<EnumType::ValA> a{0.};
}
In this case, template<> is required before the definition of the constructor because you are not defining a specialization of a member function of an already specialized class template.
You missed a semicolon (;) at the the end of class definition.
And the non template member function can be defined this way:
A<ValA>::A(double param) {
// Do Stuff
}
Informally, the template parameter list is only written when necessary, for example, for defining a member function template of a class template, the two template parameter list should all be written
template<class U, class V>
class A{
template <class T>
A();
};
template<class U, class V>
template <class T>
A<U, V>::A() {}
and a empty template parameter list is needed for a explicit specialisation of function template (which, i guess, is the reason why you use so here), informally because it tells the compiler that this is not a function overloading.
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() { ... }
CODE 1 :
template <class T>
class cat{
public:
T a;
void show(){
cout << a ;
}
};
CODE 2 :
template <class T>
class dog{
public:
T a;
template <class U> // making show function template
void show(){
cout << a ;
}
};
so cat::show() is a member function of a template class.
and dog::show() is a member function template of a template class.
Questions:
1) is there any difference between class template cat and dog, rather than when I call the member function show, I have to explicitly speciafy U for instance of dog template class?
2) does the compiler handles them the same. for example cat::show() will not be compiled until I use it. and I guess the same thing for dog::show();. so is there anything Im missing here ?
Those two are related only in the same way that the two free functions foo are related here:
void foo() {};
template <typename T>
void foo() {}
While being a member of a template class both will be instantiated on demand for implicit instantiations. On the other hand, if you explicitly instantiate the template class, the non-template function will be generated by the compiler, but the template member function will not.
Aside from that, the usual caveats: template functions will only match exact types, while non-template functions will allow implicit conversions:
template <typename T>
struct tmpl {
void foo( T, T ) {}
template <typename U>
void bar( U, U ) {}
};
tmpl<int> t;
t.foo( 5, 1. ); // fine, will convert 1. from double to int
t.bar( 5, 1. ); // error
And all other differences between templated and not templated functions.
What I really don't understand is why this is confusing you so much. It seems that you are considering the instantiation as the only property of functions, which it is not. What is it that really bothers you? Why do you think a template and non-template functions would be the same?
In particular, I feel that you are wasting too much effort into a detail of implementation. In most cases, whether one or all member functions of a template class are instantiated does not really affect the semantics of your program, if your program needs the member function, then the compiler will generate code for it, if your program does not need it, there is no difference whether it generated the code or not (consider that the linker can remove any symbol, what is the difference of the member function never having been generated or it being removed by the linker?)
I have a template container class that I derive from called MyContainer. MyContainer defines methods like Get(), Set(), etc. to access individual elements. I'd like to make a bitfield class implemented as a MyContainer<char>, where each char element holds CHAR_BIT number of bits. However, to allow the user to operate on individual bits rather than entire bytes, I would have to make Get() and Set() virtual, which is illegal. What are some alternatives?
I was thinking of defining GetBit() and SetBit() in the derived class, but this would violate the Liskov substitution principle. (Think of a SortMyContainer() function.)
EDIT: Here is a simplified example:
template <typename Datatype>
struct MyContainer
{
virtual Datatype Get();
};
template <typename Datatype> // Error: Templates may not be virtual.
virtual Datatype MyContainer<Datatype>::Get() // EDIT: The problem was on this line. The "virtual" keyword should only appear with the function declaration.
{
// ...
}
It is not illegal, only template virtual member functions are.
// valid
template<typename T> class MyContainer {
virtual void set(const T &) = 0;
}
// not valid
class MyContainer {
template <typename T> virtual void set (const T &) = 0;
}
If I got you wrong, please consider placing a code-sample.
edit after your adding of example code:
template <typename Datatype>
virtual // <-- nope, not here
Datatype MyContainer<Datatype>::Get()
{
// ...
}
virtual is only part of the declaration inside the class body. This should be valid:
template <typename Datatype>
Datatype MyContainer<Datatype>::Get()
{
// ...
}
However, note that the definition must be visible at the point of template instantiation. So either put it in the header-file, too (or in an extra-header that you then include into your real header), or leave it in the class-body.
(please nobody mention exported templates now, you and I know them a lot, but they are not quite a beginner topic, and deprecated with the next standard)
You appear to be confused about what constitutes a template. Class templates may have virtual functions, and indeed, those template parameters may appear in those function's signatures.
template<typename T> class an_interface {
virtual T Get() = 0;
};
class a_class : public an_interface<int> {
};
This is perfectly valid. What's not perfectly valid is
class an_interface {
template<typename T> virtual T Get() = 0;
}
Unless the specific member function in question has it's own, separate template parameters, the member function is not a template and may be virtual, irrespective of if it was generated from a class template.
I have a template class:
template<typename A, typename B>
class A {
};
In another .h file
template<typename A, typename B>
class A; //forward declaration
How could I declare m_A over here? I keep getting C++ forbids declaration of A with no type error:
class B {
A* m_A;
};
If you don't know the types that you want to instantiate A with when inside of B, then you will have to also make a template out of B
template<typename A1, typename B1>
class B
{
A<A1, B1>* m_A;
};
Either that, or you would have to instantiate A as a specific type, i.e.,
class B
{
A<Type_1, Type_2>* m_A;
};
Declare m_A with some specific types for A:
class B
{
A<int, char>* m_A;
}
If you B is such that you don't know a priori what types should be used in the m_A declaration, perhaps B needs to be template class and you'd use those type parameters in the declarion of m_A.
Templates are nice little peculiar beasts. The template definition must be available for the compiler at the place of instantiation, so the most common pattern is defining the template in the header so that each translation unit that uses the templated methods (and thus instantiates them) will have access to the definition.
Alternatively, you can provide the template definitions in a single translation unit, but you will have to ensure that you are instantiating the template for all the types for which you use it in the whole program.
// header
template <typename T> struct A
{
void foo( T );
}
// single translation unit
#include "header"
template <typename T> // template member definitino
void A<T>::foo( T x ) {
std::cout << "A(" << x << ")" << std::endl;
}
template struct A<int>; // explicit instantiation for int
template struct A<double>; // explicit instantiation for double
// main
#include "header"
int main() {
A<int> ai;
ai.foo( 5.5 ); // will print 5 (int rounded down)
A<double> ad;
ad.foo( 5.5 ); // will print 5.5
A<char> ac;
ac.foo( 'a' ); // linker error, A<char>::foo undefined
}
Because in general templates are meant to be used with any type through the program, defining the template methods in a single translation unit and using explicit instantiation is not a good idea. On the other hand, in the few cases where you need to control the set of types for which the template is instantiated, or under a few other circumstances (reducing large compile times [*]) you might want to follow this second approach. But again, in the general case, it is simpler to define the member functions in the header, and again it is simpler to defined them inside the class definition.
[*] Templates are compiled in all translation units in which they are used, which means that if you instantiate A<int>::foo in 5 different translation units, the compiler will compile it 5 times, and then the linker will discard 4 of the instantiations. In some cases where the template is complex, it might be an advantage to compile it once in one translation unit and just call it from the others. Note that with explicit instantiation, all member functions are compiled, while with implicit instantiation (at the place of use) only those members that are actually used will get compiled, so depending on the situation, explicit instantiation may be more costly than implicit instantiation (in classes with many members)
template<typename A>
void B<A>::function()
{
}
Btw, do not separate definitions and declarations while writing a template class.
EDIT:
changed < to < and > to >
Before that code looked like:
template
void B::function()
{
}