首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在正确的全局运算符上推导出错误的成员运算符

在正确的全局运算符上推导出错误的成员运算符
EN

Stack Overflow用户
提问于 2016-03-08 17:30:33
回答 1查看 98关注 0票数 1

我有一个3x3的Matrix和一个3x1的Vector类。我有两个乘法运算符;一个用于将矩阵与标量相乘,另一个用于将矩阵与向量对象相乘。矩阵标量乘法运算符是Matrix类中的成员,矩阵向量乘法运算符是全局的。

代码语言:javascript
复制
#include <initializer_list>
#include <array>

template <class T>
class Matrix
{
    public:
        Matrix(std::initializer_list<T> List);
        Matrix() : Matrix({0,0,0,0,0,0,0,0,0}) {}

        template <class S>                      // THE COMPILER TRIES TO USE
        Matrix<T> operator*(const S & Scalar);  // THIS OPERATOR IN BOTH CASES.

        const T & operator()(size_t i, size_t j) const;

    private:
        static constexpr size_t SIZE = 3;
        static constexpr size_t AREA = SIZE * SIZE;
        std::array<T, AREA> E;
};

template <class T>
Matrix<T>::Matrix(std::initializer_list<T> List)
{
    if (List.size() != AREA) throw("Error!");
    for (size_t i=0; i<AREA; i++)
    {
        E[i] = *(List.begin() + i);
    }
}

template <class T>
const T & Matrix<T>::operator()(size_t i, size_t j) const
{
    return E[SIZE * j + i];
}

template <class T>
template <class S>
Matrix<T> Matrix<T>::operator*(const S & Scalar)
{
    const T ScalarT = static_cast<T>(Scalar);
    Matrix<T> Result;
    for (size_t i=0; i<AREA; i++)
    {
        Result.E[i] = E[i] * ScalarT;
    }
    return Result;
}

template <class T>
class Vector
{
    public:
        Vector(std::initializer_list<T> List);
        Vector() : Vector({0,0,0}) {};
        const T & operator()(size_t i) const;
              T & operator()(size_t i);

    private:
        static constexpr size_t SIZE = 3;
        std::array<T, SIZE> E;
};

template <class T>
Vector<T>::Vector(std::initializer_list<T> List)
{
    if (List.size() != SIZE) throw("Error!");
    for (size_t i=0; i<SIZE; i++)
    {
        E[i] = *(List.begin() + i);
    }
}

template <class T>
const T & Vector<T>::operator()(size_t i) const
{
    return E[i];
}

template <class T>
T & Vector<T>::operator()(size_t i)
{
    return E[i];
}

template <class T>  // THE COMPILER NEVER TRIES USING THIS GLOBAL OPERATOR.
Vector<T> operator*(const Matrix<T> & Mat, const Vector<T> & Vec)
{
    Vector<T> Result;
    Result(0) = Mat(0,0) * Vec(0) + Mat(0,1) * Vec(1) + Mat(0,2) * Vec(2);
    Result(1) = Mat(1,0) * Vec(0) + Mat(1,1) * Vec(1) + Mat(1,2) * Vec(2);
    Result(2) = Mat(2,0) * Vec(0) + Mat(2,1) * Vec(1) + Mat(2,2) * Vec(2);
    return Result;
}

int wmain(int argc, wchar_t *argv[]/*, wchar_t *envp[]*/)
{
    Matrix<float> Mat1({2,  0,  0,
                        0,  2,  0,
                        0,  0,  2});

    Vector<float> Vec1({1,
                        2,
                        3});

    Matrix<float> Mat2 = Mat1 * 2;      // Matrix-Scalar Multiplication
    Vector<float> Vec2 = Mat1 * Vec1;   // Matrix-Vector Multiplication

    return 0;
}

问题是,当我尝试做矩阵-向量乘法时,编译器选择并尝试使用矩阵-标量乘法运算符,并给出一个编译器错误。

如果我删除了矩阵-标量乘法运算符和我使用它的行,程序就会成功运行。相反,如果我删除矩阵-向量乘法运算符,它将再次成功运行。他们就是相处不好。当它运行时(在任何一种情况下),它都会正确地进行所有计算。

这里出了什么问题?

编译器和IDE: Microsoft Visual Studio 2015社区版

EN

回答 1

Stack Overflow用户

发布于 2016-03-15 23:59:19

在搜索重载以检查所有可能的作用域时,该语言并没有指定这一点。一旦找到一个候选者,就只使用该作用域中的重载来选择最佳候选者。如果候选者由于其他原因而无法编译,它仍然不会检查其他作用域。

所以在你的例子中,由于标量是一个模板参数,它将匹配任何类型,所以只要运算符的左操作数是Matrix<T>,标量乘法就会匹配任何右操作数。

您可以:

  • 只是使这两个operator*处于相同的作用域,因此它们都被认为是重载的,例如,标量operator采用的Scalar<T>是围绕标量类型而不是泛型模板类型的薄包装器。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35863600

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档