数组衰减为Lambda指针

Array Decays to Pointer in Lambda

本文关键字:指针 Lambda 衰减 数组      更新时间:2023-10-16
template<std::size_t size>
constexpr std::size_t arraySize(int const (&)[size])
{
    return size;
}
int main()
{
    auto const lambda = [](int const arr[]) -> void
    {
        std::cout << "The length of the array is: " << arraySize(arr) << std::endl;
    };
    lambda({1, 2, 3});
    return 0;
}

这段代码给出如下输出:

main.cpp: In lambda function:
main.cpp:23:69: error: no matching function for call to 'arraySize(const int*&)'
         std::cout << "The length of the array is: " << arraySize(arr) << std::endl;
                                                                     ^
main.cpp:12:23: note: candidate: template<long long unsigned int size> constexpr std::size_t arraySize(const int (&)[size])
 constexpr std::size_t arraySize(int const (&)[size])
                       ^
main.cpp:12:23: note:   template argument deduction/substitution failed:
main.cpp:23:69: note:   mismatched types 'const int [size]' and 'const int*'
         std::cout << "The length of the array is: " << arraySize(arr) << std::endl;
                                                                     ^

我想阻止int const arr[]衰变为指针。如果我使用引用,它需要一个模板来获取大小,就像arraySize一样。模板不能与lambdas一起工作。这是可能的,还是我必须使用一个函数来代替,或者传递长度作为参数?

这不是衰变。衰减是指将数组类型的表达式转换为指针。

函数形参列表中的内容不是表达式;他们是声明者。在这种情况下,数组声明符调整为指针声明符,例如:

void f(int const arr[]);

等价于:

void f(int const *arr);

lambda也不例外;lambda函数的行为类似于保存捕获变量的自定义类的成员函数。


你可以通过引用传递一个数组,以避免这种调整:

auto const lambda = [](int const (&arr)[size]) -> void

使用c++ 14泛型lambdas,该选项还通过引用接收数组:

auto const lambda = [](auto& arr) -> void

在后一种情况下,由于引用坍缩,const也被推导出来。

据我所知,不可能让lambda 接受数组,但仍然推断数组的大小。

根据您希望使用的数组大小的不同,您可能需要不同的解决方案。

如果你需要的数组大小在编译时是已知的,我会考虑的一件事是使用std::array,也就是说,创建一个模板函数,生成一个适当的lambda函数,该函数接受特定大小的std::array。并使用lambda函数来处理该大小的数组。

如果可能的数组的大小在编译时不知道,那么我想我会建议将std::vector传递给lambda。