大括号初始化列表和无符号类型

2022-01-19 00:00:00 initialization language-lawyer c++ c++14

gcc 8 和 clang 7 不接受以下代码,它们应该默认构造一个 unsigned int 类型的临时代码:

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报错如

<source>:6:22: error: expected primary-expression before 'unsigned'

Visual C++ 2015 和 2017 接受这一点.

Visual C++ 2015 and 2017 accept this.

显然,这适用于诸如 int 之类的类型,或任何默认可构造的类类型.

Obviously, this works with a type such as int, or any default-constructible class type.

这是正确的 C++14 代码吗(在这种情况下是 clang 和 gcc 的错误)?如果不是,为什么不呢?除了无符号类型,还有哪些类型会受到同样的限制?

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?

推荐答案

new_type { expression-list(optional) } like unsigned int{} 符合 显式类型转换,它只允许单字类型名称.

new_type { expression-list(optional) } like unsigned int{} fits the syntax of explicit type conversion, which allows only single-word type name.

一个单字类型名称后跟一个花括号初始化列表是指定类型的纯右值 指定一个临时的(直到 C++17) 其结果对象是(因为C++17) 使用指定的花括号初始化列表进行直接列表初始化.

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.

请注意,unsigned int 不是单字类型名称,而 int 是.所以 int {} 工作正常.

Note that unsigned int is not a single-word type name, while int is. So int {} works fine.

函数转换表达式也是如此,

函数转换表达式由一个简单类型说明符或一个 typedef 说明符组成(换句话说,一个单字类型名称:unsigned int(expression)int*(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) or int*(expression) are not valid),

作为一种解决方法,您可以应用类型别名,例如

As a workaround, you can apply type alias, e.g.

using type = unsigned int;
type ui = type{};

相关文章