次のプログラム例を見てみましょう。
#include <cmath>
namespace half_float
{
template<typename T> struct half_expr {};
struct half : half_expr<half>
{
operator float() const;
};
template<typename T> half sin(const half_expr<T>&);
template<typename T> half atan2(const half_expr<T>&, const half_expr<T>&);
}
using namespace std;
using half_float::half;
int main()
{
half a, b;
half s = sin(a);
half t = atan2(a, b);
}
VS 2010では、これは問題なくコンパイルされます (現時点では明らかなリンカー エラーは無視してください)。しかし、VS 2012では次のようになります。
エラー C2440: 'conversion': 'float' から 'half_float::half' に変換できません
したがって、オーバーロードの解決は名前空間からバージョンを選択するのではなくhalf_float
(ADL が達成する必要があります)、std
暗黙的な変換を使用してfloat
. しかし、奇妙なことに、これは通話に対してのみ発生し、atan2
通話に対しては発生しませんsin
。
half
このエラーが実際に最初に発生した大規模なプロジェクトでは、 のような他の 2 引数関数 (または 2 引数を持つ関数) でも発生しますが、1 引数関数では発生しませんfmod
。同様に、より大きなプロジェクトでは、gcc 4.6/4.7およびclang 3.1でもエラーなく正常に動作しますが、この SSCCE バージョンを明示的にテストしていません。
したがって、私の質問は、VS 2012側でのこの誤った動作ですか ( 2012でのみ発生し、2 引数の関数でのみ発生することを考えると)、それともオーバーロード解決ルールのいくつかの微妙な点を監視しましたか (これは実際に少しトリッキーだと思います)?
編集:using namespace half_float
直接または全体をグローバル名前空間に直接配置した場合にも発生します。同様に、私がそうでない場合にも発生しますusing namespace std
が、これは数学関数をグローバル名前空間に配置する VS 実装です。
編集:元のVC 2012コンパイラと2012 年 11 月の CTPの両方で発生します。
編集:厳密な意味で本当に標準に違反しているかどうかは完全にはわかりませんが、少なくとも 1-引数は機能し、VSチームによるさらなる調査に値します。