I want to pass and return a 2D array of unknown size but I donot know how to do it. I know how to only return array of unknown size only (array of pointers). I know how to pass array of unknown size(templates) , but passing and returning a 2D array of unknown size at the same time is not working for me. I have the following code
template<typename Value_t, size_t FirstDim, size_t SecondDim>
int** FooTakes2D_ArrayRef_to_Print(Value_t (&array2d)[FirstDim][SecondDim])
{
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} };
int** arr=FooTakes2D_ArrayRef_to_Print(arr_d);
return 0;
}
CodePudding user response:
For starters you declared an array of doubles
double arr_d[][3]= { {1,2,3}, {4,5,6} };
but then are using the specifier int
in the
function declaration and in this statement.
int** arr=FooTakes2D_ArrayRef_to_Print(arr_d);
Pay attention to that array designators used in expressions with rare exceptions are implicitly converted to pointers to their first elements. So for example the array arr_d
can be implicitly converted to a pointer of the type double ( * )[3]
.
The function can look like
template<typename Value_t, size_t FirstDim, size_t SecondDim>
Value_t ( & FooTakes2D_ArrayRef_to_Print(Value_t (&array2d)[FirstDim][SecondDim]) )[FirstDim][SecondDim]
{
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;
}
That is it can return a reference to the source array.
Or like for example
template<typename Value_t, size_t FirstDim, size_t SecondDim>
Value_t ( * FooTakes2D_ArrayRef_to_Print(Value_t (&array2d)[FirstDim][SecondDim]) )[SecondDim]
{
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;
}
returning a pointer to the first element of the array.
In the both cases you can declare a pointer in main like
double (* arr )[3] = FooTakes2D_ArrayRef_to_Print(arr_d);
Here is a demonstration program
#include <iostream>
template<typename Value_t, size_t FirstDim, size_t SecondDim>
Value_t ( & FooTakes2D_ArrayRef_to_Print(Value_t (&array2d)[FirstDim][SecondDim]) )[FirstDim][SecondDim]
{
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;
}
template<typename Value_t, size_t FirstDim, size_t SecondDim>
Value_t ( * FooTakes2D_ArrayRef_to_Print2(Value_t (&array2d)[FirstDim][SecondDim]) )[SecondDim]
{
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} };
double (* arr )[3] = FooTakes2D_ArrayRef_to_Print(arr_d);
double (* arr2 )[3] = FooTakes2D_ArrayRef_to_Print2(arr_d);
}`
The program output is
1 2 3
4 5 6
1 2 3
4 5 6 `
Or you could use an alias for teh reference of the two-dimensional array the following way
#include <iostream>
template<typename Value_t, size_t FirstDim, size_t SecondDim>
using Arr2D = Value_t ( & )[FirstDim][SecondDim];
template<typename Value_t, size_t FirstDim, size_t SecondDim>
Arr2D<Value_t, FirstDim, SecondDim>
FooTakes2D_ArrayRef_to_Print(Arr2D<Value_t, FirstDim, SecondDim> 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;
}
template<typename Value_t, size_t FirstDim, size_t SecondDim>
auto FooTakes2D_ArrayRef_to_Print2(Arr2D<Value_t, FirstDim, SecondDim> 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} };
double (* arr )[3] = FooTakes2D_ArrayRef_to_Print(arr_d);
double (* arr2 )[3] = FooTakes2D_ArrayRef_to_Print2(arr_d);
}
CodePudding user response:
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);
}