Я создал матричный класс на C++.
namespace LinAlg {
template <typename T> class Matrix {
public:
Matrix();
Matrix(const uint64_t &rows, const uint64_t &cols);
template <typename P> operator P() const;
private:
uint64_t rows_, cols_;
std::vector<std::vector<T>> arr_;
};
template <typename T> template <typename P> Matrix<T>::operator P() const {
if constexpr (std::is_same_v<P, Matrix<int>> ||
std::is_same_v<P, Matrix<double>> ||
std::is_same_v<P, Matrix<float>>) {
Matrix<P> m(this->rows_, this->cols_);
for (uint64_t i = 0; i < this->rows_; i++) {
for (uint64_t j = 0; j < this->cols_; j++) {
m.arr_[i][j] = static_cast<P>(this->arr_[i][j]);
}
}
return m;
}
throw std::invalid_argument("Not a valid type conversions\n");
}
} // namespace LinAlg
Я реализовал преобразование типов Matrix<T> в Matrix<P>. Когда я попытался преобразовать Matrix<int> в Matrix<float> в своем test.cpp, используя следующий код:
LinAlg::Matrix<int> M(3, 3);
std::cin >> M;
LinAlg::Matrix<float> M1(3, 3);
std::cin >> M1;
std::cout << static_cast<LinAlg::Matrix<float>>(M) + M1 << "\n";
Я получаю ошибки типа arr_ — это private в контексте:
m.arr_[i][j] = static_cast<P>(this->arr_[i][j]);
У вашего Matrix, вероятно, есть какие-то общедоступные методы для получения/установки значений в матрице. Вы можете использовать его для решения проблемы, упомянутой в комментарии выше.
@wohlstad Я мог бы реализовать метод установки, но тогда какой смысл объявлять членов частными, если пользователь может манипулировать ими с помощью установки?
Инкапсуляция частных членов не противоречит использованию сеттеров. Но в любом случае, как вы предполагали, что пользователи класса будут устанавливать данные? (Кстати, вы также не публиковали никаких геттеров, поэтому тот же вопрос актуален для любого доступа).
Другая проблема: в m.arr_[i][j] = static_cast<P>(this->arr_[i][j]); - поскольку P - это вся матрица (а не тип элемента) - static_cast<P> попытка применить ее к элементу неверна.
... и у вас похожая проблема с Matrix<P> m(...);.
@VedantYadav опубликовал полный ответ на все проблемы, упомянутые выше.





Ваша главная проблема в том, что Matrix<T1> и Matrix<T2> (для типов T1,T2) — разные и не связанные между собой типы.
Поэтому Matrix<T1> не может получить доступ к частному члену в Matrix<T2>, и это является источником ошибки, которую вы получаете о том, что arr_ является частным в этой строке:
m.arr_[i][j] = static_cast<P>(this->arr_[i][j]);
Преодолеть эту проблему можно двумя способами:
Добавьте общедоступные методы доступа (сеттеры, геттеры) в Matrix и используйте их в реализации operator P() вместо доступа к частному arr_.
Мне это кажется лучшим решением, потому что пользователям класса, вероятно, в любом случае потребуются методы доступа для доступа к данным.
Если у вас есть веские причины избегать добавления аксессоров, и поскольку вы, похоже, поддерживаете только Matrix<int>,Matrix<double>, Matrix<float> (на основании вашего if constexpt), то вы можете подружиться с этими 3 классами:
friend Matrix<int>;
friend Matrix<double>;
friend Matrix<float>;
Это позволит вам получить доступ к приватному arr_.
Другая проблема в вашем коде заключается в том, что P — это тип целого Matrix<X> (для некоторого типа X), а не тип элемента в Matrix.
Поэтому эти две строки неверны:
Matrix<P> m(this->rows_, this->cols_);
И:
m.arr_[i][j] = static_cast<P>(this->arr_[i][j]);
Потому что они оба предполагают, что P — это тип элементов в Matrix.
Чтобы решить эту проблему, вы можете добавить псевдоним типа в Matrix (может быть полезно сделать его общедоступным):
template <typename T> class Matrix {
public:
using element_type = T;
// ...
};
Затем используйте его в двух строках выше:
Matrix<P::element_type> m(...);
И:
... = static_cast<P::element_type>(...);
Примечание. Возможно, вам придется использовать typename P::element_type вместо P::element_type (если ваша версия C++ более ранняя, чем C++20).
Matrix<A>иMatrix<B>— разные и неродственные типы. ЧастноеMatrix<A>::arr_не будет доступно вMatrix<B>. Вы могли бы сделать их друзьями.