为什么 cppreference 将 type_traits xxx_v 快捷方式定义为内联 constexpr 而不仅仅是 constexpr?

Why does cppreference define type_traits xxx_v shortcuts as inline constexpr and not just constexpr?

为什么 cppreference 将 type_traits xxx_v 快捷方式定义为 inline constexpr 而不仅仅是 constexpr

例如,参见 is_integral_v:

template< class T >
inline constexpr bool is_integral_v = is_integral<T>::value;

这只是风格问题还是行为上存在一些差异?据我所知 constexpr 变量是隐含的 inline.

编辑:看最新标准的草案,也是用inline constexpr。那么这个问题实际上适用于标准。

[dcl.constexpr]/9

A constexpr specifier used in an object declaration declares the object as const.

[basic.link]/3.2

A name having namespace scope has internal linkage if it is the name of

-a non-inline variable of non-volatile const-qualified type that is neither explicitly declared extern nor previously declared to have external linkage

没有 inline 说明符,is_integral_v 将具有内部链接。如果您比较两个指向不同翻译单元中相同变量名的指针,这可能会出现问题。


注意事项:仅当变量是 class 静态数据成员时,内联说明符才与 constexpr 冗余。


下面是一个很容易违反 one definition rule 的例子,如果 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.
  }

source1.cpp

#include "my_header.h"
void my_func1(){
   g(); //the definition of g in this translation unit.
   }

source2.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()的定义里面,使用了ODR变量bad_is_integral_v,所以g()的两个定义不一样,违反了一个定义的规则。

[basic.link]/3.2 适用于 "a non-inline variable of non-volatile const-qualified type" 的名称。变量模板不是变量,就像 class 模板不是 class、函数模板不是函数、千篇一律不是曲奇饼一样。因此该规则不适用于变量模板 is_integral_v 本身。

变量模板 specialization 是一个变量,但是,因此对于该规则是否为其提供内部链接存在一些疑问。这是core issue 1713,方向是规则不适用

然而,核心问题 1713 没有及时解决 C++17。所以 LWG 决定简单地在所有变量模板上涂抹 inline 以确保安全,因为它们也不会造成伤害。