私は C++ で本当の脳を焼き尽くすものに出くわしました。
問題の要点は、私の(テンプレート)関数の呼び出し時に、デフォルトを定義した引数の値がスクランブルされることです。デフォルトで関数を呼び出した場合にのみ発生します。
私のテンプレート関数は次のように宣言されています:
template <typename T>
vector2<T> transform(vector2<T> const &vec, matrix4<T> const &m, T z = T(0), T w = T(1));
後で、同じヘッダーで、次のように定義されます。
template <typename T>
inline vector2<T> transform(vector2<T> const &vec, matrix4<T> const &m, T z, T w)
{
vector4<T> res = m * vector4<T>(vec.x, vec.y, z, w);
return vector2<T>(res.x, res.y);
}
これを defaults ( transform(vector2<double>(0, 1), view_transform)
) で呼び出すと、期待する値が得られません。transform
VC++ デバッガーに足を踏み入れると、「おかしな」値が表示さz
れw
ます (私の経験では、何かが正しく初期化されていないことを意味します)。
面白い値の例: 0.0078125000000000000 および 2.104431116947e-317#DEN
今、私は C++ FAQ Lite で答えを見つけようとしました。シューベルトで自分を落ち着かせようとさえしましたが、私は一生それを理解することができません. 私はそれが本当に単純で、ある種のテンプレートのおふざけが働いているのではないかと推測しています。
私が期待し、望んでいるデフォルト値を取得する方法はありますか?なぜそれが私にこれを行うのですか?
編集1:
代わりにフロートを使用するように変更呼び出しを行うと ( transform(vector2<float>(0, 1), view_transform)
)、問題は解決します。これはT
=の場合にのみ発生するようdouble
です。
編集2:
と の 2 つの専門分野がある場合にのみ発生double
しfloat
ます。ある場所で float 特殊化を使用すると、double 特殊化が奇妙なデフォルト値になります。関数が呼び出されるすべての場所を変更すると、問題が2倍になり、「なくなる」。z
とw
. _
編集3:
C++ クリプトの物語:
#include <sgt/matrix4.hpp>
int main(int argc, char *argv[])
{
sgt::matrix4<double> m0(
2, 0, 0, 1,
0, 2, 0, 1,
0, 0, 1, 0,
0, 0, 0, 1);
m0 *= m0;
sgt::vector2<double> blah0 = sgt::transform(sgt::vector2<double>(1, 0), m0);
sgt::matrix4<float> m1(
2, 0, 0, 1,
0, 2, 0, 1,
0, 0, 1, 0,
0, 0, 0, 1);
m1 *= m1;
sgt::vector2<float> blah1 = sgt::transform(sgt::vector2<float>(1, 0), m1);
printf("%f", blah0.x);
printf("%f", blah1.x);
}
matrix4.hpp では:
// ...
template <typename T>
vector2<T> transform(vector2<T> const &vec, matrix4<T> const &m, T z = T(0), T w = T(1));
template <typename T>
inline vector2<T> transform(vector2<T> const &vec, matrix4<T> const &m, T z, T w)
{
vector4<T> res = m * vector4<T>(vec.x, vec.y, z, w);
return vector2<T>(res.x, res.y);
}
// ...
それを実行すると、double-specialization のデフォルト引数は正しくなりますが、float バージョンは両方のデフォルト引数をゼロ (0.000000) として取得しz = 0
ますw = 1
。
編集4:
接続の問題を作成しました。