2017-06-11 26 views
3

私は(十分なスペースがあると仮定)ダブルスのstd::vectorを取る機能があり、別のベクトルにコピーしますが、特定のオフセット:これはC++ 11打ち鳴らすコンパイラになりC++:std :: vector iteratorにオフセットするための正しいキャストは何ですか?

void copy_stuff(const std::vector<double> & data, 
       std::vector<double> & dest, 
       size_t dest_offset) { 
    std::copy(data.begin(), data.end(), dest.begin() + dest_offset); 
} 

+ dest_offset部分を中心に-Weverything警告:

Implicit conversion changes signedness: 'size_t' (aka 'unsigned long') to 'difference_type' (aka 'long').

は、私はこの警告を解消するために、発現dest.begin() + dest_offsetをキャストする必要がありかどうかはわかりません。 double *に結果をキャストすると、コンパイルされません:

std::copy(data, data + data_size, static_cast<double *>(dest.begin() + dest_offset)); 

Cannot cast from type 'std::__1::__wrap_iter' to pointer type 'double *'.

を私はベクトルのインデックスを使用して検討し、その後、アドレスを取っていました:

std::copy(data, data + data_size, &dest[dest_offset]); 

これは、この場合に警告を排除するようだが、ソースベクトルで同じパターンを使用しようとすると、つまり、最初のパラメータまたは第2引数に含まれるオフセットがstd::copyになると、コンパイルされません。たとえば、

static void copy_stuff_differently(const std::vector<double> & data, 
            std::vector<double> & dest, 
            size_t offset) { 
    std::copy(data.begin() + offset, data.end(), dest.begin()); 
} 

+ offsetで暗黙の変換についての元の警告が表示されます。

std::copy(&data[offset], data.end(), dest.begin()); 

それとも異なるが、同様のケース:しかし

std::copy(data.begin(), &data[offset], dest.begin()); 

両方が同様のエラーが発生:私は

test.cpp:8:3: error: no matching function for call to 'copy' 
    std::copy(&data[offset], data.end(), dest.begin()); 
    ^~~~~~~~~ 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iterator:1286:48: note: 
     candidate template ignored: deduced conflicting types for parameter '_Ip' ('const double *' vs. 
     'std::__1::__wrap_iter<const double *>') 
    template <class _Ip, class _Op> friend _Op copy(_Ip, _Ip, _Op); 
              ^

を示唆するかもしれないアドレスのインデックスを使用しようとすると、そのようなオフセットを処理する一貫性のある、警告のない方法を探していました。ベクトルへのオフセットを処理し、そのようなエラーや警告を避ける正しい方法は何ですか?

+1

非常に明示的に言えば、***使用しないでください - すべてを使用する必要があります。 –

+0

'std :: next(std :: begin()、dest_offset)'は何かを変更しますか? –

答えて

3

I'm not sure how I should cast the expression dest.begin() + dest_offset in order to eliminate this warning.

警告がちょうどdest_offsetがタイプstd::vector::difference_typeであることが期待されていることを言っているが、それはsize_tです。

明示的に変換を実行して警告を取り除くことができます(ソース値がdifference_typeで表現できない場合、結果は実装定義です)。例えば

dest.begin() + static_cast<std::vector<double>::difference_type>(dest_offset) 

それとも最初からタイプdifference_typeでパラメータdest_offsetを宣言します。

std::vector::difference_typeは符号付き整数型(通常はstd::ptrdiff_t)で、size_tとは異なります。これは符号なし整数型です。

+6

私は、パラメータが 'std :: vector :: difference_type'型で、' size_t'で始まらなければならないと言っています。 –

+0

'std :: next(dest.begin()、dest_offset)'は警告を避けますか?私はすぐにそれをテストすることができませんでした。 – Blastfurnace

+0

@Blastfurnace 'std :: next'も' difference_type'を期待しています。 – songyuanyao

4

あなたはすべて一緒にこの警告を回避するために一部difference_typeを使用することができます。

#include<vector> 

using difference_type = std::vector<double>::difference_type; 

void copy_stuff(const std::vector<double> & data, 
       std::vector<double> & dest, 
//    size_t dest_offset) 
       difference_type dest_offset) 
{ 
    std::copy(data.begin(), data.end(), dest.begin() + dest_offset); 
} 

それは広く、今日受け入れられている[要出典]符号なし整数型としてサイズといくつかのオフセットを使用して/された報告のこと標準ライブラリの設計ミス。 私の意見では、最良のことは、その規約に従わずに、署名されていない型を使用するように関数を適合させるのではなく、できるだけ早く標準ライブラリから符号なしの型をキャストすることです。

たとえば、copy_stuff(a.begin(), a.end(), static_cast<difference_type>(other.size()))です。

+0

ありがとう、私はこれを使用することを検討します - 最初の実験は実際に警告が消えてしまうことを示しています。 – meowsqueak

+0

'dest_offset> = 0'をチェックしてはいけませんか? – Walter

+0

@Walter残念ながら、タイプが署名されていないため、正の値が意味を成立していることを保証すると考えるのは間違いです。関数に負の数を与えると、それを大きな正の数に変換しますが、これも意味がありません。符号なしの型を使用して行う唯一の作業は、エラーを非表示にすることです。私は "不幸なことに"と言っていますが、それは実際には意味がありませんが、実際には "符号なしの型"は実際には "モジュロ型"の悪い名前なので動作しません。そのチェックを追加することはできますが、コストがかかります。プログラムロジックが理にかなっていることを確認することをお勧めします。 – alfC

関連する問題