Standard behavior for direct initialization of unsigned short

  • A+

I noticed today that in the example code:

void print(unsigned short a) {    std::cout << a << std::endl; } 

Initialization and use works like this:

print(short (5)); 

But not like this:

print(unsigned short(6)); 

main.cpp:16:8: error: expected primary-expression before 'unsigned' print(unsigned short(6));

And it's not to do with the type since this also works:

typedef unsigned short ushort; print(ushort (6)); 

Live example.

So I went searching for what the standard says about value initialization. It turns out nothing:

The effects of value initialization are:

1) if T is a class type ...

2) if T is a non-union class type ...

2) if T is a class type ...

3) if T is an array type, ..

4) otherwise, the object is zero-initialized.

Modifications made for readability. Original source.

What are the rules about value initialization of POD types? What is the reason that unsigned qualified types can't be value initialized? Is this more to do with the fact they are rvalues?


What is the reason that unsigned qualified types can't be value initialized?

It's just because only single-word type name could be used in functional cast expression, while unsigned short is not a single-word type name; short is.

The functional cast expression consists of a simple type specifier or a typedef specifier (in other words, a single-word type name: unsigned int(expression) or int*(expression) are not valid), followed by a single expression in parentheses.

As you showed, you can use typedef as the workaround, or add parentheses to change it to c-style cast expression, e.g. (unsigned short)(6), or (unsigned short)6.

From the standard, § Explicit type conversion (functional notation) [expr.type.conv]:

A simple-type-specifier or typename-specifier followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer.

And simple-type-specifier:

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 


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: