3

I am trying to pass an array to a lambda expression, where I want to print it out. I don't understand how to pass the array into the function. The problem seems to be rooted at the conversion of the array when it is passed to the lambda function. This is the current state of the function:

int actual_array[5] = {7,8,9,2,1};
const int actual_i = 3;

auto print_array = [](int &array, int i) -> int {

    //print out array

    return 0;

}(&actual_array, actual_i);
1
  • 1
    int& array is a reference to an integer, not anything that resembles an array. Commented Sep 11, 2018 at 16:22

3 Answers 3

4

You can't pass an array by value, and your syntax for passing a pointer is all wrong.

It's actually easy to pass a pointer or reference to an array though. With generic lambdas you can ignore the fact that the dimension is part of the type and just simply write:

#include <iostream>

int main()
{
    int actual_array[5] = {7,8,9,2,1};
    const int actual_i = 3;

    auto print_array = [](auto& ar, int i) {
        std::cout << ar[i] << '\n';
    };

    print_array(actual_array, actual_i);
}

In this example, the print_array instantiation that you call is accepting a int(&)[5], hidden behind the auto&.

If you can't abide by the generic lambda (which is basically a template) for some reason, then go old-school:

#include <iostream>

int main()
{
    int actual_array[5] = {7,8,9,2,1};
    const int actual_i = 3;

    auto print_array = [](const int* ar, int i) {
        std::cout << ar[i] << '\n';
    };

    print_array(&actual_array[0], actual_i);
}

None of this is specific to lambdas. It's the same for any function.

Sign up to request clarification or add additional context in comments.

Comments

1

Declare a lambda variable that takes an array (and length) as parameters;

using namespace std;

auto print_array = [](const int *items, int length) {
    for (int i = 0; i < length; i++)
    {
        cout << items[i] << endl;
    }
};

To Invoke:

int myArray[] = { 11,22,33,44 };
print_array(myArray, 4);

Comments

1

An array cannot be a function argument.

Furthermore, an int reference cannot bind to an array of int. Nor could an integer reference be used as an array.

However, a pointer can be accessed with a subscript operator in much the same way as an array can. The name of the array actually implicitly converts to the pointer to first element. This conversion is called decaying:

int array[n];
int* ptr_to_first_element = array;
assert(ptr_to_first_element[i] == array[i]);

So, you can use an integer pointer as a function argument, and pass a pointer to the first element of an array:

void foo(int *array, std::size_t size);
// ...
int array[n];
foo(array, n);

All of the above applies to lambdas as well. So you could write:

auto print_array = [](int *array, int i) -> int {
    //                    ^ notice this

    //print out array using the pointer

    return 0;

}(&actual_array, actual_i);

You can however have a reference-to-array-of-certain-size as an argument to a function:

void foo(int (&array)[20]);

This is a bit limiting, since the reference can only bind to an array of one particular size. A template makes it simple to generate such function for any size of array:

template<std::size_t size>
void foo(int (&array)[size]);

Polymorphic lambdas (introduced in C++14) simplify this greatly:

int actual_array[10];
auto print_array = [](auto &array, int i) -> int {
    //                ^^^^^^ notice this

    //print out the referred array

    return 0;

}(&actual_array, actual_i);

In this case, the type of array argument would be deduced to be int (&)[10].


P.S. "print out" the array sounds like something that doesn't need to modify the array. Consider this and if possible, use a const pointer to first element or const reference as the argument.

Note that the std::array wrapper is a class, not an array. As such, std::wrapper does not implicitly decay to pointer, and std::array can be used as a function argument if so is desired.

2 Comments

"An array cannot be a function argument." By reference it can, and that's actually what I'd recommend here. Have the arg be auto& and you're set.
If you want to pass it by reference without auto, the syntax would look like: auto print_array = [](int (&array)[SIZE], int i) -> int { ... }. Note that SIZE must be known at compile time in this case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.