2017-01-16 90 views
1

はC++ 98以下のコードスニペットをご検討ください。しかし-Woverflow警告が唯一の浮動小数点数のためにそこにあるべき他の分岐、のために放出される(だけでなく上向き-O1-Os)任意の最適化を指定してコンパイルする場合:すべて、gccの警告は "-WOverflow"

g++ test.cpp -Wall -O1 && ./a.out 
test.cpp: In instantiation of ‘T myLower() [with T = unsigned char]’: 
test.cpp:16:46: required from here 
test.cpp:9:16: warning: large integer implicitly truncated to unsigned type [-Woverflow] 
     retval = -std::numeric_limits<T>::max(); 
     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
0 

これもuint16のために失敗しました他のタイプは必要に応じて動作します。私が見る限り、std::numeric_limits<uint8_t>::is_integerはコンパイル時定数でなければなりません - なぜelse-branchはコンパイルされていますか?警告は深刻ではありませんか、私は何かが恋しいですか?

ああ、これはgcc5とgcc6で発生します。

ありがとうございます!

PS:私はここでの問題は

if (std::numeric_limits<T>::is_integer) 

Tができるかを制限しないことである

+2

コンパイラがオーバーフロー操作について不平を言っているオーバーフロー操作(符号なしタイプの結果がよく定義されていますが)に頼っているコードでは、なぜ驚いていますか? – Peter

+0

'is_integer'がコンパイル時の定数でtrueのため、オーバーフローが最初に起こるべきではないので、私は驚いていますか? uint8_tとuint16_tのオーバーフローは "発生する"ため、より大きい整数は正常です... – fdgsydfgsdfgsdfg

+0

テストがコンパイル時定数の場合、コンパイラはif/elseを最適化する必要はありません。そのような振る舞いが必要な場合は、コンパイル時の構文(テンプレート特殊化など) – Peter

答えて

1

...未来はここに着いたときますstd::numeric_limits<>::lowest()があることを知っています。つまり、elseのbranceは常にコンパイルされ、ブランチに到達していなくても操作によってオーバーフローが発生すると警告がトリガーされます。

あなたがC++ 17を持っていた場合、あなたは唯一のconstexprの条件に応じて、ifブロックまたはelseブロックをコンパイルします

template <typename T> T myLower() { 
    if constexpr (std::numeric_limits<T>::is_integer) { 
     return std::numeric_limits<T>::min(); 
    } else { 
     return -std::numeric_limits<T>::max(); 
    } 
} 

ようif constexprを使用することができます。 C++ 17より前には、SFINAEを使用して、テンプレートが解決した場合にのみ関数をコンパイルするように制約する必要がありました。

+0

ああ、そうです。ありがとう。それはそれを解決する:C++ 17はここから遠く離れている;-( – fdgsydfgsdfgsdfg

関連する問題