9

指定された数値を表すことができる最小の符号付き整数型を返すテンプレートを作成したいと思います。これが私の解決策です:

/**
 * Helper for IntTypeThatFits.
 * Template parameters indicate whether the given number fits into 8, 16 or 32
 * bits. If neither of them is true, it is assumed that it fits 64 bits.
 */
template <bool fits8, bool fits16, bool fits32>
struct IntTypeThatFitsHelper { };

// specializations for picking the right type
// these are all valid combinations of the flags
template<> struct IntTypeThatFitsHelper<true, true, true> { typedef int8_t Result; };
template<> struct IntTypeThatFitsHelper<false, true, true> { typedef int16_t Result; };
template<> struct IntTypeThatFitsHelper<false, false, true> { typedef int32_t Result; };
template<> struct IntTypeThatFitsHelper<false, false, false> { typedef int64_t Result; };

/// Finds the smallest integer type that can represent the given number.
template <int64_t n>
struct IntTypeThatFits
{
    typedef typename IntTypeThatFitsHelper<
        (n <= numeric_limits<int8_t>::max()) && (n >= numeric_limits<int8_t>::min()), 
        (n <= numeric_limits<int16_t>::max()) && (n >= numeric_limits<int16_t>::min()), 
        (n <= numeric_limits<int32_t>::max()) && (n >= numeric_limits<int32_t>::min())
    >::Result Result;
};

ただし、GCCはこのコードを受け入れません。「データ型の範囲が制限されているため、比較は常にtrueです[-Werror=type-limits]」というエラーが表示されます。なぜそれが起こるのですか?nは符号付き64ビット整数であり、nの値が異なると、すべての比較がtrueまたはfalseになる可能性がありますか、それとも何かを見落としていますか?

助けていただければ幸いです。

編集:私はC++11を使用していることに言及する必要があります。

4

5 に答える 5

4

これはgccの問題であり、テンプレート化されたコードの警告はイライラする可能性があります。警告を変更するか、別のアプローチを使用できます。

ご存知かもしれませんが、テンプレート化されたコードは2回分析されます。

  • 最初に遭遇したときに1回(解析)
  • 特定のタイプ/値に対してインスタンス化されたときに1回

ここでの問題は、インスタンス化時にチェックが簡単であり(はい65intありがとうございます)、コンパイラはこの警告がすべてのインスタンス化に当てはまらないことを認識できないことです:(に警告を表示して、警告のないコンパイルエクスペリエンスを実現します

3つの可能性があります:

  • この警告を無効にするか、エラー以外に降格します
  • プラグマを使用して、このコードに対してプラグマを選択的に非アクティブ化します
  • 警告がトリガーされなくなるように、コードを別の形式で作り直します

3番目の可能性には、大規模な変更とはるかに複雑なソリューションが含まれる場合があることに注意してください。手がかりのない警告を取り除くためだけに、複雑なコードには反対することをお勧めします。

編集

考えられる回避策の1つ:

template <int64_t n>
struct IntTypeThatFits {
    static int64_t const max8 = std::numeric_limits<int8_t>::max();
    static int64_t const min8 = std::numeric_limits<int8_t>::min();

    static int64_t const max16 = std::numeric_limits<int16_t>::max();
    static int64_t const min16 = std::numeric_limits<int16_t>::min();

    static int64_t const max32 = std::numeric_limits<int32_t>::max();
    static int64_t const min32 = std::numeric_limits<int32_t>::min();

    typedef typename IntTypeThatFitsHelper<
        (n <= max8 ) && (n >= min8 ), 
        (n <= max16) && (n >= min16), 
        (n <= max32) && (n >= min32)
    >::Result Result;
};

...比較で使用されるデータのタイプを変更することにより、コンパイラの警告を消す必要があります。明示的なキャスト(int64_t(std::numeric_limits<int8_t>::max()))も機能すると思いますが、これの方が読みやすいと思います。

于 2012-05-03T15:54:26.583 に答える
3

この警告に関するエラーをGCCに要求したため、エラーが発生しています-Werror=type-limits。警告-Wtype-limitsは、指定されたデータ型の範囲のために常に真になる比較を行う場合に警告を表示します。次に例を示します。

uint8_t x;
if(x >= 0) { ... }  // always true, unsigned integers are non-negative
if(x >= 256) { ... }  // always false

int32_t x;
if(x < 9223372036854775808LL) { ... }  // always true

この警告は役立つ場合もありますが、これを含む多くの場合、それは単に役に立たない衒学者であり、無視することができます。通常は警告です(これ-Wextraを使用する場合は、の一部として有効になります)が、-Werrorまたは-Werror=type-limitsを指定すると、GCCはエラーになります。

この場合、コードの潜在的な問題を実際に示しているわけではないため、で警告をオフにするか、コンパイラの出力にこれらの警告が表示されてもかまわない場合は-Wno-type-limits、エラーにならないようにしてください。Werror=no-type-limits

于 2012-05-03T15:45:55.343 に答える
1
   typedef typename IntTypeThatFitsHelper<
        (n <= numeric_limits<int8_t>::max()) && (n >= numeric_limits<int8_t>::min()), 
        (n <= numeric_limits<int16_t>::max()) && (n >= numeric_limits<int16_t>::min()), 
        (n <= numeric_limits<int32_t>::max()) && (n >= numeric_limits<int32_t>::min())
    >::Result Result;

C ++ではそれを行うことはできません(C ++ 11では可能です)-numeric_limits<int8_t>::max()コンパイル時定数ではありません。C ++ 11を使用していますか?

ところで、Boostはすでにこれを提供しています: http ://www.boost.org/doc/libs/1_49_0/libs/integer/doc/html/boost_integer/integer.html

于 2012-05-03T15:42:19.770 に答える
1

問題が何であるかについての他の答えは間違っていると思います。これは熱心なコンパイラの場合ではないと思いますが、コンパイラのバグだと思います。このコードはまだ警告を発します:

template<int64_t n>
bool a() {
    return (n <= static_cast<int64_t>(std::numeric_limits<int8_t>::max()));
}

を呼び出すときa<500>();、しかしこのコードはしません:

template<int64_t n>
bool a() {
    return (n <= static_cast<int64_t>(127));
}

std :: neuro_limits :: max()は127と評価されます。他に誰もいない場合は、今日の後半にこれに関するBugzillaレポートを提出します。

于 2012-05-03T16:24:45.487 に答える
0

template <int64_t n> struct IntTypeThatFits小さいn(2 ^ 32より小さい)の一部のインスタンス化では、コンパイル時のオペランドの範囲のために、いくつかの比較が常に真(原文のまま)であるため、警告が表示されます。

この場合、これは偽の警告と見なすことができます。コードはこれに依存しているため、OTOHは、-Werrorまたは同様のコマンドラインスイッチでエラーにするように明示的に要求しました。基本的に、ここで要求した内容が得られます。

于 2012-05-03T15:48:11.537 に答える