类模板特化中的静态成员函数

jaz*_*man 7 c++ static templates 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;

    }*/
};
Run Code Online (Sandbox Code Playgroud)

然后源文件TemplateTester.cpp我把一个专业化:

#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
Run Code Online (Sandbox Code Playgroud)

我明确地实例化了类,因此链接器正确解析.

在驱动程序driver.cpp中:

include "TemplateTest.h"

int main()
{
    TemplateTest<int, bool>::invoke();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我使用g ++编译TemplateTest.cpp时,它会正确生成目标文件,但是当我尝试将其链接到驱动程序类时,它会给我的链接器错误"未定义引用`TemplateTest :: invoke()"

我经历了像这样的其他相关帖子,但我没有尝试访问功能模板.

任何线索都非常感谢.

jog*_*pan 5

你是对的,你创建的目标文件TemplateTester.cpp将包含你提供的专业化的符号.这是因为任何显式特化都会导致模板被实例化,并且情况更是如此,因为您甚至添加了一个显式实例化(实际上这是不必要的).

但是,在driver.cpp编译时,编译器不知道特化,因为你只包含TemplateTester.h,并且那里没有提到特化.所以编译器实例化模板,当然不使用专门的定义,所以你得到了你的问题.

标准说(我用斜体字):

(§14.7.3/ 6)如果一个模板,一个成员模板或类模板的成员明确专门那么专业化应在第一次使用的是专业化的前宣布,将导致隐式实例发生,在每一个发生这种用途的翻译单位; 无需诊断.如果程序没有提供显式特化的定义,并且特殊化的使用方式会导致隐式实例化或成员是虚拟成员函数,则程序格式错误,无需诊断.永远不会为已声明但未定义的显式特化生成隐式实例化.[...]

因此,您需要同时进行编译器在处理时已知的特化的声明和定义driver.cpp.这样做的最好方法是将整个特化添加到TemplateTester.h.

另请注意,实际上并不需要显式实例化.