这个问题需要一些背景--如果你感到不耐烦,跳过底线.我有一个Vector-3,4和Matrix-3,4库,定义为模板专门化;也就是说,Vector<n>和Matrix<n>是在Matrix.hh中定义的,而非平凡的实现(例如矩阵乘法、矩阵逆)在Matrix.cc for N = {3,4}中有显式的专门化或实例化。
这种方法行之有效。理论上,应用程序可以实例化Matrix<100>,但不能乘以或反转矩阵,因为头部中没有可见的实现模板。只有N = {3,4}在Matrix.cc中被实例化。
最近,我加入了稳健方法来补充任何涉及内积的运算--包括矩阵乘法、矩阵向量变换等。大多数3D变换(投影/方向)条件相对良好,任何微小的精度误差都不是问题,因为共享顶点/边会产生一致的栅格化。
有一些运算必须在数值上是稳健的。在渲染时,我不能对GPU如何做点积和矩阵操作做任何事情;但是我不能让控制/摄像机参数被有效的几何限制--而且内部产品因病理性消除错误而臭名昭著,所以稳健的方法使用补偿求和、积、点积等。
这对于Vector内部产品(比方说,Matrix.hh中的内部产品)来说很好:
////////////////////////////////////////////////////////////////////////////////
//
// inner product:
template <int n> float
inner (const GL0::Vector<n> & v0, const GL0::Vector<n> & v1)
{
float r = v0[0] * v1[0];
for (int i = 1; i < n; i++)
r += v0[i] * v1[i];
return r; // the running sum for the inner product.
}
float
robust_inner (const GL0::Vector<3> &, const GL0::Vector<3> &);
float
robust_inner (const GL0::Vector<4> &, const GL0::Vector<4> &);
////////////////////////////////////////////////////////////////////////////////Matrix.cc中的实现是不平凡。
当添加一个健壮的[A]<-[A][B]矩阵乘法方法时,我处于一个更不确定的领域;也许命名并不理想:
template <int n> GL0::Matrix<n> &
operator *= (GL0::Matrix<n> & m0, const GL0::Matrix<n> & m1);
// (external instantiation)
GL0::Matrix<3> &
robust_multiply (GL0::Matrix<3> &, const GL0::Matrix<3> &);
GL0::Matrix<4> &
robust_multiply (GL0::Matrix<4> &, const GL0::Matrix<4> &);N = {3,4}在Matrix.cc中有一个operator *=实现,但它依赖于天真的内部产品,并且不健壮--尽管通常足以用于GL /可视化。robust_multiply函数也在Matrix.cc中实现。
当然,我需要Matrix乘法运算符:
template <int n> GL0::Matrix<n>
operator * (GL0::Matrix<n> m0, const GL0::Matrix<n> & m1) {
return (m0 *= m1);
}向我介绍了有问题的定义:
inline GL0::Matrix<3>
robust_multiply (GL0::Matrix<3> m0, const GL0::Matrix<3> & m1) {
return robust_multiply(m0, m1);
}
inline GL0::Matrix<4>
robust_multiply (GL0::Matrix<4> m0, const GL0::Matrix<4> & m1) {
return robust_multiply(m0, m1);
}对robust_multiply(m0, m1)的调用是不明确的。Q:我如何强迫LHS参数被解释为引用,以确保调用以前修改(m0)参数的函数。显然可以将robust_multiply命名为其他东西,但我更感兴趣的是使用类型系统。我觉得我错过了<utility>或<functional>中一些显而易见的东西。如何强制调用正确的函数?
(关于“数”这个词,我很抱歉--我在写作时试图澄清我自己的想法。)
发布于 2022-03-13 16:04:43
你给robust_multiply取错名字了。
*=和*是根本不同的操作。它们是相关的,但不是相同的操作--不同的动词。
当您对不同的名词执行相同的操作时,应使用重载。
如果你这样做,那么你的问题几乎肯定会消失。合理的过载很容易写。
在您的情况下,您希望在写入参数之间进行更改,或者不根据参数的l/r值类别进行更改。这会导致歧义问题。
我的意思是,有一些解决问题的方法--比如使用std::ref或指针,或者使用&、&&和const&重载--但它们都是补丁。
在编程中给它命名是很困难的。这是一个案例,如果你应该这么努力的话。
..。
现在你能做的一件事就是祝福这些争论。
template<class T>
struct robust{
T t;
explicit operator T&()&{return t;}
explicit operator T()&&{
return std::forward<T>(t);
}
// also get() methods
explicit robust(T&&tin):
t(std::forward<T>(tin))
{}
};然后为健壮的包装矩阵重写*=和*。
robust{a}*=b;( lhs必须保持稳健,以降低过载计数)。
现在动词清楚了,我只是把名词修饰一下。
但这只是一个想法,而不是使用测试。
https://stackoverflow.com/questions/71458432
复制相似问题