模板类成员专业化,没有声明头 [英] Template class member specialization without declaration in header

查看:123
本文介绍了模板类成员专业化,没有声明头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模板类,我在一个头声明一个方法,没有该方法的头部中的定义。在.cc文件中,我定义了该方法的特殊化,而不必在标题中声明它们。 在不同的.cc文件中,我调用存在特殊化的不同模板参数的方法。它看起来像这样:

I have a template class that I declare in a header with one method and no definition of that method in the header. In a .cc file, I define specializations of that method without ever declaring them in the header. In a different .cc file, I call the method for different template parameters for which specializations exist. It looks like this:

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 ++标准的gcc 4.7.2 c ++ 98,gnu ++ 98,c ++ 11和gnu ++ 11)。输出为:

This program compiles and links successfully with gcc 4.7.2 for all C++ standards (c++98, gnu++98, c++11, and gnu++11). The output is:

1
2

这对我有意义。因为main.cc翻译单元没有看到 bar()或其任何特殊化的定义,它期望调用 bar()在其他翻译单元中使用 bar()的非特殊定义的显式实例化。但是由于名称调整是可以预测的,因此foo.cc中的特殊化具有与非特定化定义的显式实例化相同的符号名称,因此main.cc能够使用那些特殊化,而不必在那个翻译单元中声明。

This makes sense to me. Because the main.cc translation unit does not see a definition of bar() or any specializations of it, it expects the calls to bar() to use explicit instantiations of an unspecialized definition of bar() in some other translation unit. But since name mangling is predictable, the specializations in foo.cc have the same symbol names as explicit instantiations of an unspecialized definition would, so main.cc is able to use those specializations without them ever being declared in that translation unit.

我的问题是这是一个意外,还是这是C ++标准强制的行为?换句话说,这个代码是否可移植?

My question is this: is this an accident, or is this behaviour mandated by the C++ standard? In other words, is this code portable?

最相关的先前问题,我可以找到模板类成员专用化声明,但不包括这种特殊情况。

The most relevant prior question that I could find is Declaration of template class member specialization, but it doesn't cover this particular case.

(如果你想知道为什么这对我很重要,这是因为我使用这样的代码作为一种编译时查找表,如果我不声明专业化,它会更短)。


(In case you're wondering why this matters to me, it's because I'm using code like this as a sort of compile-time look-up table and it's a lot shorter if I don't declare the specializations.)

推荐答案

标准(C ++ 11)要求在首次使用之前声明(但不必定义) / p>

The Standard (C++11) requires that explicit specializations be declared (but not necessarily defined) before they are first used:


(14.7.3 / 6)如果模板,成员模板或类模板的成员被明确指定,在首次使用该专门化之前声明的将导致在发生这种使用的每个翻译单元中发生隐式实例化;不需要诊断。如果程序不提供明确的专门化的定义,并且专用化以使得隐式实例化发生或成员是虚拟成员函数的方式使用,则
程序是不成形的,无需诊断。对于已声明但未定义的显式特化,绝不会生成隐式实例化。 [...]

(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; 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. [...]

我相信这在实际中只有当你的主模板定义包含非 - 特殊版本的成员函数之一。因为在这种情况下,当没有声明显式特化时,现有的主定义可以用于将函数内联编译成代码,并且专用化将不会在链接时使用。

I believe that this will in practice only have an effect when your primary template definition includes the definition of the non-specialized version of one of the member functions. Because in that case, when the explicit specialization isn't declared, the existing primary definition may be used to compile the function inline into the code, and the specialization would end up not being used at link-time.

换句话说,如果没有在主模板定义中包含的成员函数的定义,你的链接器技巧可能会在实践中工作,但它不会符合标准说,它可以让你陷入真正的麻烦,一旦你添加一个内联函数定义到主模板。

In other words, if there is no definition of the member function included in the primary template definition, your linker trick can probably be expected to work in practice, but it wouldn't conform with what the Standard says, and it can get you into real trouble as soon as you add an inline function definition to the primary template.

这篇关于模板类成员专业化,没有声明头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆