Passing a Std::Array of Unknown Size to a Function

Passing a std::array of unknown size to a function


Is there a simple way to make this work, as one would with plain C-style arrays?

No. You really cannot do that unless you make your function a function template (or use another sort of container, like an std::vector, as suggested in the comments to the question):

template<std::size_t SIZE>
void mulArray(std::array<int, SIZE>& arr, const int multiplier) {
for(auto& e : arr) {
e *= multiplier;
}
}

Here is a live example.

How to pass an std::array with unknown size? in C++

If you know the array size in compile-time, as is implied by your usage of std::array, then you have templates to the rescue. To restrictively support std::arrays of int of different sizes you can do this:

#include <array>

template <size_t N>
void ArrayFunc(std::array<int, N> arr)
{
// Do something with `arr`
}

int main()
{
std::array<int, 10> arr10;
std::array<int, 20> arr20;

ArrayFunc(arr10);
ArrayFunc(arr20);

return 0;
}

Note the passing by value of the arr parameter of ArrayFunc(), a thing you should consider whether it is desired or not -- I was just following your example (in pseudo) in your question. If you don't really want to copy the entire std::array for each function call then you can do either:

template <size_t N>
void ArrayFunc(std::array<int, N>& arr)

or

template <size_t N>
void ArrayFunc(const std::array<int, N>& arr)

Depending on whether you will be modifying arr in the function or not.

Passing unknown size std::Array in a function with template. How can I correct this code?


I wrote this code using 2d Vector and Array.

That is appropriate, as you do not know the size of the matrix until run time.

But I wanted to use std::array this time [...]

Well, that's a problem because the size of a std::array must be known at compile time. Moving away from C-style arrays is a recommended move, but you have to know where to go. Use the correct tool for the job at hand.

Fixed-size arrays: For arrays whose size is known by the compiler, a std::array is a reasonable replacement. In fact, the std::array is probably nothing more than the C-style array with a different interface.

Variable-size arrays: For arrays whose size is not known until run time, a std::vector is a reasonable replacement. Even though the name does not say "array", it is an array. It is a bit more complex than std::array, but that is because it supports sizes not known at compile time.

This distinction tends to be better-known by those not using gcc, as that compiler has an extension that supports declaring variable-size C-style arrays using the same syntax as declaring fixed-size C-style arrays. It is standard C++ to declare an array along the lines of int col[10]. However, it is not standard C++ to declare an array along the lines of int col[sizeY], where sizeY has a value supplied at run time. The latter syntax is supported by gcc as an extension, and some people use it without realizing it is an extension (ported from gcc's C support). To some extent, std::vector makes this extension available in a more portable form.

Passing a std::array of unknown type and size to a constructor of a templated function

As state in comment, in C++17 it's valid to use:

std::array<uint16_t, 100> buffer;
Pipeline pipeline(buffer); // Pipeline<uint16_t, 100>

Earlier than C++17 you need to use a helper function:

template <typename T, std::size_t N>
Pipeline<T, N> make_pipeline(std::array<T, N>& buffer)
{
return Pipeline<T, N>(buffer);
}

auto pipeline = make_pipeline(buffer); // Pipeline<uint16_t, 100>

That assumes that your class is move (or copy) constructable.

Passing and Returning a 2D array of unknown size in C++

The problem is that the return type of your function is int** but you are returning array2d which decays to a double (*)[3] due to type decay. Thus, there is a mismatch in the specified return type of the function and the type you're actually returning.

To solve this you can either use std::vector or use the placeholder type auto as shown below:

template<typename Value_t, size_t FirstDim, size_t SecondDim> 
//auto used here
auto FooTakes2D_ArrayRef_to_Print(Value_t (&array2d)[FirstDim][SecondDim]) -> decltype(array2d)
{
for(size_t i=0; i<FirstDim; ++i)
{
for(size_t j=0; j<SecondDim; ++j)
{
std::cout<<array2d[i][j]<<' ';
}
std::cout<<"\n";
}

return array2d;
}
int main()
{

double arr_d[][3]= { {1,2,3}, {4,5,6} };
//auto used here
auto arr=FooTakes2D_ArrayRef_to_Print(arr_d);
}

Working demo

Passing array with unknown size to function

In C++ language, multidimensional array declarations must always include all sizes except possibly the first one. So, what you are trying to do is not possible. You cannot declare a parameter of built-in multidimensional array type without explicitly specifying the sizes.

If you need to pass a run-time sized multidimensional array to a function, you can forget about using built-in multidimensional array type. One possible workaround here is to use a "simulated" multidimensional array (1D array of pointers to other 1D arrays; or a plain 1D array that simulates multidimensional array through index recalculation).

std::array with unknown length as a type for template function specification

What about something like

template <typename T>
void foo (T const &)
{ std::cout << "foo generic" << std::endl; }

template <std::size_t Dim>
void foo (std::array<float, Dim> const &)
{ std::cout << "foo float array dim " << Dim << std::endl; }

?

The following is a full working example

#include <array>
#include <iostream>

template <typename T>
void foo (T const &)
{ std::cout << "foo generic" << std::endl; }

template <std::size_t Dim>
void foo (std::array<float, Dim> const &)
{ std::cout << "foo floar array dim " << Dim << std::endl; }

int main ()
{
foo(0);
foo(std::array<float, 12U>{});
}


Related Topics



Leave a reply



Submit