简体   繁体   English

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

[英]static member function inside class template specialization

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: 在头文件TemplateTest.h中,我将主类模板定义为:

#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: 然后源文件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

I explicitly instantiated the class with so linker resolves correctly. 我明确地实例化了类,因此链接器正确解析。

In the driver driver.cpp : 在驱动程序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()" 当我使用g ++编译TemplateTest.cpp时,它会正确生成目标文件,但是当我尝试将其链接到驱动程序类时,它会给我的链接器错误“未定义引用`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. 任何线索都非常感谢。

You are right that the object file you create from TemplateTester.cpp will contain a symbol for the specialization you provided. 您是对的,您从TemplateTester.cpp创建的目标文件将包含您提供的专业化的符号。 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. 但是,在编译driver.cpp时,编译器不知道特殊化,因为您只包含TemplateTester.h ,并且那里没有提到特化。 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; (§14.7.3/ 6)如果一个模板,一个成员模板或类模板的成员明确专门那么专业化应在第一次使用的是专业化的前宣布,将导致隐式实例发生, 在每一个发生这种用途的翻译单位; 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 . 因此,当它在driver.cpp上运行时,您需要同时生成编译器已知的特化的声明和定义。 The best way of doing this is by adding the entire specialization to TemplateTester.h . 执行此操作的最佳方法是将整个特化添加到TemplateTester.h

Note, again, that an explicit instantiation is not actually required. 另请注意,实际上并不需要显式实例化。

There are several problems : 有几个问题:

  • you do not need to explicitly instantiate fully specialized template 您不需要显式实例化完全专用的模板
  • if you want to put your static method in the header, then use inline . 如果要将静态方法放在标题中,请使用inline Otherwise you will get multiple instances and linker problems 否则,您将获得多个实例和链接器问题
  • template specializations you put in the header, and define methods in the source files 放在标题中的模板特化,并在源文件中定义方法
  • if you do not want something to be called in a template, you don't need to define it. 如果您不希望在模板中调用某些内容,则无需定义它。 You'll get compiler errors, and that means catching errors 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;   
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM