Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array Decays to Pointer in Lambda

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;
}

This code gives the following output:

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;
                                                                     ^

I want to stop int const arr[] from decaying into a pointer. If I use a reference, it requires a template to get the size, just like arraySize. Templates don't work with lambdas. Is this possible, or do I have to use a function instead, or pass the length as a parameter?


1 Answers

This is not decay. Decay is when an expression of array type is converted to a pointer.

The things in a function parameter list are not expressions; they are declarators. In this situation, an array declarator is adjusted to be a pointer declarator, e.g.:

void f(int const arr[]);

is equivalent to:

void f(int const *arr);

Lambdas are no exception to this; the lambda function behaves like a member function of a custom class holding the captured variables.


You may pass an array by reference, to avoid this adjustment:

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

Using C++14 generic lambdas, this option also receives the array by reference:

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

In this latter case, the const is also deduced thanks to reference collapsing.

As far as I know, it's not possible to have the lambda only accept an array but still deduce the array size.

like image 105
M.M Avatar answered Jan 02 '26 12:01

M.M



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!