AVK AVK - 3 months ago 12
C++ Question

Explicit type conversion (functional notation) with simple-type-specifier

Porting some code I have discovered that line

unsigned char uc = unsigned char(c);


is accepted by MSVC but rejected by GCC. Is this syntax correct?

Standard says that


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


Does it mean that MS is right? Is
unsigned char
a 'simple-type-specifier'?

Answer

GCC is correct, the code is not valid.

Simple type specifiers is a single-word type name:

The simple type specifiers are

simple-type-specifier:
    nested-name-specifieropt type-name
    nested-name-specifier template simple-template-id
    nested-name-specifieropt 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 )

unsigned char is not a simple-type-specifier, it's a valid combination of simple-type-specifiers, as shown in this table from standard.

Table [tab:simple.type.specifiers] summarizes the valid combinations of simple-type-specifiers and the types they specify.

Table 9 — simple-type-specifiers and the types they specify

Specifier(s)  Type
...
unsigned char     “unsigned char” 
...

Here's an explanation from cppreference.com:

2) 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.