Как мне сделать, чтобы мой матричный объект неявно конвертировался в скаляр, когда его размеры 1×1?

Я написал Matrix учебный класс. Это делает умножения между матрицами. Иногда умножение матриц дает матрицу 1×1 (например, внутреннее произведение векторов двух столбцов). Можно ли сделать Matrix объект напрямую возвращает скалярное значение, когда оно одно за другим?

template <class T> class Matrix
{
public:
// ...
T&       operator()(uint64_t unRow, uint64_t unCol = 0) throw(MatrixOutOfRange);
const T& operator()(uint64_t unRow, uint64_t unCol = 0) const throw(MatrixOutOfRange);
// ...
protected:
std::vector<T> MatrixArray;
// ...
};

// ...

template <class T>
T & Matrix<T>::operator()(uint64_t unRow, uint64_t unCol /*= 0*/) throw(MatrixOutOfRange)
{
/* Bound checking here */
return MatrixArray[m_unColSize * unRow + unCol];
}

template <class T>
const T & Matrix<T>::operator()(uint64_t unRow, uint64_t unCol /*= 0*/) const throw(MatrixOutOfRange)
{
/* Bound checking here */
return MatrixArray[m_unColSize * unRow + unCol];
}

// ...

Пример кода:

Латексное изображение

Matrix<double> A (3, 1,    1.0, 2.0, 3.0);
Matrix<double> AT(1, 3,    1.0, 2.0, 3.0);   // Transpose of the A matrix
Matrix<double> B (3, 1,    4.0, 5.0, 6.0);
Matrix<double> C();

C = AT * B;
double Result1 = C(0, 0);
double Result2 = (AT * B)(0, 0);
double Result3 = A.InnerProductWith(B)(0, 0);

Я хочу отбросить ненужные аргументы спецификатора местоположения элемента (0, 0) когда результат представляет собой матрицу один за другим. Как это:

C = AT * B;
double Result1 = C;
double Result2 = AT * B;
double Result3 = A.InnerProductWith(B);

Это нормально, если выдает исключение, если результат не один за другим.

2

Решение

Да.

Это будет работать аналогично std::vector::at(), это также вызов времени компиляции, который всегда генерирует, если не выполнены определенные условия времени выполнения.

Оператор преобразования в тип T будет выглядеть так:

template <class T> class Matrix
{
public:
// ...
operator T &() {
// Throw here if size is not 1x1...

return (*this)( 0, 0 );
}

operator T const &() const {
// Throw here if size is not 1x1...

return (*this)( 0, 0 );
}
// ...
};

Весь ваш пример кода будет работать, как написано.

2

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

Нет, если размер не станет частью типа. Иначе, вам придется либо всегда иметь скалярное преобразование, либо никогда. Вы не можете изменить тип время компиляции функции (независимо от того, имеет ли он неявное преобразование) на основе время выполнения Факт — размер равен 1 в обоих измерениях или нет. Это потребовало бы предвидения со стороны компилятора.

0

Я думаю, что лучший способ сделать это — сделать ваши размеры частью типа:

template <class T, size_t NRows, size_t NCols>
class Matrix
{
public:
// ...
protected:
// ...
T M_storage[NRows][NCols]; // Or something...
};

Затем используйте специализацию шаблона, чтобы добавить оператор преобразования в матрицу 1×1:

template <class T>
class Matrix<T, 1, 1>
{
public:
// ...
operator T ()
{
return M_storage;//[0][0];
}
protected:
// ...
//T M_storage[1][1]; // Or something...
// Or even
T M_storage;
};
0
По вопросам рекламы [email protected]