I am struggling to access static member function defined inside class template. In the header file TemplateTest.h I defined the primary class Template as:
#include<iostream>
template<class T, class U>
struct TemplateTest
{
public:
void static invoke();
/*{
std::cout << "Should not be called" << std::endl;
}*/
};
Then Source File TemplateTester.cpp I put a specialization:
#include "TemplateTest.h"
template<>
struct TemplateTest<int, bool>
{
static void invoke()
{
std::cout << "invoke<int, bool>" << std::endl;
}
};
template struct TemplateTest<int, bool>; //instantiate to resolve linker issue
I explicitly instantiated the class with so linker resolves correctly.
In the driver driver.cpp :
include "TemplateTest.h"
int main()
{
TemplateTest<int, bool>::invoke();
return 0;
}
When I compile the TemplateTest.cpp with g++ it generates the object file correctly but when I try to link it to the driver class it gives my linker error "undefined reference to `TemplateTest::invoke()"
I went through other related postings like this one but I am not trying access a function template.
Any clue is much appreciated.
The static member is declared or defined inside the template< … > class { … } block. If it is declared but not defined, then there must be another declaration which provides the definition of the member.
Static Member Function in C++ The static is a keyword in the C and C++ programming language. We use the static keyword to define the static data member or static member function inside and outside of the class.
You cannot have static and nonstatic member functions with the same names and the same number and type of arguments. Like static data members, you may access a static member function f() of a class A without using an object of class A .
The static declaration can be of template argument type or of any defined type. The statement template T K::x defines the static member of class K , while the statement in the main() function assigns a value to the data member for K <int> .
You are right that the object file you create from TemplateTester.cpp
will contain a symbol for the specialization you provided. This is the case because any explicit specialization causes the template to be instantiated, and it is doubly the case because you even added an explicit instantiation (which is actually unnecessary).
However, at the time when driver.cpp
is compiled, the compiler does not know about the specialization, because you only include TemplateTester.h
, and the specialization isn't mentioned there. So the compiler instantiates the template, of course not using the specialized definition, so you get your problem.
The Standard says (Italics by me):
(§14.7.3/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. If the program does not provide a definition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function, the program is ill-formed, no diagnostic required. An implicit instantiation is never generated for an explicit specialization that is declared but not defined. [...]
So you need to make both, the declaration and the definition of the specialization known to the compiler when it works on driver.cpp
. The best way of doing this is by adding the entire specialization to TemplateTester.h
.
Note, again, that an explicit instantiation is not actually required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With