我正在为Hermitian matrices写一堂课。这是一个复杂的矩阵,只有n*(n+1)/2
个独立的复数(忽略关于对角线的细节是真实的)。
我的计划是只编写上三角形元素,其中行号与列号相比满足条件满足规则:row >= column
。但是,这需要像代理一样的东西?我不确定如何实现这一点。这是问题所在:
假设我实现了成员函数at(int row, int column)
来访问元素。
template<typename T>
std::complex<T>& HermitianMatrix<T>::at(long row, long column)
{
if(row >= column)
return this->_matrix[ElementIndex(row,column)];
else
return std::conj(this->_matrix[ElementIndex(column,row)]);
}
其中ElementIndex
将row
和column
输入转换为数组std::complex<T>* _matrix = new std::complex<T>(...)
中的位置。当然,这个方法返回一个引用。您在上面看到的代码不适用于矩阵的下三角部分,因为返回后引用已经消失。
实现这一点的正确和最有效的方法是什么,这样我对下三角矩阵部分有某种“管道”,对于set和get都会经历std::conj
?
如果需要,请询问更多信息。谢谢。
答案 0 :(得分:2)
按照Franck的例子,我建议返回一个包装类(或结构)来包装对元素的引用,并记住一个布尔标志,以便记住是否需要联合该数字。
像[警告:未经测试]
之类的东西template <typename T>
struct cWrapper
{
bool c;
std::complex<T> & r;
cWrapper (bool c0, std::complex<T> & r0) : c{c0}, r{r0}
{ }
operator std::complex<T>() const
{ return c ? std::conj(r) : r; }
cWrapper & operator= (const std::complex<T> & r0)
{
r = ( c ? std::conj(r0) : r0 );
return *this;
}
};
并且您的函数可以变为[编辑:在问题中相应的编辑后修改(其他情况下的行/列反转)]
template<typename T>
cWrapper<T> HermitianMatrix<T>::at(long row, long column)
{
if(row >= column)
return cWrapper<T>(false, this->_matrix[ElementIndex(row,column)]);
else
return cWrapper<T>(true, this->_matrix[ElementIndex(column,row)]);
}
答案 1 :(得分:1)
您可以实现属性类并返回此类的对象。
template <typename T>
struct ComplexGetter {
std::complex<T>* ref;
std::complex<T> conj;
ComplexGetter(std::complex<T>& reference) : ref(&reference) {}
ComplexGetter(const std::complex<T>& conjugate) : ref(nullptr), conj(conjugate) {}
operator std::complex<T>() const { return ref ? *ref : conj; }
operator=(const std::complex<T>& source)
{ if (ref) *ref = source;
else { ... /* do something */ }
}
};
可以分配并自动转换。
答案 2 :(得分:0)
考虑到std :: conj()不返回引用,您有两个选择: