Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
370 views
in Technique[技术] by (71.8m points)

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

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

For example, see is_integral_v:

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

Is this just a matter of style or is there some difference in behavior? As far as I know constexpr variables are implicitly inline.

Edit: Looking at the draft of the latest standard, it also uses inline constexpr. The question actually applies to the standard, then.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

[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<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.
   }

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...