Index-Operator doppelt überladen?



  • Wenn man das nicht will, macht man den Proxy halt privat.

    template<class MatrixRow>
    void foo(MatrixRow& row);
    


  • otze schrieb:

    Wenn man das nicht will, macht man den Proxy halt privat.

    template<class MatrixRow>
    void foo(MatrixRow& row);
    

    Ok, gutes Argument.
    Wieso sollte man das denn nicht wollen?
    Man spendiert dem Proxy noch size und iterators und schon hat man ein vollständige row.



  • Nathan schrieb:

    Ok, gutes Argument.
    Wieso sollte man das denn nicht wollen?
    Man spendiert dem Proxy noch size und iterators und schon hat man ein vollständige row.

    könnte auch ne column sein.

    //edit vgl:

    foo(m.transpose()[i]);
    


  • otze schrieb:

    volkard schrieb:

    Verstehe ich nicht. Der kostenlose Proxy leitet, wenn er was taugt, die Anfrage einfach nur weiter. Ob nun bei mat[a][5] oder bei mat(a,5) das a die Spalte oder Zeile bedeutet, ist ihm vollkommen egal.

    Du hast leider nicht verstanden worauf ich hinaus will. Um den kompletten Ausdruck m[i][j] geht es nicht, sondern um m[i]

    foo(m[i]);
    

    Uups! Da erwarte ich aber eher, daß es getRow(size_t) und getColumn(size_t) oder sowas geben muss.
    foo(m[i]); halte ich für einen dunklen Hack, gemein und hinterhältig. Aber ich sehe ein, daß man Arcoth und Nathan wohl nicht davon abhalten kann, sowas zu machen, wenn man op[][] anbietet.



  • Muss man auch niemanden abhalten.
    Nur ehrliche Unfälle vermeiden.
    Wenn das Ding AccessProxy heisst sollte das aber schon reichen.
    Wer meint dann foo()s implementieren zu müssen die so einen AccessProxy als Parameter nehmen ist selbst schuld.



  • volkard schrieb:

    Aber ich sehe ein, daß man Arcoth und Nathan wohl nicht davon abhalten kann, sowas zu machen, wenn man op[][] anbietet.

    Wenns nur die Beiden wären. Ich habe erst Donnerstag diese Diskussion mit einem Kollegen geführt, der dann auch meinte, dass es doch toll wäre, wenn op[] eine Zeile zurückgeben würde. Und solche Unfälle lassen sich ja schwerlich vermeiden. Da muss ja nur jemand glauben, dass das Ding sicherlich irgendeine row zurückgeben wird und dann sein

    template<class ArbitraryVector>
    void foo(ArbitraryVector& vector);
    

    drauf werfen. Man kann auch irgendwie argumentieren, dass row-major matrizen eine Zeile zurückgeben und column-major eine Spalte, aber dann kriegt man probleme damit, dass

    foo(m[i]);
    foo(transpose(m)[i]);
    

    die selbe Zeile von m verändern aber

    Matrix m = transpose(m);
    foo(m[i]);
    

    dann etwas anderes macht. Und wenn man immer eine Zeile zurückgibt dann hat man das Problem, dass etwas was einfach aussieht eventuell richtig teuer ist.



  • volkard schrieb:

    foo(m[i]); halte ich für einen dunklen Hack, gemein und hinterhältig. Aber ich sehe ein, daß man Arcoth und Nathan wohl nicht davon abhalten kann, sowas zu machen, wenn man op[][] anbietet.

    Äh, moment: Ich würde das nicht machen, ich sehe nur keinen direkten Grund das zu verbieten.
    Bei mir wär der Proxy private und wer drauf zugreift ist selbst schuld.



  • Nathan schrieb:

    Bei mir wär der Proxy private und wer drauf zugreift ist selbst schuld.

    Du meinst, dass es nur zufall ist, dass du ihn aus einer Funktion zurückgibst? 😉



  • otze schrieb:

    Nathan schrieb:

    Bei mir wär der Proxy private und wer drauf zugreift ist selbst schuld.

    Du meinst, dass es nur zufall ist, dass du ihn aus einer Funktion zurückgibst? 😉

    Zugreift im Sinne: Etwas anderes als operator[] aufzurufen. 😉



  • Nathan schrieb:

    otze schrieb:

    Nathan schrieb:

    Bei mir wär der Proxy private und wer drauf zugreift ist selbst schuld.

    Du meinst, dass es nur zufall ist, dass du ihn aus einer Funktion zurückgibst? 😉

    Zugreift im Sinne: Etwas anderes als operator[] aufzurufen. 😉

    Meine Beispiele machen ja auch nicht mehr.



  • otze schrieb:

    Nathan schrieb:

    otze schrieb:

    Nathan schrieb:

    Bei mir wär der Proxy private und wer drauf zugreift ist selbst schuld.

    Du meinst, dass es nur zufall ist, dass du ihn aus einer Funktion zurückgibst? 😉

    Zugreift im Sinne: Etwas anderes als operator[] aufzurufen. 😉

    Meine Beispiele machen ja auch nicht mehr.

    Nee, ich mein den operator vom Proxy. Mehr sollte man damit nicht machen, weils ein Implementierungsdetail ist.



  • Ich persönlich stehe ja mehr auf eine Wiederverwendbare Implementierung, einfach A[i][j] auf A(i,j) delegieren.

    template <typename Matrix>
    class bracket_proxy
    {
    public:
    
        typedef typename Matrix::value_type value_type;
        typedef const value_type& const_reference_type;
    
        typedef typename std::conditional<
            std::is_const<Matrix>::value,
            const_reference_type,
            value_type&
        >::type reference_type;
    
        bracket_proxy(Matrix& A, int i) : A(A), i(i) {}
    
        reference_type operator[](int j)
        {
            return A(i,j);
        }
    
    private:
        Matrix& A;
        int i;
    };
    
    class Matrix {
        /// ....
        bracket_proxy<Matrix> operator[](int i)
        {
            return bracket_proxy<Matrix>(*this, i);
        }
    
        bracket_proxy<const Matrix> operator[](int i) const
        {
            return bracket_proxy<const Matrix>(*this, i);
        }
    
        /// ....
    };
    

Anmelden zum Antworten