Почему 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
, Тогда вопрос действительно относится к стандарту.
is_integral_v
сам.
Шаблон переменной специализация это переменная, поэтому есть некоторые вопросы о том, дает ли это правило внутреннюю связь. Это основная проблема 1713, направление которого состоит в том, что правило не применимо.
Основная проблема 1713, однако, не была решена вовремя для C ++ 17. Поэтому LWG решил просто оштукатурить inline
во всех шаблонах переменных просто для безопасности, потому что они тоже не вредят.
Спецификатор constexpr, используемый в объявлении объекта, объявляет объект как const.
Имя, имеющее область имен внутренняя связь если это имя
— не-рядный переменная энергонезависимой Уста-квалифицированы тип, который явно не объявлен как extern и не был ранее объявлен как имеющий внешнюю связь
Без inline
спецификатор, is_integral_v
будет иметь внутреннюю связь. Это может быть проблематично, если вы сравниваете два указателя с одним и тем же именем переменной, взятой в другой единице перевода.
Примечание: встроенный спецификатор избыточен с constexpr, только если переменная является членом статических данных класса.
После примера легкого нарушения одно определение правила это может произойти, если 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()
переменная bad_is_integral_v
используется ODR, поэтому два определения g()
разные, что является нарушением правила одного определения.