Я пишу класс для Эрмитовы матрицы. Это сложная матрица, которая имеет только 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>(...)
, Конечно, этот метод возвращает ссылку. Код, который вы видите выше, не работает для нижней треугольной части матрицы, потому что после возврата ссылка исчезла.
Какой правильный и самый эффективный способ реализовать это, чтобы у меня была какая-то «труба» для нижней треугольной части матрицы, всегда проходит через std::conj
для обоих установить и получить?
Пожалуйста, попросите дополнительную информацию, если требуется. Спасибо.
Следуя примеру Франка, я предлагаю вернуть класс-оболочку (или структуру), которая переносит ссылку на элемент и запоминает логический флаг, чтобы запомнить, необходимо ли связывать число.
Что-то вроде [осторожно: не проверено]
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;
}
};
и ваша функция может стать [edit: изменена после соответствующего редактирования в вопросе (инверсия строки / столбца в другом случае)]
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)]);
}
Вы можете реализовать класс свойства и вернуть объект этого класса.
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 */ }
}
};
Это может быть назначено и автоматически преобразовано.
Учитывая, что std :: Con () не возвращает ссылку, у вас есть два варианта: