转换为未知边界数组:g++ 与 clang++
Conversions to arrays of unknown bound: g++ vs. clang++
注意:这是 问题的后续问题。
示例代码(t334.cpp):
typedef int T0;
typedef T0 T1[];
typedef T1* T2[];
T1 x1 = { 13 };
T2 x2 = { &x1 };
调用:
$ g++ t334.cpp -std=c++11 -pedantic -Wall -Wextra -c
t334.cpp:6:11: warning: conversions to arrays of unknown bound are only available with ‘-std=c++20’ or ‘-std=gnu++20’ [-Wpedantic]
6 | T2 x2 = { &x1 };
| ^~~
$ clang++ t334.cpp -std=c++11 -pedantic -Wall -Wextra -c
t334.cpp:6:11: error: cannot initialize an array element of type 'T1 *' (aka 'T0 (*)[]') with an rvalue of type 'T0 (*)[1]'
T2 x2 = { &x1 };
^~~
谁能解释一下,这段 C++ 代码有什么问题?
注意:等效的 C 代码是有效的,因为 int (*)[]
和 int (*)[1]
是兼容的。这意味着在 C++ 中它们不是?
第一个定义是 known 边界的数组,它是从初始值设定项推导出来的。它与以下效果相同:
int x1[1] = {13};
这意味着 x1
的类型为 int[1]
,而 &x1
的类型为 int (*)[1]
。
第二个定义试图从 int (*)[1]
类型的 (brace-enclosed) 表达式初始化 int (*)[]
类型的变量。换句话说,它需要从指向具有已知边界的数组的指针转换为指向具有未知边界的数组的指针。
正如 GCC 告诉您的那样,这种类型的转换仅从 C++20 开始才被允许。如果您使用带有 -std=c++20
的最新版本的 Clang 编译您的代码,它应该可以编译。参见 https://godbolt.org/z/4zb5xx658
注意:这是
示例代码(t334.cpp):
typedef int T0;
typedef T0 T1[];
typedef T1* T2[];
T1 x1 = { 13 };
T2 x2 = { &x1 };
调用:
$ g++ t334.cpp -std=c++11 -pedantic -Wall -Wextra -c
t334.cpp:6:11: warning: conversions to arrays of unknown bound are only available with ‘-std=c++20’ or ‘-std=gnu++20’ [-Wpedantic]
6 | T2 x2 = { &x1 };
| ^~~
$ clang++ t334.cpp -std=c++11 -pedantic -Wall -Wextra -c
t334.cpp:6:11: error: cannot initialize an array element of type 'T1 *' (aka 'T0 (*)[]') with an rvalue of type 'T0 (*)[1]'
T2 x2 = { &x1 };
^~~
谁能解释一下,这段 C++ 代码有什么问题?
注意:等效的 C 代码是有效的,因为 int (*)[]
和 int (*)[1]
是兼容的。这意味着在 C++ 中它们不是?
第一个定义是 known 边界的数组,它是从初始值设定项推导出来的。它与以下效果相同:
int x1[1] = {13};
这意味着 x1
的类型为 int[1]
,而 &x1
的类型为 int (*)[1]
。
第二个定义试图从 int (*)[1]
类型的 (brace-enclosed) 表达式初始化 int (*)[]
类型的变量。换句话说,它需要从指向具有已知边界的数组的指针转换为指向具有未知边界的数组的指针。
正如 GCC 告诉您的那样,这种类型的转换仅从 C++20 开始才被允许。如果您使用带有 -std=c++20
的最新版本的 Clang 编译您的代码,它应该可以编译。参见 https://godbolt.org/z/4zb5xx658