C++11 为什么模板友元函数的这种局部专门化会起作用?

C++11 为什么模板友元函数的这种局部专门化会起作用?,c++11,templates,template-meta-programming,template-specialization,friend-function,C++11,Templates,Template Meta Programming,Template Specialization,Friend Function,作为学习OpenGL的一部分,我正在编写实现向量和矩阵的简单类。我有如下的矩阵和向量类: // Forward declarations template <typename T, size_t N/*len*/> struct vec; template<typename T, size_t N /*rows*/, size_t M /*cols*/> struct mat; // Forward declare *operator for matrix // (Nx

作为学习OpenGL的一部分,我正在编写实现向量和矩阵的简单类。我有如下的矩阵和向量类:

// Forward declarations
template <typename T, size_t N/*len*/> struct vec;
template<typename T, size_t N /*rows*/, size_t M /*cols*/> struct mat;

// Forward declare *operator for matrix
// (NxM) matrix multiplied by (MxP) matrix yields (NxP) matrix
mat<T, N, P> operator* (const mat<T, N, M>& A, const mat<T, M, P>& B);

template <typename T, size_t N>
struct vec {
    public:
        vec() {}
        virtual ~vec() {}
    private:
        T[N] m_data;
};

template <typename T, size_t N, size_t M>
struct mat {
    public:
        mat() {}
        virtual ~mat() {}
        // This is where it gets interesting. By my reading of the rules
        // of C++11, this counts as a partial specialization of the 
        // operator template, and should not work. 
        // However, it compiles just fine!
        template <size_t n, size_t m, size_t p> 
        friend mat<T, n, p> operator* (const mat<T, n, m>& A,
                                         const mat<T, m, p> &B); 
        // Implementation appears later in the same header file. 
    private:
        T[N*M] m_data;
};
//转发声明
模板结构向量;
模板结构材料;
//矩阵的前向declare*运算符
//(NxM)矩阵乘以(MxP)矩阵得到(NxP)矩阵
mat操作员*(常数mat&A、常数mat&B);
模板
结构向量{
公众:
vec(){}
虚拟~vec(){}
私人:
T[N]m_数据;
};
模板
结构垫{
公众:
mat(){}
虚拟~mat(){}
//这就是它变得有趣的地方。通过我对规则的阅读
//对于C++11,这算作
//操作员模板,并且不应工作。
//但是,它编译得很好!
模板
friend mat operator*(const mat&A,
康斯特酒店;
//实现稍后出现在同一头文件中。
私人:
T[N*M]M_数据;
};
我将*操作符声明为朋友,因为我希望它能够访问内部
m_data
成员,但我不希望'mat'和'vec'的用户了解内部

这可以编译并运行得很好。我有一个矩阵乘法的单元测试,它工作得很好。然而,我不知道它为什么会编译,更不用说运行了。通过阅读C++模板的规则,*操作符的声明作为函数模板的部分专门化计数,是非法的。 我在这里遗漏了什么?

结果表明,这不*编译。我认为它是在编译,因为我在单元测试中没有调用模板流操作符


对不起,这个愚蠢的问题

请添加用于成功构建程序的其余代码。