2012-03-20 25 views
4

私は古いコードで警告を取り除こうとしていましたが(MSVC 2005を使用しなければならず、現在は32ビットビルドで動作しています)、苦労してsize_tunsigned int変換警告を取り除いてください。私たちは、型パラメータとして "size_t"、キャスト警告が再生されない

template<typename I> const T& at(const I i) const {return atImpl(i);}

メソッドを実装して成長している配列の私たち自身のArray<T>の実装を持っています。

size_t i = 10; myArray.at(i);

として呼び出されたときに、私はconversion from 'size_t' to 'const unsigned int', possible loss of data警告が表示されます。 作業理論はIを変換/ size_t(不便なく、許容されているだろう)atからiを渡すときunsigned intへをキャストするようにコンパイラを引き起こしているunsigned int、であると理解されていることをてきました。しかし、は最小限の作業例(この記事の最後)でも、より複雑な最小限の例でもこの警告を再現できませんでした。単にunsigned intにパラメータをキャストすると、警告が消えなり、私たちのニーズに十分であろう(契約によって、数はunsigned intに収まる)

  1. 私の理解は約Iunsigned intているように、コールで正しい(仕様では、「言いますのtypedef名は、このように別のタイプの同義語です。typedefは名 は、新しいタイプ」を導入しない、typeid(size_t(1)).name())がunsigned intsize_ttypedef供給されているようだと言います。言い換えれば、最小限の例で警告を与えるべきか、そうすべきではないか?私が知る限り、構築構成は同じです。
  2. 私たちのコードは私たちに警告を与えており、最小限の例ではないので、私は見落とされるべきものがあります。すべての努力にもかかわらず、私は何が分かりません。アイデア?

おかげ

最小限例

機能で
template<typename T> 
    class A 
    { 
     int t; 
    public: 
     template<typename I> T& at(const I i) { return t;} 
    }; 

    int main() 
    { 
     size_t i = 10; 
     A<int> a; 
     a.at(i) = 5; // no warning, why? 
     return 0; 
    } 
+0

'/ Wp64'が有効になっていますか? –

+0

万が一 '/ Wp64'オプションを使用していますか? 'size_t'は64ビットモードではサイズが違うと警告しますが、' unsigned int'はそうではありません。 –

+3

コードを移植性を持たせることに取り組んでいるなら、警告の意味を考えるのではなく、あなたの 'MyVector'型で' std :: size_t'を使うことを検討してください。ある日、または別のあなたがアーキテクチャー(64ビット)を変更し、 'size_t'は異なるサイズであるかもしれないし、あなたがカムバックを持っており、すべての警告を再訪します... ない限り、当然のことながら、引数がコンテナにアクセスするために使用されていませんが、他の形式で保存する。 –

答えて

1

もテンプレート化されています。 C++は、テンプレート型の引数を推測しようとします。 a.at < size_t>(1);のような呼び出しで型を指定していないので、あなたのコードで何が起こっているのですか?

それはunsigned int型としてのタイプを推測しているので、このコードは、警告を生成しますし、我々はEDIT

template <typename T> 
class A 
{ 
    int t; 
    public: 
     template<typename I> T& at(const I i) 
     { return t;} 
}; 

int main() 
{ 
    unsigned int j = 5; 
    size_t i = 10; 
    A<int> a; 

    a.at(j) = 4; // deduce template type as unsigned int 
    a.at(i) = 5; // generate warning 
    return 0; 
} 

size_t型に渡すようにしてみてください:は私が実際にVSでこのコードを試してみましたが、それが生成します警告。

Edit2:私が試したコードでは、size_tとunsigned intは両方とも4バイトでした。だから私は掘り起こした。 VSの古いバージョンでは、size_tはtypedef __w64 unsigned int size_tと定義されています。 '__w64'は現在廃止予定ですが、64ビットプラットフォームに移行する際に異なるサイズ(64対32など)のフラグを付けるために使用されています。 __w64を指定すると、コンパイラはsize_tを別の型として認識します。

私は自分自身の符号なし整数myintを型定義し、size_t i = 10myint i = 10に変更しました。 typedef __w64 unsigned int myintを使用して

はtypedefをunsigned int型myint`が警告を生成しません」と警告を生成します。

+0

これはそれだと思います。私の設定で 'size_t'が' unsigned int'になるので、 'at(size_t(1))'と 'at((unsigned int)2)'は同じバージョンをインスタンス化して再利用します'at'(両方とも私の現在の設定では同義語です)。 'a.at(j); a.at(i);'が使用されている場合、 'at'の' unsigned int'バージョンがインスタンス化され、等価性のために、 'a.at(i) ); '参照、これは警告をトリガーします。 'a.at(i); a.at(j);'が使用されている場合、 'size_t'のバージョンはinstです。 'a.at(j)'リファレンスで再利用されても、問題ない/警告はありません。正しい?素晴らしい発見! –

+0

これは良い集計です。 a.at(i)が最初に呼び出され、a.at(j)が呼び出されたときにunsigned intがデータの損失なしにsize_t(unsigned long)に昇格された場合も正しいです。 – Charlie

+0

は実際には、明確にするために、私は 'はsizeof 32ビットのビルド、(I)==はsizeof(J)'について話しているので、私の知る限りで、場所を取る任意の宣伝がないでしょう。残りは、私が知る限り、まだ保持されています。 –

関連する問題