[dcl.constexpr]/9 http://eel.is/c++draft/dcl.constexpr#9
对象声明中使用的 constexpr 说明符将该对象声明为 const。
[基本.链接]/3.2 http://eel.is/c++draft/basic.link#3.2
具有名称空间范围的名称具有内部联系如果它的名字是
-a 非内联非易失性变量const 限定的既没有显式声明为 extern 也没有先前声明为具有外部链接的类型
Without inline
说明符,is_integral_v
会有内部联系。如果您将两个指针与在不同翻译单元中采用的同一变量名进行比较,这可能会出现问题。
注意:仅当变量是类静态数据成员时,内联说明符对于 constexpr 来说是多余的。
以下是一个容易违反规则的例子一个定义规则 http://eel.is/c++draft/basic.def.odr如果is_integral_v
不在内联的地方。
bad_type_trait.h
template<class T>
constexpr auto bad_is_integral_v=std::is_integral<T>::value;
my_header.h
#include "bad_type_trait.h"
void f(const bool& x);
inline void g()
{
f(bad_is_integral_v<int>);
//g ODR use the static variable bad_is_integral_v.
//"ODR use" approximate definition is:
// the variable is refered by its memory address.
}
源1.cpp
#include "my_header.h"
void my_func1(){
g(); //the definition of g in this translation unit.
}
源2.cpp
#include "my_header.h"
void my_func2(){
g(); //is not the same as the definition of g in this translation unit.
}
在两个翻译单元中,变量bad_is_integral_v
被实例化为单独的静态变量。内联函数g()
是在这两个翻译单元中定义的。在定义里面g()
,变量bad_is_integral_v
是使用ODR,所以两个定义g()
不同,这违反了单一定义规则。