Я натолкнулся на реальный мозговой штурм на С++, это никогда не случалось со мной раньше.
Суть проблемы заключается в том, что при вызове моей (шаблонной) функции аргументы, которые я определил по умолчанию, имеют скремблированные значения. Это происходит только в том случае, если я вызываю функцию со значениями по умолчанию.
Моя функция шаблона объявляется следующим образом:
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);
}
Теперь, когда я вызываю это по умолчанию (transform(vector2<double>(0, 1), view_transform)
), я не получаю ожидаемые значения. Вступая в transform
с отладчиком VС++, я вижу z
и w
имеющие "смешные" значения (что, по моему опыту, означает, что что-то не инициализировано должным образом).
Примеры смежных значений: 0.0078125000000000000 и 2.104431116947e-317 # DEN
Теперь я пробовал найти ответ на С++ FAQ Lite, googling it; даже пытался успокоиться с Шубертом, но я не могу, чтобы жизнь меня поняла. Я предполагаю, что это очень просто, и я подозреваю, что на работе работает какой-то шаблонный дурачок.
Есть ли способ получить значения по умолчанию, которые я ожидаю и хочу, и почему он делает это для меня?
Изменить 1:
Если я вызываю изменение, поэтому вместо него использует float (transform(vector2<float>(0, 1), view_transform)
), проблема исчезает. Похоже, это происходит только в том случае, если T
= double
.
Изменить 2:
Это происходит только в том случае, если у меня есть две специализации для double
и float
. Если я использую специализацию float в одном месте, двойная специализация получает странные значения по умолчанию. Если я изменю все места, вызываемые функцией, поэтому он использует двойные проблемы "уходит". Я все еще не понимаю, почему, хотя, как будто он использует ошибочные смещения или что-то при настройке z
и w
.
Изменить 3:
Рассказы из Crypt Crypt:
#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);
}
// ...
Если я запустил это, двойная специализация корректно использует аргументы по умолчанию, но версия с плавающей запятой получает оба аргумента по умолчанию как ноль (0.000000), которые, хотя и лучше, все равно не являются z = 0
и w = 1
.
Изменить 4:
Сделано Соединить вопрос.