C++14 中对数组的自动右值引用(不带 &&)
Auto Rvalue Reference (without &&) to an Array in C++14
post 的答案 1
How to declare array with auto 工作正常:
template<typename T> using unsized_raw_array = T[];
auto &&z = unsized_raw_array<int>{1, 2, 3};
尝试相同但没有双符号 (&&
) 会导致 clang 和 gcc 的不同行为:
template<typename T> using unsized_raw_array = T[];
auto z = unsized_raw_array<int>{1, 2, 3};
我预计这是一个错误,因为它是右值 (universal/forwarding/temporary-object) 引用并且缺少双符号 (&&
)。这就是 gcc 6.3.0 发生的情况:
error: taking address of temporary array
然而,clang 3.9.1 成功编译并执行了它,允许在接下来的语句中打印数组的值。我只收到此警告(在某些情况下我什至没有收到警告):
warning: pointer is initialized by a temporary array, which will be destroyed at the end of the full-expression [-Waddress-of-array-temporary]
哪个编译器是正确的?
实际上,两个编译器可能都是对的!虽然我不确定具体情况(有人愿意查找吗?),但在很多情况下 C++ 标准只需要提供任何诊断,但并不强制其中的特定情况,因此无论是错误还是警告只能符合标准。
此外,查看您的编译器标志 - 大多数(包括 GCC)编译器允许通过标志将警告转化为错误...
叮当是正确的;参见 [conv.array]:
An lvalue or rvalue of type “array of N
T
” or “array of unknown bound of T
” can be converted to a prvalue
of type “pointer to T
”. The result is a pointer to the first element of the array.
即使数组是临时数组,因此是纯右值,对其执行数组到指针的转换也是合法的。
似乎在解决 gcc bug 53220 的补丁中引入了将数组纯右值转换为指针的限制。似乎线程上出现了一个共识,即允许转换是危险的,因为从数组初始化指针变量不会延长数组的生命周期。但是,将此类代码视为格式错误的代码并不是正确的解决方案,因为正如稍后在线程中指出的那样,可以以安全的方式使用此转换,例如, 如果数组被传递给一个接受指针的函数(因此将一直存在到函数returns)。
您可能需要针对 gcc 提交一个新错误,以便他们解决问题。
post 的答案 1 How to declare array with auto 工作正常:
template<typename T> using unsized_raw_array = T[];
auto &&z = unsized_raw_array<int>{1, 2, 3};
尝试相同但没有双符号 (&&
) 会导致 clang 和 gcc 的不同行为:
template<typename T> using unsized_raw_array = T[];
auto z = unsized_raw_array<int>{1, 2, 3};
我预计这是一个错误,因为它是右值 (universal/forwarding/temporary-object) 引用并且缺少双符号 (&&
)。这就是 gcc 6.3.0 发生的情况:
error: taking address of temporary array
然而,clang 3.9.1 成功编译并执行了它,允许在接下来的语句中打印数组的值。我只收到此警告(在某些情况下我什至没有收到警告):
warning: pointer is initialized by a temporary array, which will be destroyed at the end of the full-expression [-Waddress-of-array-temporary]
哪个编译器是正确的?
实际上,两个编译器可能都是对的!虽然我不确定具体情况(有人愿意查找吗?),但在很多情况下 C++ 标准只需要提供任何诊断,但并不强制其中的特定情况,因此无论是错误还是警告只能符合标准。
此外,查看您的编译器标志 - 大多数(包括 GCC)编译器允许通过标志将警告转化为错误...
叮当是正确的;参见 [conv.array]:
An lvalue or rvalue of type “array of
N
T
” or “array of unknown bound ofT
” can be converted to a prvalue of type “pointer toT
”. The result is a pointer to the first element of the array.
即使数组是临时数组,因此是纯右值,对其执行数组到指针的转换也是合法的。
似乎在解决 gcc bug 53220 的补丁中引入了将数组纯右值转换为指针的限制。似乎线程上出现了一个共识,即允许转换是危险的,因为从数组初始化指针变量不会延长数组的生命周期。但是,将此类代码视为格式错误的代码并不是正确的解决方案,因为正如稍后在线程中指出的那样,可以以安全的方式使用此转换,例如, 如果数组被传递给一个接受指针的函数(因此将一直存在到函数returns)。
您可能需要针对 gcc 提交一个新错误,以便他们解决问题。