头中没有声明的模板类成员专用化
Template class member specialization without declaration in header
我有一个模板类,我用一个方法在头中声明它,而在头中没有该方法的定义。在一个.cc文件中,我定义了该方法的特殊化,而从不在头中声明它们。在另一个.cc文件中,我为存在专门化的不同模板参数调用该方法。它看起来像这样:
foo.h:
template<typename T>
class Foo {
public:
static int bar();
};
foo.cc:
#include "foo.h"
template<>
int Foo<int>::bar() {
return 1;
}
template<>
int Foo<double>::bar() {
return 2;
}
main.cc:
#include <iostream>
#include "foo.h"
int main(int argc, char **argv) {
std::cout << Foo<int>::bar() << std::endl;
std::cout << Foo<double>::bar() << std::endl;
return 0;
}
该程序成功地编译并链接了适用于所有C++标准(C++98、gnu++98、C++11和gnu++11(的gcc 4.7.2。输出为:
1
2
这对我来说很有意义。因为main.cc翻译单元没有看到bar()
的定义或它的任何专业化,所以它希望对bar()
的调用在其他翻译单元中使用bar()
的非专业化定义的显式实例化。但是,由于名称篡改是可预测的,foo.cc中的专业化与非专业化定义的显式实例化具有相同的符号名称,因此main.cc能够使用这些专业化,而无需在该翻译单元中声明它们。
我的问题是:这是一个意外,还是C++标准强制要求这种行为?换句话说,这个代码是可移植的吗?
我能找到的最相关的先前问题是模板类成员专业化的声明,但它没有涵盖这个特定的情况。
(如果你想知道为什么这对我来说很重要,那是因为我使用这样的代码作为一种编译时查找表,如果我不声明专业化,它会短得多。(
标准(C++11(要求在首次使用显式专业化之前声明(但不一定定义(:
(14.7.3/6(如果模板、成员模板或类模板的成员是明确专门化的,则应在首次使用该专门化之前声明该专门化,这将导致在发生这种使用的每个翻译单元中发生隐式实例化;不需要进行诊断。如果程序没有提供显式专门化的定义,并且专门化的使用方式会导致隐式实例化发生,或者成员是虚拟成员函数程序格式不正确,不需要诊断。对于已声明但未定义的显式专门化,永远不会生成隐式实例化。[…]
我相信,只有当您的主要模板定义包括其中一个成员函数的非专用版本的定义时,这在实践中才会产生效果。因为在这种情况下,当没有声明显式专用化时,现有的主定义可能会被用来将函数内联编译到代码中,而专用化最终将不会在链接时使用。
换言之,如果主模板定义中没有成员函数的定义,那么链接器技巧可能会在实践中发挥作用,但它不符合标准的规定,而且一旦将内联函数定义添加到主模板中,就会给您带来真正的麻烦。
- 静态数据成员模板专用化的实例化点在哪里
- 成员变量如何使用专用类模板?
- GCC 7 中模板类的模板成员函数的专用化
- C++ 类模板部分专用化,而不专用化所有成员函数
- 专用于可变参数模板成员函数
- 对专用模板成员的未定义引用
- 对类模板成员的显式专用化的约束
- 类模板成员函数的专用化
- C++ 将派生类的成员函数指针作为参数传递时选择了错误的模板专用化
- 类成员函数的函数模板专用化
- '将成员函数仅添加到类的专用模板
- 静态数据成员的模板专用化
- 在实例化封闭类模板之后,我们可以声明模板类成员的部分专用化吗
- 如何部分专用化非成员和成员函数指针的结构模板
- 如何将类成员专用于多个模板值(常量)?
- 模板类中的模板成员专用化
- "expected initializer before '<' token"尝试模板成员专用化
- 模板化子类和模板化基类的静态成员专用化
- 数组的部分模板成员专用化
- 头中没有声明的模板类成员专用化