我编写了一个简单的 lambda 函数来将一个静态大小的数组复制到另一个
#include <tuple>
#include <iostream>
int main() {
constexpr auto copyArray = [](auto& out, const auto& in) noexcept {
[&]<size_t... Idxs>(std::index_sequence<Idxs...>) noexcept {
((out[Idxs]=in[Idxs]), ...);
}(std::make_index_sequence<std::min(std::size(out), std::size(in))>());
};
constexpr char c1[] = "dfjkwhjifehuiqh3iuhuihf3enewlknek32 ";
char c2[255]{0};
copyArray(c2, c1);
std::cout << (std::string(c2) == std::string(c1)) << "\n";
}
它在 GCC 中运行良好,但在 clang/msvc 中无法编译。
错误显示
non-type template argument is not a constant expression
,这基本上意味着 clang 无法计算出 in
和 out
的大小,但只有使用 std::size
,sizeof
才会给出正确的结果(编译器理解“真正的结果”)。 “数组的大小)。
据我了解,
in
和out
都定义为引用,应推导为char(&)[40]
和char(&)[255]
,因此大小应该在编译时可见。
是 clang/msvc 问题吗?
这是我最喜欢的奇怪 constexpr 问题:constexpr 数组大小问题,已由 P2280 解决。
简单来说,
std::size(in)
过去在常量表达式中使用是无效的,因为in
是常量求值器未知的引用。现在情况已经改变了——你实际上不需要以任何方式通读in
来找到答案,所以没有什么可以阻止它的工作。 gcc 显然在这里实现了修复,但 clang 还没有。
在此之前,您可以将 lambda 声明更改为:
constexpr auto copyArray = []<class T, size_t M, size_t M>(T (&out)[M], T const (&in)[M]) noexcept {
然后分别使用
M
和 N
代替 std::size(out)
和 std::size(in)
。或任何其他解决方法(包括仅使用 decltype(in)
并将其传递给 std::extent
等)