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"