我正在尝试实现一个简单的矢量旋转功能作为宠物项目,以进入模板元编程。借助开源数学库glm和有关SO的其他一些文章,我提出了一个基本可行的解决方案,但有一个错误。
我已经实现了几种结构,这些结构保存了代表二维eucledian向量所需的数据。结构“ vec2”具有一个联合,该联合持有一个包含两个元素的浮点数组(float data [2])和两个结构“ scalarSwizzle”的实例,该实例应实现旋转机制,使我可以像vec那样访问向量。 data [0]左右vec.x。
遵循我到目前为止实现的代码:
#include <iostream>
template<typename T>
void print(T value)
{
std::cout << "print func: " << value << std::endl;
}
template<typename T, unsigned int I>
struct scalarSwiz
{
T value[1];
T &operator=(const T newValue)
{
value[I] = newValue;
return value[I];
}
operator T()
{
return value[I];
}
};
template<typename T>
struct vec2
{
union
{
T data[2];
scalarSwiz<T, 0> x;
scalarSwiz<T, 1> y;
};
vec2()
{
x = 0.0f;
y = 1.0f;
}
vec2(T pA, T pB)
{
x = pA;
y = pB;
}
};
int main(int argc, char *args[])
{
vec2<float> vec1{5.0f, 1.0f};
std::cout << "value vec1.data[0]: " << vec1.data[0] << std::endl;
std::cout << "value vec1.data[1]: " << vec1.data[1] << std::endl;
std::cout << "value vec1.x: " << vec1.x << std::endl;
std::cout << "value vec1.y: " << vec1.y << std::endl << std::endl;
print(vec1.data[0]);
print(vec1.data[1]);
print(vec1.x);
print(vec1.y);
std::cin.get();
}
输出如下:
value vec1.data[0]: 5
value vec1.data[1]: 567.4
value vec1.x: 5
value vec1.y: 567.4
print func: 5
print func: 567.4
print func: 5
print func: 2.5565e-39
我期望直接在main()和通过print()中打印值的输出是相同的,但是当我通过print()函数打印时,无法解析vec.y。所以我想“ scalarSwizzle”中的重载typecast运算符有问题,但是我不知道该怎么办。 我还不明白的是,为什么Visual Studio也不能正确解析值,如下图所示:
vec1.y似乎指向与vec.x相同的物理地址,而main()中的直接std :: cout可以正常工作。
我已经尝试了几天,以解决这个问题,为什么重载的typecast运算符不适用于vec.y,但是我却不明白。也许这里有人可以帮助我解决这个问题。
谢谢!
答案 0 :(得分:1)
首先
template<typename T, unsigned int I>
struct scalarSwiz
{
T value[1];
T &operator=(const T newValue)
{
value[I] = newValue;
return value[I];
}
operator T()
{
return value[I];
}
};
如果I != 0
(超出数组访问范围),则会导致未定义的行为,因此不要指望您的代码正确或稳定。
第二,访问联合的不活动成员也是未定义的行为(根据c ++标准)。但是,msvc,gcc和clang扩展了c ++标准,因此访问非活动成员的行为与我们期望的一样。
最后,您的scalarSwiz
类型可以用匿名结构代替:
template<typename T>
struct vec2
{
union
{
T data[2];
struct
{
T x, y;
};
};
vec2()
{
x = 0.0f;
y = 1.0f;
}
vec2(T pA, T pB)
{
x = pA;
y = pB;
}
};
关于Visual Studio调试器的显示:这是因为您的scalarSwiz
定义。您定义一个长度为1 T value[1]
的数组,并将2个scalarSwiz
对象放入一个并集。因为联合的每个成员共享相同的内存(或者更确切地说,是从相同的内存位置开始),所以您的两个value
成员都指向data
数组的开头。监视窗口仅显示特定类型的成员及其值,不了解您的古怪索引。而且,因为两个数组占用相同的内存,所以显示的值相同。
答案 1 :(得分:0)
我更新了有关Timo答案的代码:
#include <iostream>
template<typename T>
void print(T value)
{
std::cout << "print func: " << value << std::endl;
}
template<typename T>
struct vec2
{
union
{
T data[2];
struct
{
T x, y;
};
};
vec2()
{
x = 0.0f;
y = 1.0f;
}
vec2(T pA, T pB)
{
x = pA;
y = pB;
}
};
int main(int argc, char *args[])
{
vec2<float> vec1{5.0f, 1.0f};
std::cout << "value vec1.data[0]: " << vec1.data[0] << std::endl;
std::cout << "value vec1.data[1]: " << vec1.data[1] << std::endl;
std::cout << "value vec1.x: " << vec1.x << std::endl;
std::cout << "value vec1.y: " << vec1.y << std::endl << std::endl;
print(vec1.data[0]);
print(vec1.data[1]);
print(vec1.x);
print(vec1.y);
std::cin.get();
}