正しいように見えlibstdc++
ますが、これは形式が正しくありませんが、これが LWG アクティブな問題の欠陥であるかどうかについて、いくつかの疑問が表明されていることがわかります2192
。
ドラフト C++11 標準セクション26.8
[c.math]パラグラフ11
には、次のように記載されています。
さらに、次のことを保証するのに十分な追加のオーバーロードがあるものとします。
次の項目が含まれます。
- それ以外の場合、double パラメーターに対応するいずれかの引数が double 型または整数型である場合、double パラメーターに対応するすべての引数は実質的に double にキャストされます。
libstdc++
そして、これが実際にこのケースを提供していることがわかります。
template<typename _Tp>
inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
double>::__type
abs(_Tp __x)
{ return __builtin_fabs(__x); }
llabs が存在しない場合、std::abs (long long) が std::abs (double) に頼るgcc
というバグ レポートもあります。
[...]標準では問題ありません。整数は無条件に double になるはずです。[...]
バグ レポートは、最終的にLWG アクティブな問題 2192 につながります: std::abs(0u) の有効性と戻り値の型が不明です。
- C++11 では、26.8 [c.math] p11 (LWG 2086 も参照) からの追加の「十分なオーバーロード」規則が、std::abs() オーバーロードにも適用可能であると読み取ることができます。考えられる結論:
プログラム
#include <type_traits>
#include <cmath>
static_assert(std::is_same<decltype(std::abs(0u)), double>(), "Oops");
int main() {
std::abs(0u); // Calls std::abs(double)
}
26.8 [c.math] p11 のサブブレット 2 (「[..] または整数型 [..]」) のため、適切な形式である必要があります (LWG 2086 の現在の解像度はそうではないことに注意してください)。この問題を修正します)。
- と の両方を含む変換単位は、オーバーロード std::abs(int) の戻り値の型に対する 2 つの競合する要件のために、形式が正しくない可能性があります。
少なくとも 2 番目の結果は意図されていないように思われます。個人的にはどちらも残念だと思います [...] また、7.25 p2+ で C99/C1x から対応する「ジェネリック型関数」ルール セットが追加されたことにも注意する必要があります。 3 は と の浮動小数点関数に制限されているため、abs 関数には適用できません (ただし fabs 関数には!)。
問題は、これがabs
同様に適用されることを意図していたかどうかです。現在の文言を解釈して除外する方法がないように見えるため、これは欠陥である可能性がありabs
ます。
したがって、現在の文言は準拠していることを示していますが、現在の実装をそのまま選択しlibstdc++
た理由は明らかではありません。libc++
このトピックに関するバグ レポートや議論は見つかりませんでした。また、LWG の問題では実装の相違について言及されていません。
提案された解決策は、std::abs(0u)
形式が正しくありません。
abs() が、整数昇格 ([conv.prom]) によって int に変換できない符号なし整数型の引数で呼び出された場合、プログラムは不正な形式です。[注: int に昇格できる引数は、C との互換性のために許可されています — 末尾の注]
unsigned 型を使用するという概念に疑問を呈する人もいるかもしれませんabs
が、ハワード・ヒンナントはレポートで、テンプレートを使用する場合、そのような結果は明らかではない可能性があると指摘し、例を示しています。
[...]特に、テンプレートがある C++ では、関連する型が設計時にプログラマーに常に明らかであるとは限りません。たとえば、次のことを考慮してください。
template <class Int>
Int
analyze(Int x, Int y)
{
// ...
if (std::abs(x - y) < threshold)
{
// ...
}
// ...
}