“ODR使用”是什么意思?

这只是在另一个问题的背景下出现的。

显然,类模板中的成员函数只有在使用ODR的情况下才会被实例化。 有人可以解释这到底是什么意思。 维基百科关于ODR的文章没有提到“ ODR使用 ”。

但标准将其定义为

名称出现在潜在评估expression式中的variables是odr-use,除非它是满足出现在常量expression式(5.19)中的要求并立即应用左值到右值转换(4.1)的对象。

在[basic.def.odr]中。

编辑:显然这是错误的部分,整个段落包含不同的东西的多个定义。 这可能与类模板成员函数有关:

如果从可能评估的expression式引用的过程被重载parsingselect,则其名称显示为可能评估的expression式或者候选函数集合中的成员的非重载函数是odr-used,除非它是纯虚拟函数和它的名字没有明确的限定。

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

这只是一个随意的定义,标准使用它来指定何时必须为实体提供定义(而不仅仅是声明)。 这个标准并没有说只是“使用”,因为这可以根据上下文的不同来解释。 而一些ODR使用并不真正对应于通常与“使用”相关联的东西。 例如,一个虚拟函数总是使用ODR,除非它是纯粹的,即使它并没有在程序中的任何地方被调用。

完整的定义在§3.2的第二段,尽pipe这包含了对其他章节的引用来完成定义。

关于模板,使用ODR只是问题的一部分; 另一部分是实例化。 特别是§14.7涵盖了一个模板被实例化的时候。 但是这两者是相关的:尽pipe第14.7.1节(隐式实例化)中的文本相当长,但基本原则是模板只有在被使用的情况下才会被实例化,在这种情况下,使用的是指使用ODR的模板。 因此,类模板的成员函数只有在被调用的时候才会被实例化,或者如果它是虚拟的并且类本身被实例化的话。 标准本身在许多地方都是这样的: std::list<>::sort在各个元素上使用< ,但是你可以在不支持<的元素types上实例化一个列表,只要你不用<不要打电话给它sort

简而言之,odr-used意味着在其定义必须存在的环境中使用某些东西(variables或函数)。

例如,

 struct F { static const int g_x = 2; }; int g_x_plus_1 = F::g_x + 1; // in this context, only the value of g_x is needed. // so it's OK without the definition of g_x vector<int> vi; vi.push_back( F::g_x ); // Error, this is odr-used, push_back(const int & t) expect // a const lvalue, so it's definition must be present 

注意,上面的push_back在MSVC 2013中传递,这种行为不符合标准,gcc 4.8.2和clang 3.8.0都失败了,错误信息是:未定义引用'K :: g_x'