关于模板的使用

about the using of template

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

但我收到错误消息:

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

std::array 的维度指定为 size_t 类型。即使您已经使用 int 模板参数定义了 matrix 别名,您仍然会得到具有 size_t 维度的 std::array。编译器无法自动推断您的模板参数,因为它们的类型不匹配,如果您查看完整的错误消息,它甚至会提示您:

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