C++ C++;矩阵模板,矩阵和矩阵数乘法之间的歧义

C++ C++;矩阵模板,矩阵和矩阵数乘法之间的歧义,c++,templates,matrix,operator-overloading,ambiguity,C++,Templates,Matrix,Operator Overloading,Ambiguity,我正在写一个矩阵模板类。一切顺利,直到我重载乘法运算符。我的班级是这样的: 模板类矩阵 { 私人: // ... TNum*数据; 公众: const TMatIdx NRows;//类型TMatIdx在其他地方定义。 常数TMatIdx NCols; 常数Tmax大小; // ... //矩阵*矩阵 模板 常数矩阵运算符*(常数矩阵和右)常数; //矩阵*数 模板 矩阵和运算符*=(常数T2和比例); }; //矩阵*数 模板 矩阵算子*(矩阵lhs、常数T2和rhs); //数字*矩阵 模板

我正在写一个矩阵模板类。一切顺利,直到我重载乘法运算符。我的班级是这样的:

模板类矩阵
{
私人:
// ...
TNum*数据;
公众:
const TMatIdx NRows;//类型TMatIdx在其他地方定义。
常数TMatIdx NCols;
常数Tmax大小;
// ...
//矩阵*矩阵
模板
常数矩阵运算符*(常数矩阵和右)常数;
//矩阵*数
模板
矩阵和运算符*=(常数T2和比例);
};
//矩阵*数
模板
矩阵算子*(矩阵lhs、常数T2和rhs);
//数字*矩阵
模板
矩阵算子*(常数T2&lhs,矩阵rhs);
我希望用相同的
*
运算符涵盖矩阵和数字之间所有可能的乘法组合

然后我编写了一个小测试程序,将两个
矩阵相乘,我的clang++编译器抱怨有歧义:

test.cpp:46: error: ambiguous overload for 'operator*' in 'M * N'
matrix.h:225: note: candidates are: const QCD::Matrix<TNum> QCD::Matrix<TNum>::operator*(const QCD::Matrix<T2>&) const [with T2 = double, TNum = double]
matrix.h:118: note:                 QCD::Matrix<TNum> QCD::operator*(const T2&, QCD::Matrix<TNum>) [with TNum = double, T2 = QCD::Matrix<double>]
matrix.h:109: note:                 QCD::Matrix<TNum> QCD::operator*(QCD::Matrix<TNum>, const T2&) [with TNum = double, T2 = QCD::Matrix<double>]
test.cpp:52: error: ambiguous overload for 'operator*' in 'M * N'
matrix.h:225: note: candidates are: const QCD::Matrix<TNum> QCD::Matrix<TNum>::operator*(const QCD::Matrix<T2>&) const [with T2 = double, TNum = double]
matrix.h:118: note:                 QCD::Matrix<TNum> QCD::operator*(const T2&, QCD::Matrix<TNum>) [with TNum = double, T2 = QCD::Matrix<double>]
matrix.h:109: note:                 QCD::Matrix<TNum> QCD::operator*(QCD::Matrix<TNum>, const T2&) [with TNum = double, T2 = QCD::Matrix<double>]
template <typename TNum, typename T2>
typename std::enable_if< (!std::is_same<Matrix<TNum>, T2>::value),
Matrix<TNum> >::type operator*(const T2& lhs, Matrix<TNum> rhs);
test.cpp:46:错误:“M*N”中“operator*”的重载不明确
matrix.h:225:注:候选项为:常数QCD::矩阵QCD::矩阵::运算符*(常数QCD::矩阵&)常数[其中T2=double,TNum=double]
matrix.h:118:注:QCD::matrix QCD::operator*(常数T2&,QCD::matrix)[其中TNum=double,T2=QCD::matrix]
matrix.h:109:注:QCD::matrix QCD::operator*(QCD::matrix,const T2&)[带TNum=double,T2=QCD::matrix]
test.cpp:52:错误:“M*N”中“operator*”的重载不明确
matrix.h:225:注:候选项为:常数QCD::矩阵QCD::矩阵::运算符*(常数QCD::矩阵&)常数[其中T2=double,TNum=double]
matrix.h:118:注:QCD::matrix QCD::operator*(常数T2&,QCD::matrix)[其中TNum=double,T2=QCD::matrix]
matrix.h:109:注:QCD::matrix QCD::operator*(QCD::matrix,const T2&)[带TNum=double,T2=QCD::matrix]
是否有可能克服这种模糊性,而不必明确地写下T2的所有可能的专门化

仅供参考,以下是我的实施:

template<typename TNum> template <typename T2>
Matrix<TNum>& Matrix<TNum> ::
operator*=(const T2& rhs)
{
    for(TMatIdx i = 0; i < Size; i++)
        Data[i] *= rhs;
    return *this;
}

template<typename TNum> template <typename T2>
const Matrix<TNum> Matrix<TNum> ::
operator*(const Matrix<T2>& right) const
{
    Matrix<TNum> c(NRows, right.NCols);
    TNum sum_elems;
    for(TMatIdx i = 0; i < NRows; i++)
    {
        for(TMatIdx j = 0; j < right.NCols; j++)
        {
            sum_elems = TNum(0);
            for(TMatIdx k = 0; k < right.NRows; k++)
            {
                sum_elems += at(i, k) * right.at(k, j);
            }

            c.at(i, j) = sum_elems;
        }
    }
    return c;
}


template <typename TNum, typename T2>
Matrix<TNum> operator*(Matrix<TNum> lhs, const T2& rhs)
{
    lhs *= rhs;
    return lhs;
}

template <typename TNum, typename T2>
Matrix<TNum> operator*(const T2& lhs, Matrix<TNum> rhs)
{
    rhs *= lhs;
    return rhs;
}
模板
矩阵和矩阵::
运算符*=(常数T2和rhs)
{
对于(TMatIdx i=0;i
这可能会有所帮助

#include<utility>

template<class Type>
struct test{
private:
    struct _matrix{};
    struct _scalar{};
    template<class T>
    struct category{
        typedef _scalar type;
    };
    template<class T>
    struct category<test<T>>{
        typedef _matrix type;
    };

    template<class T>
    void do_foo(T, _matrix){}

    template<class T>
    void do_foo(T, _scalar){}

public:
    //c++11
    template<class T>
    void operator*(T&& a){
        do_foo(std::forward<T>(a), category<T>::type());
    }
    //Older Compiler
    //template<class T>
    //void operator*(const T& a){
    //  do_foo(a, category<T>::type());
    //}

};

int main(){
    typedef test<int> int_matrix;
    int_matrix obj;
    obj*int_matrix();
    obj*obj;
    obj*1;
    obj*1.;

    return 0;
}
#包括
模板
结构测试{
私人:
结构矩阵{};
结构_标量{};
模板
结构类别{
typedef_标量类型;
};
模板
结构类别{
typedef_矩阵类型;
};
模板
void do_foo(T,_矩阵){}
模板
void do_foo(T,_标量){}
公众:
//c++11
模板
无效运算符*(T&&a){
do_foo(std::forward(a),category::type());
}
//旧编译器
//模板
//无效运算符*(常数T&a){
//do_foo(a,category::type());
//}
};
int main(){
typedef测试int_矩阵;
int_矩阵obj;
obj*int_矩阵();
obj*obj;
obj*1;
obj*1。;
返回0;
}
这可能会有所帮助

#include<utility>

template<class Type>
struct test{
private:
    struct _matrix{};
    struct _scalar{};
    template<class T>
    struct category{
        typedef _scalar type;
    };
    template<class T>
    struct category<test<T>>{
        typedef _matrix type;
    };

    template<class T>
    void do_foo(T, _matrix){}

    template<class T>
    void do_foo(T, _scalar){}

public:
    //c++11
    template<class T>
    void operator*(T&& a){
        do_foo(std::forward<T>(a), category<T>::type());
    }
    //Older Compiler
    //template<class T>
    //void operator*(const T& a){
    //  do_foo(a, category<T>::type());
    //}

};

int main(){
    typedef test<int> int_matrix;
    int_matrix obj;
    obj*int_matrix();
    obj*obj;
    obj*1;
    obj*1.;

    return 0;
}
#包括
模板
结构测试{
私人:
结构矩阵{};
结构_标量{};
模板
结构类别{
typedef_标量类型;
};
模板
结构类别{
typedef_矩阵类型;
};
模板
void do_foo(T,_矩阵){}
模板
void do_foo(T,_标量){}
公众:
//c++11
模板
无效运算符*(T&&a){
do_foo(std::forward(a),category::type());
}
//旧编译器
//模板
//无效运算符*(常数T&a){
//do_foo(a,category::type());
//}
};
int main(){
typedef测试int_矩阵;
int_矩阵obj;
obj*int_矩阵();
obj*obj;
obj*1;
obj*1。;
返回0;
}
这可能会有所帮助

#include<utility>

template<class Type>
struct test{
private:
    struct _matrix{};
    struct _scalar{};
    template<class T>
    struct category{
        typedef _scalar type;
    };
    template<class T>
    struct category<test<T>>{
        typedef _matrix type;
    };

    template<class T>
    void do_foo(T, _matrix){}

    template<class T>
    void do_foo(T, _scalar){}

public:
    //c++11
    template<class T>
    void operator*(T&& a){
        do_foo(std::forward<T>(a), category<T>::type());
    }
    //Older Compiler
    //template<class T>
    //void operator*(const T& a){
    //  do_foo(a, category<T>::type());
    //}

};

int main(){
    typedef test<int> int_matrix;
    int_matrix obj;
    obj*int_matrix();
    obj*obj;
    obj*1;
    obj*1.;

    return 0;
}
#包括
模板
结构测试{
私人:
结构矩阵{};
结构_标量{};
模板
结构类别{
typedef_标量类型;
};
模板
结构类别{
typedef_矩阵类型;
};
模板
void do_foo(T,_矩阵){}
模板
void do_foo(T,_标量){}
公众:
//c++11
模板
无效运算符*(T&&a){
do_foo(std::forward(a),category::type());
}
//旧编译器
//模板
//无效运算符*(常数T&a){
//do_foo(a,category::type());
//}
};
int main(){
typedef测试int_矩阵;
int_矩阵obj;
obj*int_矩阵();
obj*obj;
obj*1;
obj*1。;
返回0;
}
这可能会有所帮助

#include<utility>

template<class Type>
struct test{
private:
    struct _matrix{};
    struct _scalar{};
    template<class T>
    struct category{
        typedef _scalar type;
    };
    template<class T>
    struct category<test<T>>{
        typedef _matrix type;
    };

    template<class T>
    void do_foo(T, _matrix){}

    template<class T>
    void do_foo(T, _scalar){}

public:
    //c++11
    template<class T>
    void operator*(T&& a){
        do_foo(std::forward<T>(a), category<T>::type());
    }
    //Older Compiler
    //template<class T>
    //void operator*(const T& a){
    //  do_foo(a, category<T>::type());
    //}

};

int main(){
    typedef test<int> int_matrix;
    int_matrix obj;
    obj*int_matrix();
    obj*obj;
    obj*1;
    obj*1.;

    return 0;
}
#包括
模板
结构测试{
私人:
结构矩阵{};
结构_标量{};
模板
结构类别{
typedef_标量类型;
};
模板
结构类别{
typedef_矩阵类型;
};
模板
void do_foo(T,_矩阵){}
模板
void do_foo(T,_标量){}
公众:
//c++11
模板
无效运算符*(T&&a){
do_foo(std::forward(a),category::type());
}
//旧编译器
//模板
//无效运算符*(常数T&a){
//do_foo(a,category::type());
//}
};
int main(){
typedef测试int_矩阵;
int_矩阵obj;
obj*int_矩阵();
obj*obj;
obj*1;
obj*1。;
返回0;
}

我将描述一个使用c++11的解决方案,然后解释如何在c++98中实现它

在c++11中,头
包括类型函数和类型谓词
template<typename, typename>
struct is_same{
  static const bool value = false;
};

template<typename T>
struct is_same<T, T>{
  static const bool value = true;
};
struct false_type {
  static const bool value = false;
};

struct true_type {
  static const bool value = true;
};
template<typename, typename>
struct is_same : false_type {};

template<typename T>
struct is_same<T, T> : true_type {};