问题
gcc 8 and clang 7 do not accept the following code, which should default-construct a temporary of type unsigned int
:
unsigned int ui = unsigned int{};
clang 7 reports an error such as
<source>:6:22: error: expected primary-expression before 'unsigned'
Visual C++ 2015 and 2017 accept this.
Obviously, this works with a type such as int
, or any default-constructible class type.
Is this correct C++14 code (and in that case a bug of clang and gcc)? If not, why not? Which types other than unsigned types would suffer from the same restriction?
回答1:
new_type { expression-list(optional) }
like unsigned int{}
fits the syntax of explicit type conversion, which allows only single-word type name.
A single-word type name followed by a braced-init-list is a prvalue of the specified type
designating a temporary (until C++17)
whose result object is (since C++17)
direct-list-initialized with the specified braced-init-list.
Note that unsigned int
is not a single-word type name, while int
is. So int {}
works fine.
This is same for functional cast expression,
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)
orint*(expression)
are not valid),
As a workaround, you can apply type alias, e.g.
using type = unsigned int;
type ui = type{};
回答2:
"Int" is optional in "unsigned int".
Try simply:
unsigned ui = unsigned{};
It works.
Edit: I found this answer: Standard behavior for direct initialization of unsigned short
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.
来源:https://stackoverflow.com/questions/53336344/braced-init-list-and-unsigned-types