Why does cppreference define type_traits xxx_v shortcuts as inline constexpr
and not just constexpr
?
For example, see is_integral_v:
[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
Without inline
specifier, is_integral_v
would have internal linkage. This could be problematic if you compared two pointers to this same variable name taken in different translation unit.
Nota Bene: the inline specifier is redundant with constexpr only if the variable is a class static data member.
Following an exemple of easy violation of the one definition rule that could happen if is_integral_v
where not inline.
bad_type_trait.h
template
constexpr auto bad_is_integral_v=std::is_integral::value;
my_header.h
#include "bad_type_trait.h"
void f(const bool& x);
inline void g()
{
f(bad_is_integral_v);
//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.
}
In the two translation units, the variable bad_is_integral_v
is instantiated as separate static variables. The inline function g()
is defined in these two translation units. Inside the definition of g()
, the variable bad_is_integral_v
is ODR used, so the two definitions of g()
are different, which is a violation of the one definition rule.