c ++ 11 — C ++: прокси для установки / получения значения массива со сложным сопряжением

Я пишу класс для Эрмитовы матрицы. Это сложная матрица, которая имеет только 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 для обоих установить и получить?

Пожалуйста, попросите дополнительную информацию, если требуется. Спасибо.

1

Решение

Следуя примеру Франка, я предлагаю вернуть класс-оболочку (или структуру), которая переносит ссылку на элемент и запоминает логический флаг, чтобы запомнить, необходимо ли связывать число.

Что-то вроде [осторожно: не проверено]

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)]);
}
2

Другие решения

Вы можете реализовать класс свойства и вернуть объект этого класса.

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 */ }
}
};

Это может быть назначено и автоматически преобразовано.

1

Учитывая, что std :: Con () не возвращает ссылку, у вас есть два варианта:

  • не возвращать ссылку в вашей функции, но значение
  • реализовать собственную версию функции std :: Con (), которая возвращает ссылку
0
По вопросам рекламы [email protected]