【发布时间】:2013-02-25 07:09:30
【问题描述】:
我有一个模板类,我在标头中声明了一个方法,并且在标头中没有定义该方法。在一个 .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++ 标准规定的这种行为?换句话说,这段代码是否可移植?
我能找到的最相关的先前问题是Declaration of template class member specialization,但它不包括这种特殊情况。
(如果您想知道为什么这对我很重要,那是因为我将这样的代码用作一种编译时查找表,如果我不声明专业化,它会短得多。 )
【问题讨论】:
-
这是一个相当好的第一个问题!我认为 IBM 的编译器允许您使用 extern 关键字声明您的特化,但我自己从未这样做过。
标签: c++ templates declaration template-specialization