Konstante Proxy Klasse?


  • Mod

    kkaw schrieb:

    Ich verweise nochmal auf die Slice-Klasse von oben.

    Nimm doch einfach Template-Parameter für die Schrittlänge.



  • Arcoth schrieb:

    kkaw schrieb:

    Ich verweise nochmal auf die Slice-Klasse von oben.

    Nimm doch einfach Template-Parameter für die Schrittlänge.

    Für Matritzen dynamischer Grösse ... lol


  • Mod

    Für Matritzen dynamischer Grösse ... lol

    Ganz vergessen.



  • kkaw schrieb:

    ?!

    Verstehe nicht, warum ihr das so umständlich macht. Ich verweise nochmal auf die Slice-Klasse von oben.

    Hm, hab mir das mit der Slice-Klasse (warum eigentlich "Slice", hat das was mit Object Slicing zu tun?) nochmal angeschaut und kriegs nicht hin, da ich auch da immer den gleichen Fehler wie im Eingangspost bekomme... Also wenn das hier meine slice Klasse ist:

    template <typename T>
    class matrix_slice
    {
    	public:
    		explicit matrix_slice(std::vector<T> &data_, size_t row_, size_t size_) : data(data_), row(row_), size(size_) {}
    
    		T& operator[](size_t col_) { return data[row + col_*size]; }
    
    	private:
    		std::vector<T> &data;
    		size_t row, size;
    };
    

    dann meckert der Compiler halt wieder dass "durch keine der 2 Überladungen alle Parameter konvertiert werden konnten", also das gleiche Problem wie wenn ich direkt die Matrix übergeben würde...



  • Slice steht für "Scheibe" à la "eine Scheibe abschneiden". So, wie ich mir das gedacht hatte, ist es allgemeiner als "Row". Du kannst es eben auch Spalten und Diagonalen verwenden. Wenn Du es nur für Zeilen brauchst, wobei step_ dann immer 1 wäre (by row-major storage), könntest du das natürlich auch zwecks Größenoptimierung weglassen und wieder zu matrix_row oder so umbenennen.

    So, wie du das jetzt aufgeschrieben hattest (mit Referenz auf non-const matrix statt eines Iterators) ist Deine Klasse natürlich nicht für den const-only-Zugriff nutzbar. Keine Ahnung, warum Du unbedingt wieder eine Matrix-Referenz benutzen musstest. Das war ja sicher ein Teil Deines Problems.

    Relativ allgemein aufgeschrieben und diesmal mit 'nem Iterator statt eines rohen Zeigers sieht das so aus.

    template<class RandomAccessIter>
    class slice
    {
    public:
        typedef typename std::iterator_traits<RandomAccessIter>::reference reference;
        slice(RandomAccessIter base, std::size_t size, std::size_t step = 1)
        : base_(base), size_(size), step_(step)
        {}
    
        std::size_t size() const { return size_; }
    
        reference operator[](std::size_t index) const {
            assert(index<size_);
            return base_[index*step_];
        }
    
    private:
        RandomAccessIter base_;
        std::size_t size_;
        std::size_t step_;
    };
    

    (ungetestet, aber eventuelle Fehler solltest Du behoben kriegen)

    Und Deine Matrix-Klasse könntest Du jetzt so bauen:

    template<class T>
    class matrix
    {
    public:
        typedef slice<typename std::vector<T>::iterator> slice_type;
        typedef slice<typename std::vector<T>::const_iterator> const_slice_type;
    
        explicit matrix(std::size_t rows, std::size_t cols)
        : rows_(rows), cols_(cols), elememts_(rows*cols)
        {}
        ...
        const_slice_type row(std::size_t index) const {
            assert(index<rows_);
            return const_slice_type(elements_.begin()+index*cols_,cols_,1);
        }
        slice_type row(std::size_t index) {
            assert(index<rows_);
            return slice_type(elements_.begin()+index*cols_,cols_,1);
        }
        const_slice_type col(std::size_t index) const {
            assert(index<cols_);
            return const_slice_type(elements_.begin()+index,rows_,cols_);
        }
        slice_type col(std::size_t index) {
            assert(index<cols_);
            return slice_type(elements_.begin()+index,rows_,cols_);
        }
        ...
    private:
        ...
        std::size_t rows_, cols_;
        std::vector<T> elements_;
        ...
    };
    

    (auch ungetestet, Fehler kannst du behalten)



  • Alternativ verwendest Du Boost.MultiArray. Das ist noch einen Tucken generischer in der Hinsicht, dass die Dimension des Arrays noch ein Templateparameter ist. Damit kannst Du auch 5D-Arrays bauen oder so ...


Anmelden zum Antworten