Почему cppreference определяет ярлыки type_traits xxx_v как встроенный constexpr, а не просто constexpr?

Почему 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, Тогда вопрос действительно относится к стандарту.

15

Решение

[basic.link] /3.2 применяется к именам «не встроенных переменная энергонезависимого типа с константной квалификацией «. Шаблон переменной не является переменной, так же, как шаблон класса не является классом, шаблон функции не является функцией, а инструмент для обрезки файлов cookie не является файлом cookie. это правило не относится к шаблону переменной is_integral_v сам.

Шаблон переменной специализация это переменная, поэтому есть некоторые вопросы о том, дает ли это правило внутреннюю связь. Это основная проблема 1713, направление которого состоит в том, что правило не применимо.

Основная проблема 1713, однако, не была решена вовремя для C ++ 17. Поэтому LWG решил просто оштукатурить inline во всех шаблонах переменных просто для безопасности, потому что они тоже не вредят.

9

Другие решения

[Dcl.constexpr] / 9

Спецификатор constexpr, используемый в объявлении объекта, объявляет объект как const.

[Basic.link] /3.2

Имя, имеющее область имен внутренняя связь если это имя

не-рядный переменная энергонезависимой Уста-квалифицированы тип, который явно не объявлен как 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() разные, что является нарушением правила одного определения.

14

По вопросам рекламы [email protected]