50 Stimmen

Generischer Vektor von Vektoren in C++

Gibt es eine gute Möglichkeit in C++ zu implementieren (oder fake) einen Typ für einen generischen Vektor von Vektoren?

Ignorieren Sie die Frage, wann ein Vektor von Vektoren eine gute Idee ist (es sei denn, es gibt etwas Gleichwertiges, das immer besser ist). Gehen Sie davon aus, dass er das Problem genau modelliert, und dass eine Matrix das Problem nicht genau modelliert. Gehen Sie auch davon aus, dass Funktionen, die diese Dinge als Parameter nehmen, die Struktur manipulieren müssen (z.B. durch den Aufruf von push_back), so dass sie nicht einfach einen generischen Typ als Unterstützung nehmen können. [][] .

Was ich tun möchte, ist:

template<typename T>
typedef vector< vector<T> > vecvec;

vecvec<int> intSequences;
vecvec<string> stringSequences;

aber das ist natürlich nicht möglich, da typedef nicht als Vorlage verwendet werden kann.

#define vecvec(T) vector< vector<T> >

ist nahe dran und würde die Duplizierung des Typs in jeder Schablonenfunktion, die mit Vecvecs arbeitet, ersparen, wäre aber bei den meisten C++-Programmierern nicht beliebt.

51voto

Johannes Schaub - litb Punkte 479831

Sie möchten Vorlagen-Typendefinitionen haben. Das heißt no in der aktuellen C++-Version noch nicht unterstützt. Eine Umgehung ist die Ausführung von

template<typename T>
struct vecvec {
     typedef std::vector< std::vector<T> > type;
};

int main() {
    vecvec<int>::type intSequences;
    vecvec<std::string>::type stringSequences;
}

Im nächsten C++ (genannt c++0x, c++1x ab 2010) wäre dies möglich:

template<typename T>
using vecvec = std::vector< std::vector<T> >;

14 Stimmen

Ich glaube, sie haben auch die Notwendigkeit von Leerzeichen in >> behoben.

5voto

Łukasz Milewski Punkte 1859

Ich benutze Boost.MultiArray die in der boost-Bibliothek implementiert ist.

HTH

4voto

Rexxar Punkte 1838

Sie können einfach eine neue Vorlage erstellen:

#include <string>
#include <vector>

template<typename T>
struct vecvec : public std::vector< std::vector<T> > {};

int main() 
{
    vecvec<int> intSequences;
    vecvec<std::string> stringSequences;
}

Wenn Sie das tun, müssen Sie daran denken, dass der Destruktor des Vektors nicht virtuell ist und nicht so etwas wie das zu tun:

void test()
{
    std::vector< std::vector<int> >* pvv = new vecvec<int>;
    delete pvv;
}

4 Stimmen

Sie werden alle praktischen Konstruktoren von vector<T> verlieren. Man muss sie definieren und nur die Argumente an die Eltern übergeben. Eine Möglichkeit, aber keine schlanke Lösung.

0 Stimmen

-1 Die Antwort selbst ist gut formuliert, und Sie weisen auf einen der Hauptmängel der vorgestellten Lösung hin. Dieser und andere Fehler sind jedoch Grund genug für eine Abwertung, denke ich.

2voto

mloskot Punkte 34861

Sie können den einfachen Vektor-von-Vektor-Typ mit std::vector als Grundlage:

#include <iostream>
#include <ostream>
#include <vector>
using namespace std;

template <typename T>
struct vecvec
{
    typedef vector<T> value_type;
    typedef vector<value_type> type;
    typedef typename type::size_type size_type;
    typedef typename type::reference reference;
    typedef typename type::const_reference const_reference;

    vecvec(size_type first, size_type second)
        : v_(first, value_type(second, T()))
    {}

    reference operator[](size_type n)
    { return v_[n]; }

    const_reference operator[](size_type n) const
    { return v_[n]; }

    size_type first_size() const
    { return v_.size(); }

    size_type second_size() const
    { return v_.empty() ? 0 : v_[0].size(); }

    // TODO: replicate std::vector interface if needed, like
    //iterator begin();
    //iterator end();

private:
    type v_;

};

// for convenient printing only
template <typename T> 
ostream& operator<<(ostream& os, vecvec<T> const& v)
{
    typedef vecvec<T> v_t;
    typedef typename v_t::value_type vv_t;
    for (typename v_t::size_type i = 0; i < v.first_size(); ++i)
    {
        for (typename vv_t::size_type j = 0; j < v.second_size(); ++j)
        {
            os << v[i][j] << '\t';
        }
        os << endl;
    }
    return os;
}

int main()
{
    vecvec<int> v(2, 3);
    cout << v.first_size() << " x " << v.second_size() << endl;
    cout << v << endl;

    v[0][0] = 1; v[0][1] = 3; v[0][2] = 5;
    v[1][0] = 2; v[1][1] = 4; v[1][2] = 6;
    cout << v << endl;
}

Es ist nur ein sehr einfacher Container, der eine Matrix imitiert (solange der Benutzer verspricht, durch die Verbesserung der Vecvec-Definition oder durch die richtige Verwendung, rechteckige Form).

0 Stimmen

Leider lässt sich das Problem nicht in einer Matrix darstellen. Die Daten sind nicht "rechteckig", die verschiedenen Zeilen sind unterschiedlich lang.

0 Stimmen

@Steve Jessop - im Allgemeinen, während der Arbeit mit Vektor von Vektoren, ja gibt es eine solche Möglichkeit wegen der Exposition von push_back usw., aber es soll eine Veranschaulichung sein, eine primitive Lösung und ich überließ Verbesserungen zum Leser, d.h. zu garantieren, gemeinsame Größe für Zeilen beibehalten wird, nicht auf Operationen, die Dimension der Zeile Vektor ändern könnte, etc.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X