• Class / Function / Type

      std::
    • Header file

      <>
    • Other / All

    最終更新日時(UTC):
    が更新

    履歴 編集

    variable
    <limits>

    std::numeric_limits::is_modulo

    // C++03
    static const bool is_modulo;
    
    // C++11
    static constexpr bool is_modulo;
    

    概要

    加算 (+) ・減算 (-) ・乗算 (*) における数学的な値と、その型での値との間に (max() - min() + 1) を法として常に合同関係があるかを判定する。

    この性質を持つ型は、オーバーフロー時に最大値+1で剰余した値となる。

    符号なし整数型の場合は常にtrueとなる。

    • C++03 : 多くのマシンでは、浮動小数点数型の場合はfalseに、符号付き整数型の場合はtrueになる
    • C++17 : 標準では符号付き整数型はfalseとなる。標準の拡張として実装の符号あり整数型が、未定義動作としてではなく正しくオーバーフローする場合、trueと定義される

    備考

    • C++03の「ほとんどのマシンでは符号付き整数型はtrueになる」という仕様は、符号あり整数型の未定義動作としてのオーバーフロー動作を正しいものとして扱ってしまっていた。これは間違いであった。C++17では、符号あり整数型は標準ではfalseとし、実装がオーバーフロー時に値を折り返す場合にtrueと定義されるように修正された
    • コンパイルオプション
      • GCCとClangでは、-fwrapvオプションをつけることで、符号付き整数型を2の補数表現として折り返すよう動作を規定するが、is_modulofalseとなる
      • Visual C++では、d2UndefIntOverflowオプションをつけることで、符号付き整数型のオーバーフローを利用するコードの最適化を無効化し、値を折り返す動作になるが、is_modulofalseとなる

    #include <iostream>
    #include <cassert>
    #include <limits>
    
    int main()
    {
      std::cout << std::boolalpha;
      std::cout << "int : " << std::numeric_limits<int>::is_modulo << std::endl;
      std::cout << "unsigned int : " << std::numeric_limits<unsigned int>::is_modulo << std::endl;
      std::cout << "float : " << std::numeric_limits<float>::is_modulo << std::endl;
      std::cout << "char : " << std::numeric_limits<char>::is_modulo << std::endl;
      std::cout << "char : " << std::numeric_limits<bool>::is_modulo << std::endl;
    
      assert(std::numeric_limits<unsigned int>::max() + 1 == 0u);
    }
    

    出力例

    int : false
    unsigned int : true
    float : false
    char : false
    char : false
    

    関連項目

    参照