Вперед объявить шаблон переменной constexpr

Я попытался объявить шаблон переменной constexpr следующим образом:

template<typename>
constexpr std::size_t iterator_category_value;

Цель состояла в том, чтобы задокументировать, что каждая специализация должна быть constexpr, но я должен признать, что я никогда не проверял, является ли она законной или нет, и g++ был доволен этим. Однако, когда я попытался скомпилировать эту сеть с помощью clang++, я получил следующую ошибку:

error: default initialization of an object of const type 'const std::size_t' (aka 'const unsigned long')
    constexpr std::size_t iterator_category_value;
                          ^
                                                  = 0

Ошибка имеет смысл, и удаление constexpr приводит к ее исчезновению, так что это не проблема. Однако теперь мне любопытно: разрешает ли стандарт такое constexpr предварительное объявление для шаблона переменной или это незаконно? g++ и clang++, кажется, не согласны, и я хотел бы знать, куда я должен отправить отчет об ошибке, если это необходимо.

Оба они жалуются на предварительно объявленную переменную constepxr, которая не является шаблоном переменной, поэтому контекст шаблона переменной, похоже, вызывает разногласия между компиляторами.


person Morwenn    schedule 18.10.2015    source источник
comment
Текст wg21.cmeerw.net/cwg/issue1712 подразумевает, что вы не можете предварительно объявить об этом как constexpr, однако я не совсем уверен, как стандарт запрещает это. Шаблон переменной не похож на объявление объекта для меня.   -  person dyp    schedule 18.10.2015
comment
OTOH, [dcl.dcl]p9 кажется очень общим и должен применяться к шаблонам переменных (=> шаблоны переменных являются объявлениями объектов => constexpr требует инициализации)   -  person dyp    schedule 18.10.2015
comment
@dyp Кстати, что ты имеешь в виду? Разве вы не компилируете самые последние исходные коды, доступные в настоящее время на Git?   -  person Columbo    schedule 18.10.2015
comment
@Колумбо Не регулярно :)   -  person dyp    schedule 18.10.2015
comment
@dyp Да, объявление шаблона переменной, являющееся объявлением объекта, было для меня не совсем очевидным, отсюда и вопрос:/   -  person Morwenn    schedule 18.10.2015


Ответы (2)


В стандарте С++ 14 кажется довольно ясным, что требуется инициализация. Из раздела 7.5.1 параграф 9,

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

Что касается точного значения «объявления объекта», в параграфе 7 раздела 7 говорится:

Если decl-specifier-seq не содержит спецификатора typedef, объявление называется объявлением функции, если тип, связанный с именем, является типом функции, и объявлением объекта в противном случае.

person Vaughn Cato    schedule 18.10.2015

Кланг прав. объявление шаблона переменной является объявлением объекта ([dcl.dcl]/9), поэтому оно должно предоставлять инициализатор согласно [dcl.constexpr]/9:

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

Тем не менее, фактически нет никакого способа «вперед» объявить объект как constexpr в первую очередь; Если constexpr применяется к объявлению переменной, это должно быть определение ([dcl.constexpr]/1).

person Columbo    schedule 18.10.2015
comment
comment
Просто код, содержащий обсуждаемый случай. Он содержит предварительное объявление шаблона переменной constexpr, но компилируется нормально. - person Tomilov Anatoliy; 25.11.2015
comment
@Orient Вы понимаете, что компилируете с помощью компилятора с ошибками в этом отношении? - person Columbo; 25.11.2015
comment
Да, но это изменение введено в недалеком прошлом, я думаю. Наверное намеренно. Но, может быть, и нет. - person Tomilov Anatoliy; 25.11.2015
comment
@Orient Ну, GCC только начал поддерживать все функции, используемые начиная с 5.2, и эта версия уже ложно компилирует этот штраф. - person Columbo; 25.11.2015