实现A(:,k)=b;C++;矩阵库:避免常数 我开发了一个基于我自己的C++矩阵类的表达式模板。我还实现了一个Range类来支持类似Matlab的读取 cout << A(Range(3,5),Range(0,10)) << endl;

实现A(:,k)=b;C++;矩阵库:避免常数 我开发了一个基于我自己的C++矩阵类的表达式模板。我还实现了一个Range类来支持类似Matlab的读取 cout << A(Range(3,5),Range(0,10)) << endl;,c++,class,expression,template-meta-programming,C++,Class,Expression,Template Meta Programming,其中B是一个合适的矩阵 矩阵()运算符重载如下 inline Expr<SubMatrixExpr<const OutType*,OutType>,OutType> operator()(Range range1, Range range2) { typedef SubMatrixExpr<const OutType*,OutType> SExpr; return Expr<SExpr,OutType>(SExpr(...some s

其中
B
是一个合适的矩阵

矩阵
()
运算符重载如下

inline Expr<SubMatrixExpr<const OutType*,OutType>,OutType> operator()(Range range1, Range range2)
{   typedef SubMatrixExpr<const OutType*,OutType> SExpr; 
    return Expr<SExpr,OutType>(SExpr(...some stuff...),...some stuff...); 
}
Expr
类的示例如下:

template <class A, class B>
class Expr
{
    // Constructor (a is the expression, the SubMatrixExpr in my case)
    Expr(const A &a, ...stuff...) : ...stuff...

    // Access
    inline B operator[](const int i) const { return a_[i]; }

    Expr<A,B> operator=(const Matrix<B> &ob)
    {
        for (int i=0; i<GetNumElements(); i++) { std::cout << a_[i] << " " << ob.GetDataPointer()[i] << "\n"; a_[i] = ob.GetDataPointer()[i]; }
        return *this;
    }
}
此外,我还删除了
子矩阵xpr的原始访问操作符,并添加了

inline const B& operator[](const int i) const { return a_[i]; }
inline  B& operator[](const int i)  
{ 
    const Expr& constThis = *this;
    return const_cast<B&>(constThis[i]); 
}
inline const Type& operator[](const int i) const
{
    // Stuff
    return M_[IDX2R(GlobalRow,GlobalColumn,Columns_up_)];
}

不幸的是,编译器返回以下错误

qualifiers dropped in binding reference of type "LibraryNameSpace::double2_ &" to initializer of type "const LibraryNameSpace::double2_"    
double2
是我自己的一种复杂类型)

编辑#2-关于M#的信息

template <class A, class Type>
class  SubMatrixExpr
{
    private:
   A M_;

    // STUFF
}
模板
类子矩阵Xpr
{
私人:
一位女士;
//东西
}

从上面报告的
Matrix()
运算符重载中,
A=const-OutType*
,其中
OutType
是矩阵类型,
double2
是我当前运行的示例。

这实际上不是contenss问题。您可以通过
运算符[]
中的值返回。因此,返回的值被复制,您将新的值分配给该副本,该副本将被销毁

实际上,您的代码是这样工作的

struct S
{
    int v;
} x = {0};
S foo() { return x;}
int main() 
{
    foo() = {1}; 
    std::cout << foo().v;
}
  • 第二个重载使用可变容器并通过引用返回,因此可以修改容器项:

    Type& operator[](const int i) { ...stuff... }
    B& operator[](const int i) { return a_[i]; }
    
  • 原则上,可变版本可以通过常量版本实现:

    B& Class::operator[](const int i) 
    {
    const Class& constThis = *this;
    return const_cast<B&>(constThis[i]);
    }
    
    B&Class::operator[](常量int i)
    {
    const Class&constThis=*this;
    返回const_cast(constThis[i]);
    }
    
    您是否实际使用const_cast来实现可变版本?我从来没有这样做过,所以每次我都编写两个版本的函数(一个常量,一个可变)。。每次我都觉得很烦人。但我从未使用过const_cast,只是感觉不对@Corey,如果getter很短,我写两个函数。而且getter通常都很短。但是,如果getter很重要,我将使用
    const\u cast
    @Lol4t0非常感谢您的回答。我已经根据你的建议修复了我的代码,正如编辑后的文章所报道的那样。不幸的是,编译器返回了一个错误(参见编辑的文章)。你有迹象表明原因吗?再次感谢。这里是什么?它是如何定义的?在编辑的帖子中添加了关于
    M
    的信息。非常感谢。好的,但是如果
    A
    const OutType*
    ,那么
    \u M
    元素根本无法修改,因为它们是常量类型。@Lol4t0是的,我现在删除了
    const
    关键字,现在一切似乎都正常了。但是,我是否仍然可以使用
    const
    关键字,并在重载的
    []
    运算符中绕过
    const
    -ness,这样我就不会更改现有代码?再次感谢您,我已经接受了您的回答:-)您无论如何都应该通过引用返回,您可以使用
    const cast
    ,但要非常小心。因为修改真正的常量值是未定义的行为!我认为你没有太多的代码,我认为你最好现在就修复它,否则你可能不得不稍后修复它,它会比现在更复杂。
    struct S
    {
        int v;
    } x = {0};
    S foo() { return x;}
    int main() 
    {
        foo() = {1}; 
        std::cout << foo().v;
    }
    
    const Type& operator[](const int i) const { ...stuff... }
    const B& operator[](const int i) const { return a_[i]; }
    
    Type& operator[](const int i) { ...stuff... }
    B& operator[](const int i) { return a_[i]; }
    
    B& Class::operator[](const int i) 
    {
    const Class& constThis = *this;
    return const_cast<B&>(constThis[i]);
    }