模板类成员专业化而不声明在报头(Template class member specializati

2019-07-20 11:41发布

我有一个模板类,我的头声明以一个方法,并没有在标题中该方法的定义。 在.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;
}

这个程序编译,并成功地用gcc 4.7.2所有C ++标准(C ++ 98,GNU ++ 98,C ++ 11,和GNU ++ 11)的链接。 输出是:

1
2

这对我来说很有意义。 由于main.cc翻译单元没有看到的定义bar()或它的任何特例,它预计调用bar()使用的未特化的定义明确的实例bar()在其他一些翻译单元。 但由于名称重整是可以预见的,foo.cc中的特例具有相同的符号名作为非特定义明确的实例会,所以main.cc能够使用这些特例,没有他们曾经在翻译单元被宣布。

我的问题是:这是一个意外,或者是这种行为由C ++标准规定的? 换句话说,这是代码的可移植性?

我能找到最相关的现有问题是模板类成员专业化的宣言 ,但不包括这种特殊情况。

(在你想知道为什么这关系到我的情况,那是因为我用这样的代码作为一种编译时查表的,这是一个短了很多,如果我不申报的专业。)

Answer 1:

标准(C ++ 11)要求明确的特化被宣布(但不一定限定)首先被使用之前:

(14.7.3 / 6)如果一个模板,一个成员模板或类模板的成员是明确专门那么专业化应在第一次使用的是专业化的,它会造成隐式实例发生前宣布,在每一个翻译单元在其中发生这样的使用; 没有诊断是必需的。 如果程序不为明确专业化提供的定义和任一专业化而可能导致的隐式实例发生或构件是虚拟成员函数的方式使用时,该程序是形成不良的,没有诊断需要。 它从未在一个声明,但没有定义一个明确的专业化分工产生的隐式实例。 [...]

我相信,当您的主模板定义包括非专业版本的成员函数的定义,这将在实践中才有效。 因为在这种情况下,当显式特未声明,现有的主定义可以被用于编译函数内联到代码,和专业化最终将不被在链接时使用。

换句话说,如果没有包括在主模板定义的成员函数的定义,你的连接招大概可以预计在实践中的工作,但它不会与标准说什么符合,它可以让你进入只要你内联函数定义添加到主模板真正的麻烦。



文章来源: Template class member specialization without declaration in header