Dan*_*nra 16 c++ language-lawyer c++17 inline-variable
为什么cppreference定义type_traits xxx_v快捷方式inline constexpr而不仅仅是constexpr?
例如,请参阅is_integral_v:
template< class T >
inline constexpr bool is_integral_v = is_integral<T>::value;
Run Code Online (Sandbox Code Playgroud)
这只是风格问题还是行为有所不同?据我所知,constexpr变量是隐含的inline.
编辑:查看最新标准的草案,它也使用inline constexpr.那么问题实际上适用于标准.
Oli*_*liv 14
对象声明中使用的constexpr说明符将对象声明为const.
具有命名空间作用域的名称具有内部链接(如果它的名称)
- 非易失性const限定类型的非内联变量,既未显式声明为extern,也未声明为具有外部链接
没有inline说明符,is_integral_v就会有内部联系.如果您将两个指针与在不同翻译单元中采用的相同变量名称进行比较,则可能会出现问题.
Nota Bene:只有当变量是类静态数据成员时,内联说明符才与constexpr冗余.
遵循一个简单违反一个定义规则的例子,如果is_integral_v不是内联的话可能会发生.
bad_type_trait.h
template<class T>
constexpr auto bad_is_integral_v=std::is_integral<T>::value;
Run Code Online (Sandbox Code Playgroud)
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.
}
Run Code Online (Sandbox Code Playgroud)
source1.cpp
#include "my_header.h"
void my_func1(){
g(); //the definition of g in this translation unit.
}
Run Code Online (Sandbox Code Playgroud)
source2.cpp
#include "my_header.h"
void my_func2(){
g(); //is not the same as the definition of g in this translation unit.
}
Run Code Online (Sandbox Code Playgroud)
在两个转换单元中,变量bad_is_integral_v被实例化为单独的静态变量.内联函数g()在这两个翻译单元中定义.在定义中g(),变量bad_is_integral_v是使用的ODR,因此两个定义g()是不同的,这违反了一个定义规则.