如何专门化模板类的模板化运算符重载?

时间:2021-07-26 11:42:56

标签: c++ templates template-specialization

我有一个这样的矩阵类:

template <class Type, size_t x_dim, size_t y_dim>
class mat {
  private:
    std::array<Type, x_dim * y_dim> m_data;
    size_t xdim = x_dim, ydim = y_dim; // xdim=no of cols   ydim= no of rows
public:
    // normal constructor to make unit matrix
     mat() {
        for (int i = 0; i < y_dim; i++)
            for (size_t j = 0; j < x_dim; j++)
                operator()(i, j) = i == j ? 1 : 0;
    }
    
    //constructor to take in array
    mat(const std::array<Type, x_dim * y_dim> &in) {
        assert(in.size() == x_dim * y_dim);
        m_data = in;
    }
    
    // () overload to access elements of matrix
    Type &operator()(const size_t &r, const size_t &c){
        assert(r >= 0 && r < y_dim && c >= 0 && c < x_dim);
        return m_data[r * xdim + c];
    }

    // * overload to multiply two matrices 
    template <size_t lx, size_t ly>
    mat<Type, x_dim, ly> operator*(const mat<Type, lx, ly> &in) const {
        assert(x_dim == ly);
        mat<Type, x_dim, ly> ret;
        int i, j, k;
        for (i = 0; i < y_dim; i++) {
            for (j = 0; j < lx; j++) {
                ret(i, j) = 0;
                for (k = 0; k < x_dim; k++)
                    ret(i, j) += operator()(i, k) * in(k, j);
            }
        }
        return ret;
    }
#ifdef _MSC_VER
    template <>
    mat<Type, xdim, 4> operator*<4,4>(const mat<Type, 4, 4> &in) const;
#endif
};

我如何专门为任何 operator* 使用 mat<Type,4,4> 函数以删除 for 循环。我尝试在上面定义的类之外编写下面的代码:

template <class Type, size_t x_dim, size_t y_dim>
template <size_t lx, size_t ly>
mat<Type, 4, 4> mat<Type, 4, 4>::operator*<4, 4>(const mat<Type, 4, 4> &in) const {
    return mat<Type, 4, 4>({
        operator()(0, 0) * in(0, 0) + operator()(0, 1) * in(1, 0) + operator()(0, 2) * in(2, 0) + operator()(0, 3) * in(3, 0),
        operator()(0, 0) * in(0, 1) + operator()(0, 1) * in(1, 1) + operator()(0, 2) * in(2, 1) + operator()(0, 3) * in(3, 1),
        operator()(0, 0) * in(0, 2) + operator()(0, 1) * in(1, 2) + operator()(0, 2) * in(2, 2) + operator()(0, 3) * in(3, 2),
        operator()(0, 0) * in(0, 3) + operator()(0, 1) * in(1, 3) + operator()(0, 2) * in(2, 3) + operator()(0, 3) * in(3, 3),
        operator()(1, 0) * in(0, 0) + operator()(1, 1) * in(1, 0) + operator()(1, 2) * in(2, 0) + operator()(1, 3) * in(3, 0),
        operator()(1, 0) * in(0, 1) + operator()(1, 1) * in(1, 1) + operator()(1, 2) * in(2, 1) + operator()(1, 3) * in(3, 1),
        operator()(1, 0) * in(0, 2) + operator()(1, 1) * in(1, 2) + operator()(1, 2) * in(2, 2) + operator()(1, 3) * in(3, 2),
        operator()(1, 0) * in(0, 3) + operator()(1, 1) * in(1, 3) + operator()(1, 2) * in(2, 3) + operator()(1, 3) * in(3, 3),
        operator()(2, 0) * in(0, 0) + operator()(2, 1) * in(1, 0) + operator()(2, 2) * in(2, 0) + operator()(2, 3) * in(3, 0),
        operator()(2, 0) * in(0, 1) + operator()(2, 1) * in(1, 1) + operator()(2, 2) * in(2, 1) + operator()(2, 3) * in(3, 1),
        operator()(2, 0) * in(0, 2) + operator()(2, 1) * in(1, 2) + operator()(2, 2) * in(2, 2) + operator()(2, 3) * in(3, 2),
        operator()(2, 0) * in(0, 3) + operator()(2, 1) * in(1, 3) + operator()(2, 2) * in(2, 3) + operator()(2, 3) * in(3, 3),
        operator()(3, 0) * in(0, 0) + operator()(3, 1) * in(1, 0) + operator()(3, 2) * in(2, 0) + operator()(3, 3) * in(3, 0),
        operator()(3, 0) * in(0, 1) + operator()(3, 1) * in(1, 1) + operator()(3, 2) * in(2, 1) + operator()(3, 3) * in(3, 1),
        operator()(3, 0) * in(0, 2) + operator()(3, 1) * in(1, 2) + operator()(3, 2) * in(2, 2) + operator()(3, 3) * in(3, 2),
        operator()(3, 0) * in(0, 3) + operator()(3, 1) * in(1, 3) + operator()(3, 2) * in(2, 3) + operator()(3, 3) * in(3, 3)};    
   }); 
} 

我从 msvc 的智能感知中收到此错误: enter image description here

以及来自编译器的这个错误: 1>Project\Application\include\maths.h(723,34): warning C4346: 'mat<Type,4,4>::*': dependent name is not a type

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

我将使用一个更简单的例子:

template <typename T,size_t x>
struct foo {    
    template <size_t y>
    foo<T,x+y> operator*(const foo<T,y>& other){ return {};}
};

如果不专门化 foo::operator*,您就不能专门化 x==4foo。不过,您可以提供非成员 operator* 并重载它:

#include <iostream>

template <typename T,size_t x> struct foo {};

template <typename T,size_t x,size_t y>
foo<T,x+y> operator*(const foo<T,x>& a,const foo<T,y>& b){ 
    std::cout << "general operator*\n";
    return {};
}

template <typename T>
foo<T,4> operator*(const foo<T,4>& a,const foo<T,4>& b){
    std::cout << "4*4\n";
    return {};
}

int main() {
    foo<int,4> f;
    foo<int,3> g;
    f*f;
    g*g;
}

Output

4*4
general operator*

答案 1 :(得分:0)

temp.spec#temp.expl.spec-16

<块引用>

成员或成员模板可以嵌套在许多封闭的类模板中。在对此类成员的显式特化中,对于每个显式特化的封闭类模板,成员声明应在 template<> 之前。

相关问题