Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模板和铸件_C++_Templates - Fatal编程技术网

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