You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为不同类型矩阵(deque/array of vectors等)泛化克罗内克积函数?

适配广义克罗内克积函数至多种矩阵类型

我已经实现了适用于std::vector<std::vector<T>>的广义克罗内克积函数,但目前卡在如何将其适配至其他类型矩阵(如std::deque<std::vector<T>>、std::array<std::vector<T>, N>等)的环节。我不确定是否应该、以及能否传入指向矩阵首尾的函数指针或迭代器,也不清楚这种方式是否适用于int array[]这类C风格数组。

原实现代码:

#include <iostream>
#include <cmath>
#include <vector>
#include <deque>
#include <iterator>
#include <iomanip>

template<typename T,typename T1,typename F>
std::vector<std::vector<T>> GeneralizedKroneckerProduct(std::vector<std::vector<T>>M1, std::vector<std::vector<T>>M2, F &f ){
    int m=M1.size();
    int n=M1.at(0).size();
    int p=M2.size();
    int q=M2.at(0).size();
    std::vector<std::vector<T1>>result(m*p,std::vector<T1>(n*q));
    for(int i=0; i<m;i++){
        for(int j=0; j<n;j++){
            for(int k=0; k<p;k++){
                for(int z=0; z<q;z++){
                    result.at(i*p+k).at(j*q+z)=f(M1.at(i).at(j),M2.at(k).at(z));
                }
            }
        }
    }
    return result;
}

int main ()
{
    std::cout<<"Enter dimensions of the first matrix: ";
    int m=0,n=0;
    std::cin>>m>>n;
    std::cout<<"Enter elements of the first matrix: ";
    std::vector<std::vector<int>>A;
    std::vector<int>temp;
    int number;
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            std::cin>>number;
            temp.push_back(number);
        }
        A.push_back(temp);
        temp.clear();
    }
    std::cout<<"Enter dimensions of the second matrix: ";
    int p=0,q=0;
    std::cin>>p>>q;
    std::cout<<"Enter elements of the second matrix: ";
    std::vector<std::vector<int>>B;
    for(int i=0;i<p;i++){
        for(int j=0;j<q;j++){
            std::cin>>number;
            temp.push_back(number);
        }
        B.push_back(temp);
        temp.clear();
    }

    auto f=[](int x, int y){return x*y;};
    auto result=GeneralizedKroneckerProduct<int,int,decltype(f)>(A, B,f);
    std::cout<<"Their Kronecker product is: "<<std::endl;
    for(const auto &row:result){
        for(const auto &number:row){
            std::cout<<std::setw(5)<<number<<" ";
        }
        std::cout<<std::endl;
    }

    return 0;
}

解决方案

1. 抽象容器类型为模板参数

将函数的输入矩阵类型改为模板参数,而非固定std::vector<std::vector<T>>,这样可以兼容所有支持size()和operator[]的二维容器(如std::deque、std::array):

template<typename Matrix1, typename Matrix2, typename F>
auto GeneralizedKroneckerProduct(const Matrix1& M1, const Matrix2& M2, F&& f) {
    using T = typename Matrix1::value_type::value_type;
    using T1 = decltype(f(M1[0][0], M2[0][0]));
    const size_t m = M1.size();
    const size_t n = M1[0].size();
    const size_t p = M2.size();
    const size_t q = M2[0].size();

    // 默认返回vector<vector<T1>>,也可扩展为用户自定义返回类型
    std::vector<std::vector<T1>> result(m * p, std::vector<T1>(n * q));
    for (size_t i = 0; i < m; ++i) {
        for (size_t j = 0; j < n; ++j) {
            for (size_t k = 0; k < p; ++k) {
                for (size_t z = 0; z < q; ++z) {
                    result[i * p + k][j * q + z] = f(M1[i][j], M2[k][z]);
                }
            }
        }
    }
    return result;
}

2. 兼容C风格数组

C风格数组无法直接作为二维容器传递(会退化为指针),可以通过以下两种方式处理:

  • 用std::array包装C风格数组,例如std::array<std::array<int, 2>, 2>
  • 为C风格数组提供重载版本:
// 重载:处理C风格二维数组
template<typename T, size_t m, size_t n, typename U, size_t p, size_t q, typename F>
auto GeneralizedKroneckerProduct(const T (&M1)[m][n], const U (&M2)[p][q], F&& f) {
    using T1 = decltype(f(M1[0][0], M2[0][0]));
    std::vector<std::vector<T1>> result(m * p, std::vector<T1>(n * q));
    for (size_t i = 0; i < m; ++i) {
        for (size_t j = 0; j < n; ++j) {
            for (size_t k = 0; k < p; ++k) {
                for (size_t z = 0; z < q; ++z) {
                    result[i * p + k][j * q + z] = f(M1[i][j], M2[k][z]);
                }
            }
        }
    }
    return result;
}

3. 测试不同容器类型

修改后的函数可以直接支持std::deque、std::array等:

int main() {
    // 测试std::deque<std::vector<int>>
    std::deque<std::vector<int>> dq1 = {{1,2}, {3,4}};
    std::deque<std::vector<int>> dq2 = {{5,6}, {7,8}};
    auto dq_result = GeneralizedKroneckerProduct(dq1, dq2, [](int x, int y){return x*y;});

    // 测试std::array<std::array<int,2>,2>
    std::array<std::array<int,2>,2> arr1 = {{{1,2}, {3,4}}};
    std::array<std::array<int,2>,2> arr2 = {{{5,6}, {7,8}}};
    auto arr_result = GeneralizedKroneckerProduct(arr1, arr2, [](int x, int y){return x*y;});

    // 测试C风格数组
    int c_arr1[2][2] = {{1,2}, {3,4}};
    int c_arr2[2][2] = {{5,6}, {7,8}};
    auto c_arr_result = GeneralizedKroneckerProduct(c_arr1, c_arr2, [](int x, int y){return x*y;});

    // 输出结果
    std::cout << "Deque result:\n";
    for (const auto& row : dq_result) {
        for (int num : row) std::cout << std::setw(5) << num;
        std::cout << "\n";
    }
    return 0;
}

关键要点

  • 使用模板参数抽象容器类型,避免绑定到具体的std::vector
  • 通过decltype自动推导返回值类型,无需手动指定T和T1
  • 对C风格数组单独重载,利用模板非类型参数获取数组维度
  • 优先使用operator[]而非at()以提升性能(若需边界检查可保留at())

内容的提问来源于stack exchange,提问作者eminbihh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 11:31:12