Static member function inside a class

I am trying to access a static member function defined inside a class template. In the TemplateTest.h header file, 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 the source file TemplateTester.cpp placed the 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 created an instance of the class, so that link replication is correct.

In driver.cpp driver:

 include "TemplateTest.h" int main() { TemplateTest<int, bool>::invoke(); return 0; } 

When I compile TemplateTest.cpp with g ++, it correctly generates an object file, but when I try to link it to a driver class, it gives my linker error "undefined link to" TemplateTest :: invoke () "

I have looked at other related publications, such as this one , but I am not trying to access the function template.

Any hint is greatly appreciated.

+7
source share
2 answers

You are correct that the object file created with TemplateTester.cpp will contain a character for the specialization you specified. This is because any explicit specialization leads to the creation of an instance of the template, and this is doubly because you even added an explicit creation (which is actually not necessary).

However, while driver.cpp compiling, the compiler does not know about specialization, because you only include TemplateTester.h , and specialization is not mentioned there. Thus, the compiler creates an instance of the template, of course, without using a specialized definition, so you get your problem.

The standard says (italics mine):

(ยง14.7.3 / 6). If a template, a member template, or a member of a class template is explicitly specialized, then this specialization must be declared before the first use of this specialization, which will cause an implicit instantiation, in each translation unit in which such use occurs; no diagnostics required. If the program does not provide a definition for explicit specialization, and either specialization is used in such a way as to implicitly create an instance, or the member is a virtual member function, the program is poorly formed, and diagnostics are not required. An implicit instance is never created for explicit specialization, which is declared but not defined. [...]

So, you need to make both a declaration and a specialization definition known to the compiler when it runs on driver.cpp . The best way to do this is to add all the specialization to TemplateTester.h .

Note again that explicit instantiation is not really required.

+5
source

There are several problems:

  • you do not need to explicitly create a fully specialized template
  • if you want to put your static method in the header, use inline . Otherwise, you will get multiple instances and linker problems.
  • templates that you insert in the header and define methods in the source files
  • If you do not want something called in the template, you do not need to define it. You will get compiler errors, which means that errors were detected earlier.

 // TemplateTest.h #include<iostream> template<class T, class U> struct TemplateTest; template<> struct TemplateTest<int, bool> { inline static void invoke() { std::cout << "invoke<int, bool>" << std::endl; } }; // main.cpp include "TemplateTest.h" int main() { TemplateTest<int, bool>::invoke(); } 

Another way is to change the header and add the source file.

 // TemplateTest.h #include<iostream> template<class T, class U> struct TemplateTest; template<> struct TemplateTest<int, bool> { static void invoke(); }; // TemplateTest.cpp #include "TemplateTest.h" void TemplateTest<int, bool>::invoke() { std::cout << "invoke<int, bool>" << std::endl; } 
+3
source

All Articles