我有一堂这样的课
class Foo {
public:
Matrix M;
Foo();
~Foo();
}
Run Code Online (Sandbox Code Playgroud)
我想M
在类内部是不可变的(内部成员函数不能改变它),但是类外部的代码应该能够不受约束地更新它,有没有办法做到这一点?
一点背景:我正在开发一个 OpenGL 应用程序,我有一个Mesh
类可以保存所有顶点/纹理数据,并且可以Draw()
按需使用。我意识到观察矩阵和投影矩阵对于场景是全局的,而模型矩阵M
对于每个网格都是局部的,所以我声明M
为类的公共成员Mesh
,它被初始化为单位矩阵。类外的调用者应该更新M
每一帧以进行转换。但是,我不希望它在课堂内被意外更改。希望这是有道理的。
这似乎违反了c++
原则,但我需要以某种方式绑定M
到类的实例。该Matrix
类型实际上是glm::mat4
BTW。
假设我下面有两个函数,在Foo()
函数中,我如何将hw
字符串打包到 args 并将它们转发到Bar()
?
我试过了,std::bind
但这没有用。
template<typename T, typename... Args>
void Bar(Args&&... args)
{
// do something with args
}
template<typename T, typename... Args>
void Foo(Args&&... args)
{
if (typeid(T) == typeid(std::string)) {
std::string hw = "Hello, world!";
Bar<T>(std::forward<Args>(hw, args)...); // how to add hw to the forward list?
}
else {
Bar<T>(std::forward<Args>(args)...);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:终于我找到了我的错误!对于那些你谁是想知道为什么hw
不转移到Bar()
即使你这样做是正确的,请讲究Bar()
的else
分支。如果Bar()
期望不同类型的参数取决于T
并且代码不会编译,则else
分支可能会发出编译器错误。正如@JeJo 提到的,我应该使用它if constexpr …
简单的测试代码
glm::mat4 m = glm::rotate(glm::mat4(1.0f), 0.78f, glm::vec3(0,1,0));
while (true) {
glm::vec3 axis = glm::normalize(glm::vec3(m[0])); // right vector
PRINT_VEC("{0:.3f} {1:.3f} {2:.3f}", axis.x, axis.y, axis.z);
m = glm::rotate(m, glm::radians(5.f), axis); // 5 degrees each iteration
}
Run Code Online (Sandbox Code Playgroud)
因此,假设我有一个模型矩阵,它从恒等式绕 y 轴旋转 0.78 弧度,那么每一帧我都会围绕局部右向量旋转,该向量是矩阵的第一列(假设是右手系统)。由于右向量是我旋转的轴,因此我希望它是恒定的,但事实并非如此。我不明白为什么glm::rotate
还要改变旋转轴。
输出变化相当大,所以我不认为这是浮点精度错误。
0.657 -0.424 -0.623
0.643 -0.482 -0.595
0.626 -0.539 -0.563
0.608 -0.593 -0.527
0.588 -0.646 -0.487
0.566 -0.696 -0.442
0.543 -0.742 -0.393
0.518 -0.785 -0.339
0.491 -0.824 -0.281
0.464 -0.858 -0.219
0.435 -0.887 -0.153
0.406 -0.910 -0.084
0.377 -0.926 …
Run Code Online (Sandbox Code Playgroud) 我的代码中有一个我不太明白的错误。根据文档,std::vector.back()
返回对容器中最后一个元素的引用,所以这就是我所做的:(住在这里)
#include <iostream>
#include <vector>
class Foo {
public:
Foo(int id) : id(id) {
std::cout << "foo " << id << " constructed" << std::endl;
}
~Foo() {
std::cout << "foo " << id << " destructed" << std::endl;
}
int id;
};
int main() {
std::vector<Foo> foos;
for (int i = 0; i < 2; i++) {
foos.emplace_back(i); // construct foo in place
auto& foo = foos.back();
std::cout << "Play with " << foo.id << …
Run Code Online (Sandbox Code Playgroud)