“ODR 使用"是什么意思?某物?

2021-12-13 00:00:00 templates c++ one-definition-rule

这只是在 另一个问题.

显然,类模板中的成员函数只有在 ODR 使用时才会被实例化.有人可以解释一下这到底是什么意思.维基百科关于单一定义规则 (ODR) 的文章 没有提到ODR 使用".

Apparently member functions in class templates are only instantiated if they are ODR-used. Could somebody explain what exactly that means. The wikipedia article on One Definition Rule (ODR) doesn't mention "ODR-use".

然而标准将其定义为

名称显示为潜在求值表达式的变量是 odr-used 除非它是满足以下要求的对象出现在常量表达式 (5.19) 和左值到右值中立即应用转换 (4.1).

A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately applied.

在 [basic.def.odr] 中.

in [basic.def.odr].

显然这是错误的部分,整个段落包含对不同事物的多个定义.这可能与类模板成员函数相关:

Apparently this is the wrong part and the entire paragraph contains multiple definitions for different things. This might be the relevant one for class template member function:

一个非重载函数,其名称显示为潜在评估表达式或一组候选的成员函数,如果从 a 引用时由重载决议选择潜在评估的表达式,被 odr 使用,除非它是一个纯虚函数及其名称未明确限定.

A non-overloaded function whose name appears as a potentially-evaluated expression or a member of a set of candidate functions, if selected by overload resolution when referred to from a potentially-evaluated expression, is odr-used, unless it is a pure virtual function and its name is not explicitly qualified.

但是我不明白,这个规则是如何跨多个编译单元工作的?如果我显式实例化一个类模板,是否所有成员函数都实例化了?

I do however not understand, how this rule works across multiple compilation units? Are all member functions instantiated if I explicitly instantiate a class template?

推荐答案

这只是一个任意定义,被标准用来指定何时必须为实体提供定义(如反对只是声明).标准不只是说使用",因为这可以根据不同的情况进行不同的解释语境.并且一些 ODR 使用并不真正对应于什么通常会与使用"相关联;例如,一个虚拟函数总是被 ODR 使用,除非它是纯函数,即使它不是实际上在程序中的任何地方调用.

It's just an arbitrary definition, used by the standard to specify when you must provide a definition for an entity (as opposed to just a declaration). The standard doesn't say just "used", because this can be interpreted diversely depending on context. And some ODR-use doesn't really correspond to what one would normally associate with "use"; for example, a virtual function is always ODR-used unless it is pure, even if it isn't actually called anywhere in the program.

完整定义在 §3.2,第二段,尽管这包含对其他部分的引用以完成定义.

The full definition is in §3.2, second paragraph, although this contains references to other sections to complete the definition.

关于模板,使用 ODR 只是问题的一部分;另一部分是实例化.特别是,§14.7 涵盖当模板被实例化时.但两者是相关的:而§14.7.1(隐式实例化)中的文本相当长,基本原则是模板只会在以下情况下被实例化它被使用,在这种情况下,使用意味着 ODR 使用.因此,类模板的成员函数只会被实例化如果它被调用,或者它是虚拟的并且类本身是实例化.标准本身在许多方面都依赖于此地方:std::list<>::sort 对个体使用 <元素,但您可以在元素类型上实例化列表不支持<,只要你不调用sort

With regards to templates, ODR-used is only part of question; the other part is instantiation. In particular, §14.7 covers when a template is instantiated. But the two are related: while the text in §14.7.1 (implicit instantiation) is fairly long, the basic principle is that a template will only be instantiated if it is used, and in this context, used means ODR-used. Thus, a member function of a class template will only be instantiated if it is called, or if it is virtual and the class itself is instantiated. The standard itself counts on this in many places: the std::list<>::sort uses < on the individual elements, but you can instantiate a list over an element type which doesn't support <, as long as you don't call sort on it.

相关文章