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

C++ 在头文件中使用符合ODR的常量,c++,c++11,one-definition-rule,C++,C++11,One Definition Rule,通过查看,我意识到我不能通过头文件使用匿名名称空间中的对象或函数,因为这会导致类定义或内联函数中的ODR冲突。如果是这种情况,那么是否可以在内联函数或类中安全地使用命名的const或constepr静态对象?例如,如果常量位于下面的名称空间内,则不安全,但可以使用带有静态链接的常量吗 // some header file to be included by multiple .cpp files static const/*expr*/ int CONSTANT = 2; inline in

通过查看,我意识到我不能通过头文件使用匿名名称空间中的对象或函数,因为这会导致类定义或内联函数中的ODR冲突。如果是这种情况,那么是否可以在
内联
函数或类中安全地使用命名的
const
constepr
静态
对象?例如,如果
常量
位于下面的
名称空间
内,则不安全,但可以使用带有静态链接的常量吗

// 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])为:

D
的每个定义中,根据3.4查找的相应名称应指在
D
定义中定义的实体,或在重载解析和部分模板专门化匹配后指同一实体,但名称可指非易失性实体除外 如果对象在
D
的所有定义中具有相同的文字类型,并且该对象使用常量表达式初始化,并且该对象未使用odr,并且该对象在
D
的所有定义中具有相同的值,则该对象具有内部链接或无链接;及

此用法与“除……和……和……之外”部分中的所有条件都匹配:

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

“未使用odr”这一点应该是指“未在
f()
中使用odr”——也就是说,如果在程序的其他地方使用了
CONSTANT
,它不会中断
f()

至少在C++17中,这不再是一个问题。奇怪的是,类型别名可以解决您的问题:
使用CONSTANT=std::integral\u CONSTANT
@Barry从M.M为C++17 I gather删除的引用中删除的“对象未使用odr”?N4606(根据isocpp.org,这是最新的标准草案)仍然有“对象未使用odr”@M.M抱歉idk为什么我一开始认为它会。。等待巴里的response@RyanHainingN4606的日期在该文件之后,该文件与N4606之间的某些文本不同,因此我们需要小心。它的确切含义是“在
D
的定义中未使用odr”。