C++ 当矩阵对象的维数为1x1时,如何将其隐式转换为标量?

C++ 当矩阵对象的维数为1x1时,如何将其隐式转换为标量?,c++,matrix,operator-overloading,member-functions,C++,Matrix,Operator Overloading,Member Functions,我写了一个Matrix类。它在矩阵之间进行乘法。有时矩阵相乘产生1x1矩阵(例如,两列向量的内积)。当一个矩阵对象一个接一个地返回标量值时,是否可以让它直接返回标量值 template <class T> class Matrix { public: // ... T& operator()(uint64_t unRow, uint64_t unCol = 0) throw(MatrixOutOfRange);

我写了一个
Matrix
类。它在矩阵之间进行乘法。有时矩阵相乘产生1x1矩阵(例如,两列向量的内积)。当一个
矩阵
对象一个接一个地返回标量值时,是否可以让它直接返回标量值

template <class T> class Matrix
{
    public:
        // ...
        T&       operator()(uint64_t unRow, uint64_t unCol = 0) throw(MatrixOutOfRange);
        const T& operator()(uint64_t unRow, uint64_t unCol = 0) const throw(MatrixOutOfRange);
        // ...
    protected:
        std::vector<T> MatrixArray;
        // ...
};

// ...

template <class T>
T & Matrix<T>::operator()(uint64_t unRow, uint64_t unCol /*= 0*/) throw(MatrixOutOfRange)
{
    /* Bound checking here */
    return MatrixArray[m_unColSize * unRow + unCol];
}

template <class T>
const T & Matrix<T>::operator()(uint64_t unRow, uint64_t unCol /*= 0*/) const throw(MatrixOutOfRange)
{
    /* Bound checking here */
    return MatrixArray[m_unColSize * unRow + unCol];
}

// ...
如果结果不是一个接一个地出现,则抛出异常是可以的。

这将类似于,这也是一个编译时调用,除非满足某些运行时条件,否则将始终抛出该调用

类型
T
的转换运算符如下所示:

template <class T> class Matrix
{
    public:
        // ...
        operator T &() { 
           // Throw here if size is not 1x1...

           return (*this)( 0, 0 ); 
        }

        operator T const &() const { 
           // Throw here if size is not 1x1...

           return (*this)( 0, 0 ); 
        }
        // ...
};
模板类矩阵
{
公众:
        // ...
运算符T&({
//如果大小不是1x1,则抛出此处。。。
返回(*本)(0,0);
}
运算符T常量&()常量{
//如果大小不是1x1,则抛出此处。。。
返回(*本)(0,0);
}
        // ...
};

您所有的示例代码都可以正常工作。

除非大小成为类型的一部分。否则,您必须始终进行标量转换,或者从不进行标量转换。您不能基于运行时事实更改类型的编译时功能(无论它是否具有隐式转换)——无论大小在两个维度中是否为1。这需要编译器预先识别。

我认为更好的方法是将您的大小作为类型的一部分:

template <class T, size_t NRows, size_t NCols>
class Matrix
{
public:
    // ...
protected:
    // ...
    T M_storage[NRows][NCols]; // Or something...
};
模板
类矩阵
{
公众:
// ...
受保护的:
// ...
T M_storage[NRows][NCols];//或其他什么。。。
};
然后使用模板专门化将转换运算符添加到1x1矩阵:

template <class T>
class Matrix<T, 1, 1>
{
public:
    // ...
    operator T ()
    {
       return M_storage;//[0][0]; 
    }
protected:
    // ...
    //T M_storage[1][1]; // Or something...
    // Or even
    T M_storage;
};
模板
类矩阵
{
公众:
// ...
算子T()
{
返回M_存储;//[0][0];
}
受保护的:
// ...
//T M_storage[1][1];//或其他什么。。。
//甚至
T M_储存;
};

这是可能的,但绝对不是一个好主意。
C
是一个函数(您从未定义过),它不带参数并返回一个
矩阵。对于默认构造的对象,请去掉括号。@BenjaminLindley指的是行
矩阵C()。这是一个欺骗性的分析。但是矩阵的大小不是类型的一部分,所以这种转换适用于所有大小的矩阵。@juanchopanza这是正确的,有点令人讨厌,但这显然是问题的一部分。“如果结果不是一个接一个地出现,则抛出异常就可以了。”
运算符T&()
运算符T const&()const
最好与
运算符()
索引的语义匹配。@Potatoswatter是的,我应该这样做!现在,类似于
myMatrix1x1=0.0
的语法也有效。谢谢。使用CRTP添加功能更安全,而无需重写整个
矩阵
类。更好的办法是同时使用这两种类型(固定矩阵和弹性矩阵)。隐式转换仅适用于
已修复的
。Flex有一个转换为标量的成员函数。Fixed是根据Flex实现的,但也可以在编译时保证大小。哦,当你这样做的时候,
[]
就是把元素取出(或者
[a,b,…]
或者
[a][b][…]
),
()
就是作为一个参数的线性函数进行计算。
template <class T, size_t NRows, size_t NCols>
class Matrix
{
public:
    // ...
protected:
    // ...
    T M_storage[NRows][NCols]; // Or something...
};
template <class T>
class Matrix<T, 1, 1>
{
public:
    // ...
    operator T ()
    {
       return M_storage;//[0][0]; 
    }
protected:
    // ...
    //T M_storage[1][1]; // Or something...
    // Or even
    T M_storage;
};