web-dev-qa-db-ja.com

Cスタイルの配列を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の同様のエラー。

何が問題で、どうすれば修正できますか?

20
mans

パラメーター宣言では、int input[16]int* inputと同じです。そして、引数配列を渡すと ポインタへの減衰 になり、両方とも配列のサイズに関する情報が失われます。 std::begin および std::end は、ポインターでは機能しません。

配列のサイズを予約する参照渡しに変更できます。

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

16の正確なサイズの配列のみを関数に渡すことができることに注意してください。

40
songyuanyao

重要なことはすべて said すでに、関数をもう少し柔軟にすることができます:

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

(後期)編集:そこにis上記のアプローチの欠点:含まれていないため、割り当て時に返された配列をコピーする必要があります真に移動可能なデータ(生の配列でも同じです)。ターゲット配列に直接コピーすることにより、この欠点を回避できます。

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);
34
Aconcagua

すでに述べたように、ここで問題となるのは、配列が関数に渡されるとポインターに減衰することです。つまり、サイズが保持されません。

ただし、knew配列に16個の要素があった場合、これを行うことができます。

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