C++ 类模板专门化中的静态成员函数

C++ 类模板专门化中的静态成员函数,c++,templates,static,instantiation,specialization,C++,Templates,Static,Instantiation,Specialization,我正在努力访问类模板中定义的静态成员函数。 在头文件TemplateTest.h中,我将主要类模板定义为: #include<iostream> template<class T, class U> struct TemplateTest { public: void static invoke(); /*{ std::cout << "Should not be called" << std::endl;

我正在努力访问类模板中定义的静态成员函数。 在头文件TemplateTest.h中,我将主要类模板定义为:

#include<iostream>

template<class T, class U>
struct TemplateTest
{
public:
    void static invoke();
    /*{

        std::cout << "Should not be called" << std::endl;

    }*/
};
#包括
模板
结构模板测试
{
公众:
void static invoke();
/*{

std::cout有几个问题:

  • 您不需要显式地实例化完全专用化的模板
  • 如果要将静态方法放在标题中,请使用
    inline
    。否则会出现多个实例和链接器问题
  • 将模板专门化放在标题中,并在源文件中定义方法
  • 如果您不希望在模板中调用某些内容,则无需对其进行定义。您将得到编译器错误,这意味着可以更早地捕获错误

//TemplateTest.h
#包括
模板
结构模板测试;
模板
结构模板测试
{
内联静态void invoke()
{

std::cout您是对的,您从
TemplateTester.cpp
创建的对象文件将包含您提供的专门化的符号。这种情况是因为任何显式专门化都会导致模板被实例化,而这种情况是双重的,因为您甚至添加了显式实例化(这实际上是不必要的)

但是,在编译
driver.cpp
时,编译器不知道专门化,因为您只包括
TemplateTester.h
,而专门化没有提到。因此编译器实例化了模板,当然没有使用专门化定义,所以您会遇到问题

标准上说(我用斜体):

(§14.7.3/6)如果一个模板、一个成员模板或一个类模板的一个成员被显式地专门化,那么该专门化应在第一次使用该专门化之前声明,该专门化将导致隐式实例化发生,在发生这种使用的每个翻译单元中;不需要诊断。如果程序不提供显式专门化的定义,该专门化的使用方式可能导致隐式实例化,或者该成员是虚拟成员函数,程序格式错误,不需要诊断。对于已声明但未定义的显式专门化,不会生成隐式实例化内德[…]

因此,当编译器在
driver.cpp
上运行时,您需要让编译器知道专门化的声明和定义。最好的方法是将整个专门化添加到
TemplateTester.h


再次请注意,实际上并不需要显式实例化。

将实现移动到头文件。模板的实现需要对所有使用它们的TU可见。感谢@Bццћ我实际上在这里尝试了一个原型。也许我应该显式提到它们。类模板实际上是stati的一部分c库,因此,我认为我仍然需要实例化。但你是对的,我不应该在类内定义函数。它应该在类外完成。我会尝试一下,看看它是否解决了我的问题。@jazaman不,你不需要实例化完全专用的模板,因为它们与普通(非模板)模板类似类。如果在多个位置包含标题,则会出现链接器错误。在阅读了其他答案后,我了解到,如果是完全专用的情况,则无需再这样做。感谢@jogojapan的解释。这实际上是我正在处理的模板静态库的原型。现在我可以了解为什么它会失败uess我可以移动定义以使编译器满意。
#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
include "TemplateTest.h"

int main()
{
    TemplateTest<int, bool>::invoke();
    return 0;
}
// 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();
}
// 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;   
}