21

I have this code:

 std::array<int,16> copyarray(int input[16])
{
    std::array<int, 16> result;
    std::copy(std::begin(input), std::end(input), std::begin(result));
    return result;
}

When I try to compile this code, I am getting this error:

'std::begin': no matching overloaded function found 

and a similar error for std::end.

What is the problem and how I can fix it?

Boann
  • 48,794
  • 16
  • 117
  • 146
mans
  • 17,104
  • 45
  • 172
  • 321
  • 2
    Size of array parameter does not work this way, it is equal to `int *input` – Slava May 23 '18 at 13:29
  • @Slava How to fix it? – mans May 23 '18 at 13:30
  • 9
    Simply don't use C style arrays. They don't know their size and get converted to pointers when used as function parameters. No `std::begin` overload accepts pointer type. – Ron May 23 '18 at 13:34
  • 2
    @Ron Avoiding arrays might be the intention of the question - possibly there is an array somewhere in code mans cannot change? – Aconcagua May 23 '18 at 13:51
  • see https://stackoverflow.com/a/26219764/2785528 – 2785528 May 23 '18 at 14:11
  • Possible duplicate -- https://stackoverflow.com/q/26219721/2785528 – 2785528 May 23 '18 at 14:15
  • 1
    You can also copy between them with `std::memcpy( result.data(), input, sizeof(input) );` It might be a good habit to define both array sizes as the same `constexpr size_t` value. If you retype `16` in multiple places, and they get out of sync, you would have a buffer overflow or underflow. – Davislor May 23 '18 at 21:01

3 Answers3

41

In parameter declaration, int input[16] is same as int* input. And when you pass argument array would decay to pointer, both mean the information about size of the array is lost. And std::begin and std::end can't work with pointers.

You could change it to pass-by-reference, which reserve the array's size.

std::array<int,16> copyarray(int (&input)[16])

Note that you can only pass array with exact size of 16 to the function now.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
34

Everything important said already, you can get the function just a little bit more flexible:

template <typename T, size_t N>
std::array<T, N> copyarray(T const (&input)[N])
{
    std::array<T, N> result;
    std::copy(std::begin(input), std::end(input), std::begin(result));
    return result;
}

(Late) edit: There is a disadvantage with the approach above: You'll need to copy the returned array on assignment, as it doesn't contain any truely movable data (that's the same for raw arrays already). You can avoid this drawback by directly copying into the target array:

template <typename T, size_t N>
void copyarray(std::array<T, N>& target, T const (&source)[N])
{
    std::copy(std::begin(source), std::end(source), std::begin(target));
}

This mimicks the assignment target = source; if you like better, you can swap the parameters, of course, to have the output parameter last.

Usage (as is):

int source[7] = { };
std::array<int, sizeof(source)/sizeof(*source)> target;
copyarray(target, source);
Aconcagua
  • 24,880
  • 4
  • 34
  • 59
  • template it is from to `std::array` definition – Ulrich Von Rekkenin May 24 '18 at 15:09
  • @UlrichVonRekkenin What are you trying to tell with? Template parameters are the same because they need to be, how else could you have a generic reference to an array? The pattern yet occurs at many other locations, too - have you looked at the std::begin/end variants for arrays, for example? – Aconcagua May 25 '18 at 10:24
1

As stated already the problem here is that arrays decay to pointers when passed to a function, meaning that the size is not preserved.

If however you knew that there were 16 elements in the array you could do this:

array<int,16> copyarray(const int input[]) {
    array<int, 16> result;
    copy_n(input, size(result), begin(result));
    return result;
}    
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • You can preserve size using `template array copyarray(const int (&input)[N]) { ... }` if you aren't attached to 16. Edit -- Aconcagua parametrized this way but with `class T` instead of `int` as well. – John P May 23 '18 at 14:40
  • @JohnP Yup, just presenting this as an alternative. – Jonathan Mee May 23 '18 at 14:46