在符合 ODR 的头文件中使用常量

using constants in header file with ODR compliance

查看 another question 我意识到我不能通过头文件使用来自匿名名称空间的对象或函数,因为它会导致 class 定义或内联函数中的 ODR 违规。如果是这种情况,那么是否可以在 inline 函数或 classes 中安全地使用命名 constconstexpr static 对象?例如,如果 CONSTANT 在下面的 namespace 内,那将是不安全的,但是可以使用带有静态链接的常量吗?

// some header file to be included by multiple .cpp files
static const/*expr*/ int CONSTANT = 2;

inline int f() {
  return CONSTANT;
}

class Cls {
  int mem = CONSTANT;
};

这段代码没问题。完整段落 (C++14 [basic.def.odr/6.2]) 是:

in each definition of D, corresponding names, looked up according to 3.4, shall refer to an entity defined within the definition of D, or shall refer to the same entity, after overload resolution and after matching of partial template specialization, except that a name can refer to a non-volatile const object with internal or no linkage if the object has the same literal type in all definitions of D, and the object is initialized with a constant expression, and the object is not odr-used, and the object has the same value in all definitions of D; and

这种用法确实符合 "except ... and ... and ..." 部分中的所有条件:

  • 名称 CONSTANT 实际上是指具有内部链接的非易失性 const 对象
  • 它在f()的所有定义中具有相同的文字类型。
  • 它是用常量表达式2初始化的。
  • 它不是 odr-used
  • 它在f()的所有定义中具有相同的值。

点 "It is not odr-used" 应该意味着 "It is not odr-used within f()" —— 即它不会破坏 f() 如果你碰巧 odr-use CONSTANT 在程序的其他地方。