#c #language-lawyer #c 20
Вопрос:
У меня есть шаблон класса для N-мерного массива:
templatelt;typename T, std::size_t... Shapegt; class ndarray { ... };
Одним из следствий такого дизайна шаблона является наличие дополнительного «неявного» параметра шаблона , если хотите: std::size_t Size
, произведение всех аргументов в Shape
. Я использовал сложенное выражение C 17 ( (1 * ... * Shape)
), которое я обычно использовал Size
бы, если бы оно не зависело от Shape
, но мне интересно, приведет ли добавление следующего «псевдонима» к каким-либо незначительным различиям в скомпилированной сборке:
templatelt;typename T, std::size_t... Shapegt; class ndarray { static constinit std::size_t Size = (1 * ... * Shape); ... };
Интересно, что стандарт ISO C 20 не указывает, подразумевает ли это или нет constinit
inline
, как это делается для constexpr
и consteval
. Я думаю , что семантика constinit
(особенно в отношении constexpr
переменных) действительно имеет смысл только в том случае, если переменная также inline
была, но ее отсутствие в стандарте заставляет меня с осторожностью относиться к этому выводу.
Комментарии:
1. Почему бы вам вместо этого сделать его
constinit
переменнойconstexpr
? Планируете ли вы изменить его позже?2. @NicolBolas Вау! Ваш комментарий заставил меня взглянуть
constinit
еще раз, и сначала я совершенно неправильно его понял.
Ответ №1:
constinit
имеет ровно и только одну семантику: выражение, используемое для инициализации переменной, должно быть постоянным выражением.
Это оно. Это все, что он делает: он вызывает ошибку компиляции, если инициализирующее выражение не является допустимым постоянным выражением. Во всех других отношениях такая переменная идентична отсутствию constinit
там. Действительно, в ранних версиях предложения константа была атрибутом, а не ключевым словом, поскольку на самом деле она ничего не делала. Это только дало ошибку компиляции для недопустимой инициализации переменной.
В этом случае нет причин не делать переменную constexpr
. Вы явно не собираетесь изменять переменную, поэтому нет смысла изменять переменную.
Ответ №2:
Нет, это совсем не одно и то же, потому constinit
что не делает переменную переменной const
. Таким образом, инициализация Size
даже не является допустимой. Письмо constinit const
в основном эквивалентно письму constexpr
, которое семантически эквивалентно постоянному складчатому выражению. Нет никакой гарантии, что какой-либо компилятор обрабатывает их одинаково, но в большинстве случаев с постоянным выражением не так много места для вариаций.
constinit
также не подразумевает inline
: дело не в том, что стандарт «не указывает», просто нечего сказать. Поскольку нет смысла указывать constinit
и constexpr
на одну и ту же переменную, неясно, какую семантику вы ожидаете в этой области.