模板 lambda 中的数组引用推导

问题描述 投票:0回答:1

我编写了一个简单的 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 问题吗?

c++ g++ c++20 clang++
1个回答
0
投票

这是我最喜欢的奇怪 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
等)

© www.soinside.com 2019 - 2024. All rights reserved.