Стандартное поведение для прямой инициализации unsigned short
Я заметил сегодня, что в примере кода:
void print(unsigned short a) {
std::cout << a << std::endl;
}
Инициализация и использование работает следующим образом:
print(short (5));
но не такой:
print(unsigned short(6));
main.cpp: 16: 8: Ошибка: ожидаемое первичное выражение перед "unsigned" print (unsigned short (6));
и это не связано с типом, так как это также работает:
typedef unsigned short ushort;
print(ushort (6));
поэтому я пошел искать то, что стандарт говорит об инициализации значения. Получается ничего:
эффекты инициализации значения:
1) Если T-тип класса ...
2) Если T-тип класса без объединения ...
2) Если T-тип класса ...
3) Если T-тип массива,..
4) иначе, объект инициализирован нулем.
модификации для удобочитаемость. первоисточник.
каковы правила инициализации значения POD типы? В чем причина того, что unsigned
квалифицированные типы не могут быть инициализированы значением? Это связано с тем, что они являются rvalues
?
2 ответов
в чем причина этого
unsigned
квалифицированные типы не могут быть инициализированы значением?
это просто потому, что в функциональное выражение cast, а unsigned short
не является именем типа одного слова;short
есть.
функциональное выражение cast состоит из простого спецификатора типа или спецификатора typedef (другими словами, однословное имя типа:
unsigned int(expression)
илиint*(expression)
не действительны), далее следует одно выражение в скобках.
как вы показали, вы можете использовать typedef
в качестве обходного пути или добавьте скобки, чтобы изменить его на выражение C-style cast, например (unsigned short)(6)
или (unsigned short)6
.
из стандартного, §7.6.1.3 / 1 явное преобразование типов (функциональная нотация) [expr.тип.conv]:
A простой-тип-описатель или параметр typename-описатель после чего в скобках необязательный expression-list или braced-init-list (инициализатор) создает значение указанного типа, заданного инициализатором.
simple-type-specifier: nested-name-specifier opt type-name nested-name-specifier template simple-template-id nested-name-specifier opt template-name char char16_t char32_t wchar_t bool short int long signed unsigned float double void auto decltype-specifier type-name: class-name enum-name typedef-name simple-template-id decltype-specifier: decltype ( expression ) decltype ( auto )
typename-specifier: typename nested-name-specifier identifier typename nested-name-specifier template opt simple-template-id
это просто сбой в грамматике: два имени типа слов не работают при создании временных объектов. То есть ни одна из этих работ
template <typename T> void use(T);
int main() {
use(unsigned int());
use(const int());
use(long long());
}
обходной путь заключается в использовании псевдонима для соответствующего типа, т. е. все они работают:
template <typename T> void use(T);
int main() {
{ using type = unsigned int; use(type()); }
{ using type = const int; use(type()); }
{ using type = long long; use(type()); }
}
скобки также могут использоваться для инициализации значения, хотя требуется использование завитушек:
template <typename T> void use(T);
int main() {
use((unsigned int){});
use((const int){});
use((long long){});
}