1

私は独自の式テンプレート ベースの C++ マトリックス クラスを開発しました。RangeMatlab のような読み取りを有効にするクラスも実装しました。

cout << A(Range(3,5),Range(0,10)) << endl;

Matlab のような割り当てを次のように有効にしたいと思います。

A(Range(3,5),Range(0,10))=B;

ここBで、 は適切な行列です。

Matrix ()演算子のオーバーロードは次のとおりです。

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...); 
}

クラスは次のSubMatrixExprように例示されます

template <class A, class Type>
class  SubMatrixExpr
{
    // Constructor (M is a pointer to the Matrix data)
    SubMatrixExpr(const A &M, ...stuff...) : ...stuff...    

    // Access operator
    inline Type operator[](const int i) const { ...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;
    }
}

私の問題は次のとおりです。const上記の 2 つの式クラスのアクセス演算子で使用します。その結果=、クラスのオーバーロードされた演算子はExpr正しくa_[i]andを返しますob.GetDataPointer()[i]が、代入は行いません。

コード全体を変更せずconstに、オーバーロードされた演算子内の -nessを無視することは可能ですか?=

ご助力ありがとうございます。

Lol4t0の回答に従って編集

Exprクラスの元のアクセス演算子を削除して追加しました

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

また、元のアクセス演算子を削除してSubMatrixExpr追加しました

inline const Type& operator[](const int i) const
{
    // Stuff
    return M_[IDX2R(GlobalRow,GlobalColumn,Columns_up_)];
}

inline Type& operator[](const int i) 
{
    // Stuff
    // The following line returns an error
    return M_[IDX2R(GlobalRow,GlobalColumn,Columns_up_)];
}

残念ながら、コンパイラは次のエラーを返します

qualifiers dropped in binding reference of type "LibraryNameSpace::double2_ &" to initializer of type "const LibraryNameSpace::double2_"    

(double2_は私自身の複合型です)。

EDIT #2 - M_に関する情報

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

    // STUFF
}

上記で報告されたMatrix ()演算子のオーバーロードからA = const OutType*、は現在実行中の例OutTypeの行列タイプdouble2_です。

4

1 に答える 1

2

それは実際には constenss の問題ではありません。の値で戻りますoperator []。したがって、返された値がコピーされ、そのコピーに新しい値を割り当てると、破棄されます。

実際、あなたのコードはこのように動作します

struct S
{
    int v;
} x = {0};
S foo() { return x;}
int main() 
{
    foo() = {1}; 
    std::cout << foo().v;
}

当然、割り当てた新しい値は保存されません。

通常、コンテナーには次の 2 つのオーバーロードがありoperator[]ます。

  • 最初のオーバーロードは定数コンテナーで動作し、定数参照によって返されます。

    const Type& operator[](const int i) const { ...stuff... }
    const B& operator[](const int i) const { return a_[i]; }
    
  • 2 番目のオーバーロードは変更可能なコンテナーで動作し、参照によって返されるため、コンテナー項目を変更できます。

    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]);
}
于 2013-05-09T21:01:36.393 に答える