“ODR使用”是什么意思?

时间:2013-10-28 08:58:47

标签: c++ templates one-definition-rule

这恰好出现在another question

的背景下

显然,类模板中的成员函数只有在使用ODR时才会被实例化。 有人可以解释一下究竟是什么意思。 wikipedia article on One Definition Rule (ODR)未提及“ ODR-use ”。

但是标准将其定义为

  

一个变量,其名称显示为可能已评估的表达式   是 odr-used ,除非它是满足要求的对象   出现在常量表达式(5.19)和左值到右值   转换(4.1)立即应用。

[basic.def.odr]中的

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

  

非重载函数,其名称显示为   潜在评估的表达或一组候选人的成员   函数,如果从a引用时通过重载决策选择   可能被评估的表达,是有用的,除非它是纯粹的   虚函数及其名称未明确限定。

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

2 个答案:

答案 0 :(得分:60)

这只是标准使用的任意定义 指定何时必须为实体提供定义(如 反对只是宣言)。标准不仅仅是说 “使用”,因为这可以根据不同的解释来解释 上下文。一些ODR使用并不真正对应于什么 通常会与“使用”联系在一起;例如,一个虚拟的 函数总是使用ODR,除非它是纯粹的,即使它不是 实际上在程序的任何地方调用。

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

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

答案 1 :(得分:14)

简单来说,使用odr意味着在必须存在定义的上下文中使用某些东西(变量或函数)。

例如,

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&#39;