Как int()
а также int{}
являются постоянная выражения значения равны 0
Я думал, что они эквивалентны и взаимозаменяемы, поэтому компиляторы должны относиться к ним одинаково. Например,
int a[0]; //error: zero-sized array not allowed in ISO C++
int b[int()]; //error: zero-sized array not allowed in ISO C++
int c[int{}]; //error: zero-sized array not allowed in ISO C++
Но, похоже, в некоторых угловых случаях они не взаимозаменяемы.
При инициализации указателя:
int *p = 0; //ok
int *q = int(); //error - by clang only
int *r = int{}; //error - by gcc and clang both
Увидеть НКУ а также лязг Сообщения. Я подозреваю, что это ошибка в обоих компиляторах, так как я ожидаю, что они взаимозаменяемы в этом контексте, но я был бы рад оказаться ошибочным. 🙂
При переходе на шаблон класса:
template<int N> struct X{};
X<0> x1; //ok
X<int{}> x2; //ok (same as X<0>)
X<int()> x3; //error
Увидеть НКУ а также лязг Сообщения.
Я нахожу синтаксис X<int()>
довольно знакомый, как я видел (и, вероятно, использовал) подобный синтаксис ранее, такой как в std::function<int()>
аргумент шаблона int()
как ожидается, будет тип функции (вместо 0
не принимая аргументов и возвращаясь int
, Но я хочу знать раздел спецификации, который говорит в этом контексте int()
должен рассматриваться как функция тип и не эквивалентно int{}
который всегда 0
,
Выражения int()
а также int{}
оба являются значениями константных выражений целочисленного типа, которые оцениваются как ноль, и поэтому взаимозаменяемы с литералом 0
в любом контексте, где требуется целочисленное постоянное выражение prvalue целочисленного типа, которое оценивается как ноль.
Оба выражения удовлетворяют требованиям для константного выражения, как указано в 5.19 Выражения констант [expr.const].
относительно X<int()>
стандарт указывает, что int()
не интерпретируется как выражение в этом контексте:
14.3 Аргументы шаблона [temp.arg]
В Шаблон-аргумент, двусмысленность между тип-идентификатор и выражение решено к тип-идентификатор, независимо от формы соответствующего Шаблон-параметр.
Что касается преобразования указателей:
4.10 Преобразование указателей [conv.ptr]
Константа нулевого указателя является целочисленным константным выражением (5.19), имеющим тип целочисленного типа, равным нулю.
или тип значенияstd::nullptr_t
,
Исходя из вышеприведенного пункта, оба int()
а также int{}
являются константными выражениями нулевого указателя. Это указывает на (очень незначительную) ошибку компилятора, хотя существует открытый отчет о дефектах (903) что может привести к изменению этого абзаца:
Среди CWG был твердый консенсус в отношении того, что только литерал 0 следует считать константой нулевого указателя, а не произвольным константным выражением с нулевым значением, как указано в настоящее время.
Следующая формулировка касается значения выражения int()
:
8.5 Инициализаторы [dcl.init]
Инициализация с нуля объекта или ссылки типа T означает:
[пропущенные пункты, которые не применяются]— если T является скалярным типом (3.9), объекту присваивается значение 0 (ноль), принимаемое как интегральное постоянное выражение,
[…]
преобразован в TИнициализировать значение объекта типа T означает:
— если T является (возможно, cv-квалифицированным) типом класса (раздел 9) с предоставленным пользователем конструктором (12.1), то
[пропущенные пункты, которые не применяются]
вызывается конструктор по умолчанию для T (и инициализация некорректна, если T не имеет доступного по умолчанию
конструктор);— в противном случае объект инициализируется нулями.
Объект, инициализатором которого является пустой набор скобок, то есть (), должен быть инициализирован значением.
И для стоимости int{}
:
8.5.4 Инициализация списка [dcl.init.list]
Инициализация списка объекта или ссылки типа T определяется следующим образом:
— Если список инициализаторов не имеет элементов и T является типом класса с конструктором по умолчанию, объект
[пропущенные пункты, которые не применяются]
значение инициализации.— В противном случае, если в списке инициализатора нет элементов, объект инициализируется значением.
Все цитаты из C ++ Рабочий черновик стандарта N3337.
Других решений пока нет …