別の質問では、のトピックがstd::numeric_limits<int>::is_modulo
出てきました。しかし、考えれば考えるほど、仕様またはGCC、あるいはその両方に問題があるように思われます。
いくつかのコードから始めましょう:
#include <limits>
#include <iostream>
bool test(int x)
{
return x+1 > x;
}
int main(int argc, char *argv[])
{
int big = std::numeric_limits<int>::max();
std::cout << std::numeric_limits<int>::is_modulo << " ";
std::cout << big+1 << " ";
std::cout << test(big) << "\n";
}
これをg++ -O3 -std=c++11
(x86_64 GCC 4.7.2)でコンパイルすると、次の出力が生成されます。
1 -2147483648 1
つまり、is_modulo
trueであり、1つのプラスINT_MAX
は負であり、1つのプラスINT_MAX
は。より大きいですINT_MAX
。
あなたがこの質問に答える現実的なチャンスを持っているような人なら、あなたはすでにここで何が起こったのかを知っています。C ++仕様では、整数のオーバーフローは未定義動作であるとされています。コンパイラは、あなたがそうしないと想定することができます。したがって、への引数を;にするx+1
ことはできませんINT_MAX
。したがって、コンパイラーは関数をコンパイルして無条件test
に返すことができます(そしてコンパイルします)。true
ここまでは順調ですね。
ただし、C ++ 11仕様には次のようにも記載されています(18.3.2.4段落60-61)。
static constexpr is_modulo;
タイプがモジュロの場合はTrue。222、、、またはそのタイプの値を含む操作で
+
、-
結果*
が範囲外になる場合、タイプはモジュロです。[min(),max()]
返される値は、の整数倍だけ真の値と異なりますmax() - min() + 1
。ほとんどのマシンでは、これは
false
浮動型、true
符号なし整数、および符号付き整数true
用です。
セクション5の段落(4)には、「式の評価中に、結果が数学的に定義されていないか、そのタイプの表現可能な値の範囲内にない場合、動作は未定義である」と記載されていることに注意してください。is_modulo == true
例外を作成することについての言及はありません。
したがって、整数のオーバーフローを同時に定義および未定義にすることはできないため、標準は論理的に矛盾しているように見えます。または、少なくとも、GCCは不適合です。これは、符号付き演算が確実にラップアラウンドしない場合でも、GCCが不適合であるためis_modulo
ですtrue
。
標準のバギーですか?GCCは不適合ですか?私は何かが足りないのですか?