首页 > 解决方案 > 关于模板的使用

问题描述

我正在尝试重载矩阵乘法的运算符。

但我收到错误消息:

<source>:29:16: error: invalid operands to binary expression ('matrix<3, 3>' (aka 'array<array<int, 3>, 3>') and 'matrix<3, 2>' (aka 'array<array<int, 2>, 3>'))
    auto c = a * b;
             ~ ^ ~
<source>:12:6: note: candidate template ignored: substitution failure: deduced non-type template argument does not have the same type as the corresponding template parameter ('unsigned long' vs 'int')
auto operator* (const matrix<row, shared>& a, const matrix<shared, column>& b) -> matrix<row, column> {
     ^
1 error generated.
ASM generation compiler returned: 1
<source>:29:16: error: invalid operands to binary expression ('matrix<3, 3>' (aka 'array<array<int, 3>, 3>') and 'matrix<3, 2>' (aka 'array<array<int, 2>, 3>'))
    auto c = a * b;
             ~ ^ ~
<source>:12:6: note: candidate template ignored: substitution failure: deduced non-type template argument does not have the same type as the corresponding template parameter ('unsigned long' vs 'int')
auto operator* (const matrix<row, shared>& a, const matrix<shared, column>& b) -> matrix<row, column> {
     ^

我想知道我的代码有什么问题,或者我误解了如何使用模板。

#include <array>
#include <iostream>

using std::array;
using std::cout;
using std::endl;

template<int row, int column>
using matrix = array<array<int, column>, row>;

template<int row, int shared, int column>
auto operator* (const matrix<row, shared>& a, const matrix<shared, column>& b) -> matrix<row, column> {
    int row_index, column_index, index;
    matrix<row, column> c;
    
    for(row_index = 0; row_index < row; ++row_index) {
        for(column_index = 0; column_index < column; ++column_index) {
            for(index = 0; index < shared; ++index) {
                c[row_index][column_index] += a[row_index][index] * b[index][column_index];
            }
        }
    }
    return c;
}

int main(void) {
    matrix<3, 3> a = {{{3, 2, 1}, {5, 6, 7}, {2, 4, 6}}};
    matrix<3, 2> b = {{{2,3}, {3,4}, {6,2}}};
    auto c = a * b;
    for(auto line : c) {
        for(auto num : line) {
            cout << num << ' ';
        }
        cout << endl;
    }
    return 0;
}

如果我更改int为,unsigned long那么它可以工作。

template<unsigned long row, unsigned long shared, unsigned long column>
auto operator* (const matrix<row, shared>& a, const matrix<shared, column>& b) -> matrix<row, column> {
    int row_index, column_index, index;
    matrix<row, column> c;
    
    for(auto& line : c) {
        for(auto& num : line) {
            num = 0;
        }
    }
    
    for(row_index = 0; row_index < row; ++row_index) {
        for(column_index = 0; column_index < column; ++column_index) {
            for(index = 0; index < shared; ++index) {
                c[row_index][column_index] += a[row_index][index] * b[index][column_index];
            }
        }
    }
    return c;
}

标签: c++templatesoperator-overloading

解决方案


的尺寸std::array被指定为类型size_t。即使你已经用模板参数定义了你的matrix别名,你最终还是会得到一个带维度的。编译器无法自动推断您的模板参数,因为它们的类型不匹配,如果您查看完整的错误消息,它甚至会告诉您以下提示:intstd::arraysize_t

candidate template ignored: substitution failure: deduced non-type template argument does not have the same type as the corresponding template parameter ('unsigned long' vs 'int')

您还可以从等式中删除扣除,以表明您的函数至少是可调用的:

auto c = operator*<3,3,2>(a, b);

这确实可以编译,但可能不是您想要使用它的方式。

unsigned long可能与您平台上的类型相同,size_t这就是为什么更改类型以unsigned int解决问题的原因。

完全工作的跨平台代码将是:

template<size_t row, size_t column>
using matrix = array<array<int, column>, row>;

template<size_t row, size_t shared, size_t column>
auto operator* (const matrix<row, shared>& a, const matrix<shared, column>& b) -> matrix<row, column> {
    size_t row_index, column_index, index;
    matrix<row, column> c;
    
    for(row_index = 0; row_index < row; ++row_index) {
        for(column_index = 0; column_index < column; ++column_index) {
            for(index = 0; index < shared; ++index) {
                c[row_index][column_index] += a[row_index][index] * b[index][column_index];
            }
        }
    }
    return c;
}

推荐阅读