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

霸气de小男生 提交于 2019-11-30 07:56:31

问题


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.


回答1:


[basic.link]/3.2 applies to names of "a non-inline variable of non-volatile const-qualified type". A variable template isn't a variable, just like a class template isn't a class, a function template isn't a function, and a cookie cutter isn't a cookie. So that rule doesn't apply to the variable template is_integral_v itself.

A variable template specialization is a variable, however, so there are some questions about whether that rule gives it internal linkage. This is core issue 1713, the direction of which is that the rule is not applicable.

Core issue 1713, however, wasn't resolved in time for C++17. So LWG decided to simply plaster inline all over the variable templates just to be safe, because they don't hurt, either.




回答2:


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



来源:https://stackoverflow.com/questions/48041618/why-does-cppreference-define-type-traits-xxx-v-shortcuts-as-inline-constexpr-and

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!