"ODR使用"是什么意思?

Sar*_*ien 79 c++ templates one-definition-rule

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

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

但是标准将其定义为

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

在[basic.def.odr]中.

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

一个非重载函数,其名称显示为可能已评估的表达式或一组候选函数的成员,如果从可能已评估的表达式引用时通过重载决策选择,则使用该函数,除非它是纯虚拟的函数及其名称未明确限定.

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

Jam*_*nze 64

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

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

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


zha*_*fei 17

简而言之,odr-used意味着某些东西(变量或函数)用于必须存在其定义的上下文中.

例如,

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
Run Code Online (Sandbox Code Playgroud)

请注意,在MSVC 2013通过上面的push_back,这种行为是不是符合标准,无论是GCC 4.8.2和3.8.0铿锵失败,错误消息是:未定义的引用'K :: g_x"

  • 简洁开头句子的+1:"简单来说,使用odr意味着某些东西(变量或函数)在必须存在它的定义的上下文中使用." (2认同)