gpt4 book ai didi

c++ - 如何在运算符重载中将 int 类型的模板矩阵类 static_cast 转换为 double 类型?

转载 作者:行者123 更新时间:2023-12-04 07:14:17 26 4
gpt4 key购买 nike

编写一个运算符函数以将自定义模板矩阵类与标量相乘。

template <typename T>
class Matrix
{
public:
Matrix() //default constructor
Matrix(size_t Row, size_t Col); //initialize with zeros of row,col
explicit Matrix(const vector<vector<T>> matElems); // create a matrix from vec<vec>>
friend Matrix<ret_type> operator*(const Matrix<mat_type> matrix,
const scalar_type scalar);

private:
vector<vector<T>> elements;
std::size_t nRows;
std::size_t nCols;
};

template <typename mat_type, typename scalar_type,
typename ret_type = decltype(mat_type()* scalar_type())>
Matrix<ret_type> operator*(const Matrix<mat_type> matrix,
const scalar_type scalar)
{
Matrix<mat_type> copy_matrix = matrix;

Matrix<ret_type> result = static_cast<Matrix<ret_type>>(copy_matrix);

for (vector<ret_type> v : result.elements)
{
std::transform(v.begin(), v.end(), v.begin(),
std::bind1st(std::multiplies<ret_type>(), scalar));
}
return result;
}

错误:
no matching function for call to ‘Matrix<double>::Matrix(Matrix<int>&)’
on the line **Matrix<ret_type> result = static_cast<Matrix<ret_type>>(copy_matrix)**
这样做的原因是,如果乘以双标量,则将 int 类型矩阵转换为 double。

最佳答案

你有类型不匹配的问题!Matrix是一个类模板,当您使用模板参数实例化时,它会为您提供具体类型 T .这意味着实例化的类具有两个不同的 T s 将是两种不同类型的 Matrix .
这意味着,Matrix<ret_type>不同于 Matrix<mat_type> ,因此转换将不起作用,您已在此行尝试过:

Matrix<ret_type> result = static_cast<Matrix<ret_type>>(copy_matrix);
这会产生编译器错误!
您需要遍历 Matrix<mat_type> 的每个元素并转换到 ret_type并制作一个新的 Matrix<ret_type>从它。
话虽如此,
  • 您不需要在那里进行类型转换。既然要返回一个新的Matrix<ret_type>来自 Matrix<int> ,你可以生成一个新的 Matrix来自传递的所需类型 matrix .
  • std::bind1st 已在 中弃用 并已在 中删除 .因此,将它们放在代码库中会在 future 的编译器更新中产生编译器错误。由于您可以访问 , 使用 lambda functions instead .
  • 最后但并非最不重要的,看看:Why is "using namespace std;" considered bad practice?

  • 以下是更新后的代码。我希望评论可以驱动代码!
    #include <iostream>
    #include <vector>
    #include <utility> // std::move
    #include <type_traits> // std::common_type

    template <typename T> class Matrix /* final */
    {
    private:
    std::vector<std::vector<T>> elements{};
    std::size_t nRows{};
    std::size_t nCols{};

    public:
    Matrix() = default; // default constructor
    explicit Matrix(std::vector<std::vector<T>> matElems)
    : elements{ std::move(matElems) }
    , nRows{ elements.size() }
    , nCols{ elements.empty() ? 0u : elements[0].size() }
    {}

    template<typename mat_type, typename scalar_type>
    friend auto operator*(const Matrix<mat_type>& matrix, const scalar_type scalar)
    ->Matrix<typename std::common_type<mat_type, scalar_type>::type>;
    // or
    // -> Matrix<decltype(mat_type{} * scalar_type{})> ;

    // some useful member functions!
    void reserve(const std::size_t n) noexcept { elements.reserve(n); }
    std::size_t size() const noexcept { return elements.size(); }

    // to make the "Matrix" iteratable: Useful in range-based for loop/ standard algorithms.
    auto begin() noexcept ->decltype(elements.begin()) { return elements.begin(); }
    auto end() noexcept ->decltype(elements.end()) { return elements.end(); }

    auto begin() const noexcept ->decltype(elements.cbegin()) { return elements.cbegin(); }
    auto end() const noexcept ->decltype(elements.cend()) { return elements.cend(); }

    // operator<< overload for printing
    friend std::ostream& operator<<(std::ostream& out, const Matrix& obj) noexcept
    {
    for (const auto& raw: obj)
    {
    for (const T ele : raw) out << ele << ' ';
    out << '\n';
    }
    return out;
    }
    };

    // non-member operator* definition
    template<typename mat_type, typename scalar_type>
    auto operator*(const Matrix<mat_type>& matrix, const scalar_type scalar)
    -> Matrix<typename std::common_type<mat_type, scalar_type>::type>
    // or
    // -> Matrix<decltype(mat_type{} * scalar_type{}) >
    {
    using ret_type = typename std::common_type<mat_type, scalar_type>::type;

    Matrix<ret_type> result; // default constructed matrix!
    // reserve some memory for "Matrix" for unwanted reallocations!
    result.reserve(matrix.size()); // calls the Matrix<T>::reserve()

    for (const std::vector<mat_type>& rawVec : matrix)
    {
    std::vector<ret_type> newRaw;
    // reserve the memory for raw vectors for unwanted reallocations!
    newRaw.reserve(rawVec.size());

    for (mat_type element : rawVec) newRaw.emplace_back(element * scalar);

    // add the updated raws to the "result"
    result.elements.emplace_back(newRaw);
    }
    return result;
    }

    int main()
    {
    Matrix<int> matInt{ { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} } };
    auto res = matInt * 0.1;
    std::cout << res; // 0.1 0.2 0.3
    // 0.4 0.5 0.6
    // 0.7 0.8 0.9
    return 0;
    }
    这是 ( a complete demo )

    另外,请注意,您始终可以拥有一维 std::vector (如果 raw-size 和 col-size 是运行时)或 std::array (如果维度在编译时已知),并通过索引操作将它们视为二维数组。

    关于c++ - 如何在运算符重载中将 int 类型的模板矩阵类 static_cast 转换为 double 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68879971/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com