实现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]);
}