C++:使用复数共轭代理 set/get 数组值
C++: Proxy to set/get array value with a complex conjugate
我正在为 Hermitian matrices 写 class。这是一个只有 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>(...)
中的位置。当然这个方法returns有参考意义。您在上面看到的代码不适用于矩阵的下三角部分,因为返回后引用消失了。
什么是正确和最有效的实现方法,这样我有某种 "pipe" 的下三角矩阵部分总是通过 std::conj
进行设置和获取?
如有需要,请索取更多信息。谢谢。
考虑到 std::conj() 没有 return 引用,您有两个选择:
- 不要return函数中的引用,而是值
- 实现您自己的 std::conj() 函数版本,return作为参考
您可以实现 属性 class 和 return 这个 class 的对象。
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 */ }
}
};
可赋值自动转换
按照 Franck 的示例,我建议 return 包装器 class(或结构)包装对元素的引用并记住布尔标志以记住是否需要连接数字.
类似于[注意:未测试]
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;
}
};
并且您的函数可能会变成[编辑:在问题中进行相应编辑后修改(row/column 其他情况的反转)]
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)]);
}
我正在为 Hermitian matrices 写 class。这是一个只有 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>(...)
中的位置。当然这个方法returns有参考意义。您在上面看到的代码不适用于矩阵的下三角部分,因为返回后引用消失了。
什么是正确和最有效的实现方法,这样我有某种 "pipe" 的下三角矩阵部分总是通过 std::conj
进行设置和获取?
如有需要,请索取更多信息。谢谢。
考虑到 std::conj() 没有 return 引用,您有两个选择:
- 不要return函数中的引用,而是值
- 实现您自己的 std::conj() 函数版本,return作为参考
您可以实现 属性 class 和 return 这个 class 的对象。
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 */ }
}
};
可赋值自动转换
按照 Franck 的示例,我建议 return 包装器 class(或结构)包装对元素的引用并记住布尔标志以记住是否需要连接数字.
类似于[注意:未测试]
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;
}
};
并且您的函数可能会变成[编辑:在问题中进行相应编辑后修改(row/column 其他情况的反转)]
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)]);
}