C++ 模板和铸件
我用模板创建了一个矩阵类:C++ 模板和铸件,c++,templates,C++,Templates,我用模板创建了一个矩阵类: template <typename T> class Matrix { static_assert(std::is_arithmetic<T>::value,""); public: Matrix(size_t n_rows, size_t n_cols); Matrix(size_t n_rows, size_t n_cols, const T& value); // Functions
template <typename T>
class Matrix
{
static_assert(std::is_arithmetic<T>::value,"");
public:
Matrix(size_t n_rows, size_t n_cols);
Matrix(size_t n_rows, size_t n_cols, const T& value);
// Functions
// Operators
Matrix<T>& operator*=(const T& value)
private:
size_t rows;
size_t cols;
std::vector<T> data;
};
模板
类矩阵
{
静态断言(std::is_算术::value,“”);
公众:
矩阵(大小n行、大小n列);
矩阵(行大小、列大小、常数和值);
//功能
//操作员
矩阵和运算符*=(常数T和值)
私人:
行大小;
尺码;
std::矢量数据;
};
我创建了以下两个(外部)运算符,将我的矩阵与一个数字相乘:
// Inner operator used by the externals ones
template <typename T>
inline Matrix<T>& Matrix<T>::operator*=(const T& value)
{
for(size_t i(0); i < data.size(); i++)
{
data[i] *= value;
}
return *this;
}
template <typename T>
inline Matrix<T> operator*(const T& value, const Matrix<T>& matrix)
{
Matrix<T> tmp(matrix);
return tmp *= value;
}
template <typename T>
inline Matrix<T> operator*(const Matrix<T>& matrix, const T& value)
{
return value * matrix;
}
//外部运算符使用的内部运算符
模板
内联矩阵和矩阵::运算符*=(常数T和值)
{
对于(size_t i(0);i
问题是,如果我将矩阵声明为双精度矩阵,我只能将矩阵乘以双精度矩阵,以此类推
Matrix<double> m1(3,3,1.);
5. * m1; // Works
5 * m1; // Doesn't work (5 is an int and not a double)
矩阵m1(3,3,1.);
5. * m1;//作品
5*m1;//不起作用(5是整数而不是双精度)
我怎样才能解决这个问题?可以让double与其他算术类型相乘吗?当然可以,只允许模板自由函数和成员函数使用两个参数 例如:
template <typename T> class Matrix {
/* ... */
template <typename U>
inline Matrix<T>& operator*=(const U& value)
{
for(size_t i(0); i < data.size(); i++)
{
data[i] *= value;
}
return *this;
}
};
template <typename T, typename U>
inline Matrix<T> operator*(const U& value, const Matrix<T>& matrix)
{
Matrix<T> tmp(matrix);
return tmp *= value;
}
模板类矩阵{
/* ... */
模板
内联矩阵和运算符*=(常数U和值)
{
对于(size_t i(0);i
如果您试图将矩阵与无意义的内容相乘,即
T*U
未定义,则会触发编译时错误。是。将矩阵类中的函数声明为
template <typename T>
class Matrix
{
public:
/* ... */
template <typename S>
inline Matrix & operator*=( const S & value );
/* ... */
};
您看到的问题是,模板类型推断需要所有推断类型的完美匹配。在本例中,您有一个模板,它接受一个类型参数
T
,该参数是标量类型和矩阵类型。当编译器看到操作:5*m1
时,它对第一个参数推断出T==int
,但对第二个参数推断出T==double
,类型推断失败
有多种方法可以解决此问题,正如所建议的,您可以添加第二个模板参数:
template <typename T, typename S>
Matrix<T> operator*( Matrix<T> m, S scalar ) {
return m*=scalar;
}
在这种方法中,有一个操作符*
,该操作符以双
作为参数。在前面的示例中,它可能需要对标量进行两次类型转换(例如,将矩阵
乘以5
,然后将5
转换为双精度
,然后将其转换回int
,以匹配运算符*=
的签名
第三种方法是创建一个非模板函数,该函数使用矩阵
和另一个相同类型的参数。这将与原始代码最接近,但有一点优势,即不是模板,它允许对标量参数进行转换。理论上,您可以自己定义所有此类函数法律上:
Matrix<int> operator*( Matrix<int>, int ) { ... }
Matrix<double> operator*( Matrix<double>, double ) { ... }
矩阵运算符*(矩阵,int){…}
矩阵算子*(矩阵,双){…}
但这很容易成为一个维护问题。幸运的是,该语言中有一个功能,允许一般地定义所有非模板函数。尽管语法可能不是最自然的。您只需要将自由函数声明为模板的朋友,并在类模板定义中定义它声明:
template <typename T>
class Matrix {
// ...
friend Matrix operator*( Matrix m, T scalar ) { return m*=scalar; }
};
模板
类矩阵{
// ...
友元矩阵算子*(矩阵m,T标量){返回m*=标量;}
};
由于我们在类模板
Matrix
中,我们可以使用Matrix
(无参数)引用当前实例化(Matrix
,MatrixI删除了“强制转换”tag.Conversion是指将一种类型的值更改为另一种类型。强制转换是指您告诉编译器进行转换。这里您要查找的是隐式转换,它不是强制转换。成员函数不需要此更改来帮助模板参数推断。但可能还有其他原因要这样做。@Aschepper:什么更改?我知道引入的唯一更改是模板化参数的类型,您需要它来允许它接受任意类型。您是否建议使用SFINAE检查是否允许T*U
?我只是说原始代码允许m1*=5;
,使用int模板>代码两次。lass(T
)和一次函数参数本身(S
)。这种方法很简单,但会为程序中的每个S和T组合生成一个运算符*,即使运算符*=中的实际乘法总是在T上执行。这是一个问题?每个S和T组合的生成只会减慢编译速度,或者在运行时也是一个问题?@R.M.:这不一定是坏的,而且在这种特殊情况下,如果实际函数只是一个转发器,那么它应该不会产生太大影响,而是说您直接实现了操作符*
(无转发器),那么对于S
和T
的每一个组合,编译器都必须生成函数,这意味着每一个组合都会有一个二进制实现,并且二进制会更大。我想说,一个更大的bi
template <typename T>
Matrix<T> operator*( Matrix<T> m, double scalar ) {
return m*=scalar;
}
Matrix<int> operator*( Matrix<int>, int ) { ... }
Matrix<double> operator*( Matrix<double>, double ) { ... }
template <typename T>
class Matrix {
// ...
friend Matrix operator*( Matrix m, T scalar ) { return m*=scalar; }
};