Почему я не могу скопировать массив C-style в std :: array?

У меня есть этот код:

 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;
}

Когда я пытаюсь скомпилировать этот код, я получаю эту ошибку:

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

и аналогичная ошибка для std::end.

В чем проблема и как я могу это исправить?

Ответ 1

В объявлении параметра int input[16] совпадает с int* input. И когда вы передаете массив аргументов, он будет распадаться на указатель, оба означают, что информация о размере массива теряется. И std::begin и std::end не могут работать с указателями.

Вы можете изменить его на передачу по ссылке, которая резервирует размер массива.

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

Обратите внимание, что вы можете передать массив только с точным размером 16.

Ответ 2

Все важное уже сказано, вы можете сделать функцию чуть более гибкой:

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;
}

(Позднее) редактирование: у подхода, описанного выше, есть недостаток: вам нужно будет копировать возвращенный массив при присваивании, так как он не содержит действительно перемещаемых данных (то же самое уже для необработанных массивов). Вы можете избежать этого недостатка, непосредственно копируя в целевой массив:

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));
}

Это имитирует назначение target = source; если вам нравится больше, вы можете поменять местами параметры, чтобы выходной параметр был последним.

Использование (как есть):

int source[7] = { };
std::array<int, sizeof(source)/sizeof(*source)> target;
copyarray(target, source);

Ответ 3

Как уже говорилось, проблема здесь заключается в том, что массивы распадаются на указатели при передаче функции, что означает, что размер не сохраняется.

Если бы вы знали, что в массиве было 16 элементов, вы могли бы это сделать:

array<int,16> copyarray(const int input[]) {
    array<int, 16> result;
    copy_n(input, size(result), begin(result));
    return result;
}