1

Is there a way to pass default value to array which is passed by reference to a function so that passing it is not necessary?

I have a function like this:

void foo(int (&arr) [3])
{
    //some code...
}

Then i tried this:

void foo(int (&arr) [3] = nullptr)
{
    //some code...
}

but it obvoiusly didn't work because reference cannot be nullptr and it is not even an array.

EDIT: I would like not to use std::array if possible, and I also need to know the size of passed array without passing its size which is why I didn't do this: int (*arr)[3].

Kesto2
  • 70
  • 1
  • 13

2 Answers2

3

In C++, you cannot directly pass a default value to an array passed by reference. However, you can achieve a similar effect by overloading the function with a version that accepts a default array and calls the original function with it.

Here is a Code

void foo(int (&arr)[3]){}

void foo()
{
    int defaultArr[3] = {1, 2, 3};
    foo(defaultArr);
}
int main()
{
    int arr[3] = {2, 1, 4};
    foo(arr); 

    foo();     
    return 0;
}
3

I also need to know the size of passed array without passing its size which is why I didn't do this: int (*arr)[3].

This explanation doesn't make sense to me. The array size is encoded in the pointer type. Simply indirect through the pointer and you get a int (&arr) [3]. Example:

void foo(int (*arr)[3] = nullptr)
{
    if (arr)
        std::cout << std::size(*arr);
    else
        std::cout << "nullptr";
}

As such, using a pointer to array is an answer to your question.

Another option is to use an optional span:

void foo(std::optional<std::span<int, 3>> arr = std::nullopt)

While the parameter type is a bit more verbose, this allows you to pass an array directly without using the addressof operator. Furthermore, this allows passing other contiguous ranges too, not just arrays.


If you know at compile time that you want the default option, then I recommend using the overload solution in Syed's answer, but that won't work if the option is determined at runtime.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • 1
    Ehh "The array size is encoded in the pointer type" - not really; you cannot get the size of an array from a pointer. You'd need a `std::array` or `std::vector` for that - with a `.size()` member you can call. – Jesper Juhl Jun 18 '23 at 15:30
  • @JesperJuhl `you cannot get the size of an array from a pointer.` Yes, you can get the size from a pointer to array. `You'd need a std::array or std::vector for that` No, you don't need those. – eerorika Jun 18 '23 at 15:32
  • 1
    please demonstrate getting the array size from just a pointer to the first element of an array . *Prove* me wrong. – Jesper Juhl Jun 18 '23 at 15:34
  • @JesperJuhl I added an example. – eerorika Jun 18 '23 at 15:35
  • @JesperJuhl `from just a pointer to the first element of an array` Your mistake is thinking that `int (*arr)[3]` is a pointer to the first element of an array. It is **not**. It is a pointer to the whole array. – eerorika Jun 18 '23 at 16:01
  • 1
    @JeJo True, but then we have a template, which OP might need to avoid. But if template is not an issue, then it's good for generality indeed. The optional span version can be templated similarily. – eerorika Jun 18 '23 at 16:04
  • 1
    @JeJo `std::optional might require the caller side also to change/ use/ convert the arrays to optional type as well` The conversion is implicit and trivial. – eerorika Jun 18 '23 at 16:10
  • @eerorika Okay thanks, sorry that i didn't saw edit. – Kesto2 Jun 18 '23 at 16:13