这恰好出现在another question。
的背景下显然,类模板中的成员函数只有在使用ODR时才会被实例化。 有人可以解释一下究竟是什么意思。 wikipedia article on One Definition Rule (ODR)未提及“ ODR-use ”。
但是标准将其定义为
[basic.def.odr]中的一个变量,其名称显示为可能已评估的表达式 是 odr-used ,除非它是满足要求的对象 出现在常量表达式(5.19)和左值到右值 转换(4.1)立即应用。
。
编辑:显然这是错误的部分,整个段落包含不同内容的多个定义。这可能是类模板成员函数的相关内容:
非重载函数,其名称显示为 潜在评估的表达或一组候选人的成员 函数,如果从a引用时通过重载决策选择 可能被评估的表达,是有用的,除非它是纯粹的 虚函数及其名称未明确限定。
但我不明白,这条规则如何在多个编译单元中工作?如果我显式实例化一个类模板,是否会实例化所有成员函数?
答案 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;