英文:
Giving two template class as arguments, choose the return template class using a hierarchy order
问题
I have a class Matrix defined as template<class T, int m_rows, int m_cols = m_rows> class Matrix
and an overloaded operator of the type template <class V, int m_cols2> Matrix operator * (const Matrix<V,m_cols,m_cols2>& other)
. The idea is that, for example, if T is complex and V is double, the returning matrix should be of the type V (complex). How do I accomplish that in the code?
As of now I have
template <class V, int m_cols2>
Matrix operator * (const Matrix<V,m_cols,m_cols2>& other) const {
Matrix<T,m_rows,other.m_cols> res;
for (int i = 0; i < m_rows; ++i) {
for (int k = 0; k < other.m_rows; ++k) {
res[i][k] = 0;
for (int j = 0; j < m_cols; ++j) {
res[i][k] += m_matrix[i][j]*other[j][k];
}
}
}
return res;
}
But this automatically sets the matrix "res" to the type T.
How can I tell that it should decide the type of res depending on the type hierarchy? For example
complex > double > integer?
Thanks for your answers
I have no idea what to try
英文:
I have a class Matrix defined as template<class T, int m_rows, int m_cols = m_rows> class Matrix
and an overloaded operator of the type template <class V, int m_cols2> Matrix operator * (const Matrix<V,m_cols,m_cols2>& other)
. The idea is that, for example, if T is a complex and V is a double, the returning matrix should be of the type V (complex). How do I accomplish that in the code?
As of now I have
template <class V, int m_cols2>
Matrix operator * (const Matrix<V,m_cols,m_cols2>& other) const {
Matrix<T,m_rows,other.m_cols> res;
for (int i = 0; i < m_rows; ++i) {
for (int k = 0; k < other.m_rows; ++k) {
res[i][k] = 0;
for (int j = 0; j < m_cols; ++j) {
res[i][k] += m_matrix[i][j]*other[j][k];
}
}
}
return res;
}
But this automatically sets the matrix "res" to the type T.
How can I tell that it should decide the type of res depending on the type hierarchy? For example
complex > double > integer?
Thanks for your answers
I have no idea what to try:)
答案1
得分: 3
你可以生成一个"common type"的矩阵:
// 注意:最好不要将模板参数命名为"m_something",因为这会与类的数据成员造成混淆。
template <class OtherT, int OtherCols>
auto operator * (const Matrix<OtherT, Cols, OtherCols>& other) const
-> Matrix<std::common_type_t<T, OtherT>, Rows, OtherCols>> // trailing return type
{
// 使用 decltype 避免复制和粘贴返回类型。
// 我们还可以使用推导返回类型(只是 auto,没有 trailing -> ...),
// 但这不会对 SFINAE 友好,即:即使没有共同的类型,operator* 也会被实例化。
decltype(*this * other) result;
for // ...
return result;
}
如果你的 complex
类是 std::complex
,你可以像上面的示例一样使用 std::common_type
。否则,你可能需要为你的类型专门化 std:common_type<Complex, ...>
以使其工作。
这是因为 double
可以隐式转换为 std::complex<double>
,但反之则不行。它也适用于 int
和 double
,即:
static_assert(std::is_same_v<double, std::common_type_t<int, double>>); // 通过
英文:
You could produce a matrix of a "common type":
// note: it's best not to call template parameters "m_something", because
// it creates confusion with data members of the class.
template <class OtherT, int OtherCols>
auto operator * (const Matrix<OtherT, Cols, OtherCols>& other) const
-> Matrix<std::common_type_t<T, OtherT>, Rows, OtherCols>> // trailing return type
{
// Avoid copying and pasing the return type with decltype.
// We could also use a deduced return type (just auto, no trailing -> ...),
// however, this wouldn't be SFINAE-friendly, i.e.: operator* gets
// instantiated even if there is no common type.
decltype(*this * other) result;
for // ...
return result;
}
If your complex
class is std::complex
, you can just use std::common_type
like in the above example. Otherwise you may have to specialize std:common_type<Complex, ...>
for your type to make it work.
This works because a double
is implicitly convertible to a std::complex<double>
, but not the other way around. It also works for int
and double
, i.e.
static_assert(std::is_same_v<double, std::common_type_t<int, double>>); // passes
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论