类模板专门化内部的静态成员函数
static member function inside class template specialization
我正在努力访问类模板内定义的静态成员函数。在头文件TemplateTest.h中,我将主类Template定义为:
#include<iostream>
template<class T, class U>
struct TemplateTest
{
public:
void static invoke();
/*{
std::cout << "Should not be called" << std::endl;
}*/
};
源文件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
我显式地实例化了这个类,使用了正确的链接器解析
driver.cpp:
include "TemplateTest.h"
int main()
{
TemplateTest<int, bool>::invoke();
return 0;
}
当我用g++编译TemplateTest.cpp时,它会正确生成对象文件,但当我试图将其链接到驱动程序类时,它会给我的链接器错误"未定义的引用到' templatettest::invoke()"
我浏览了其他相关的帖子,比如这个,但我没有尝试访问函数模板。
您从TemplateTester.cpp
创建的对象文件将包含您提供的专门化的符号,这是正确的。之所以会出现这种情况,是因为任何显式专门化都会导致模板被实例化,而且由于您甚至添加了显式实例化(这实际上是不必要的),这种情况会加倍。
但是,在编译driver.cpp
时,编译器并不知道专门化,因为您只包含了TemplateTester.h
,并且在那里没有提到专门化。所以编译器实例化模板,当然不使用专门化定义,所以你得到你的问题。
The Standard says(斜体by me):
(§14.7.3/6)如果模板、成员模板或类模板的成员被显式特化,则该特化应在第一次使用该特化之前声明,该特化将导致隐式实例化发生,在每个使用该特化的翻译单元中, 不需要诊断。如果程序没有为显式专门化提供定义,并且专门化的使用方式导致隐式实例化发生,或者成员是虚成员函数,则程序是病态的,不需要诊断。对于声明但未定义的显式专门化,永远不会生成隐式实例化。[…]
因此,当编译器在driver.cpp
上工作时,您需要同时声明和定义专门化。最好的方法是将整个专门化添加到TemplateTester.h
。
再次注意,实际上并不需要显式实例化。
有几个问题:
- 你不需要显式实例化完全专门化的模板
- 如果你想把你的静态方法放在头部,然后使用
inline
。否则你会得到多个实例和链接器问题 - 模板专门化放在头文件中,并在源文件中定义方法
- 如果你不希望某些东西在模板中被调用,你不需要定义它。你会得到编译错误,这意味着要更早地捕获错误。
// 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;
}
- 如何在C++中使用非静态成员函数作为回调函数
- 静态成员函数使用相同的名称时出现模板类型名称错误
- 在 nullptr 上调用无状态类的非静态成员函数是否合法?
- 为什么传递非静态成员函数会导致编译错误?
- 处理类内的回调时,必须调用对非静态成员函数的引用
- 非静态成员函数的 decltype 格式不正确吗?
- std::异步与非静态成员函数
- C++无效使用非静态成员函数?
- 未使用的C++未优化的静态成员函数/变量
- C++:如何返回指向非静态成员函数的指针?
- 使用静态成员函数而不是普通函数是否有任何开销?
- 在 stream_descriptor::async_wait 中无效使用非静态成员函数
- 为什么我不能像这样在静态成员函数中调用静态成员变量?
- 无法在clang Linux中分配非静态成员函数,但我可以在Visual Studio Windows中分配
- 在类定义中推导内联静态成员函数的返回类型
- `enable_if()`以禁用模板化类的静态成员函数声明
- 错误:无效使用非静态成员函数"int test::hotplug_callback(libusb_contex
- 常量静态成员函数
- 使用 vector.sort() 的非静态成员函数无效使用
- 从静态成员函数访问私有非静态类变量 - C++