49 votes

Vecteur générique de vecteurs en C++

Existe-t-il un bon moyen en C++ d'implémenter (ou de simuler) un type pour un vecteur générique de vecteurs ?

Ignorez la question de savoir quand un vecteur de vecteurs est une bonne idée (à moins qu'il n'existe quelque chose d'équivalent qui est toujours meilleur). Supposons qu'il modélise correctement le problème, et qu'une matrice ne le modélise pas correctement. Supposons également que les fonctions modélisées prenant ces éléments comme paramètres doivent manipuler la structure (par exemple, en appelant push_back), et qu'elles ne peuvent donc pas se contenter de prendre un type générique qui les supporte. [][] .

Ce que je veux faire, c'est :

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

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

mais bien sûr, ce n'est pas possible, puisque le typedef ne peut pas être modélisé.

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

est proche, et éviterait de dupliquer le type dans toutes les fonctions modélisées qui opèrent sur des vecvecs, mais ne serait pas populaire auprès de la plupart des programmeurs C++.

51voto

Johannes Schaub - litb Points 256113

Vous voulez avoir des modèles-typedefs. C'est-à-dire no encore pris en charge dans la version actuelle de C++. Une solution de contournement consiste à faire

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

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

Dans le prochain C++ (appelé c++0x, c++1x prévu pour 2010), cela serait possible :

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

5voto

Łukasz Milewski Points 1401

J'utilise Boost.MultiArray qui est implémenté dans la bibliothèque boost.

HTH

4voto

Rexxar Points 1076

Vous pouvez simplement créer un nouveau modèle :

#include <string>
#include <vector>

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

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

Si vous faites cela, vous devez vous rappeler que le destructeur du vecteur n'est pas virtuel et ne pas faire quelque chose comme ceci :

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

2voto

mloskot Points 13971

Vous pouvez implémenter le type de base vecteur-de-vecteur en utilisant std::vector comme base :

#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;
}

C'est juste un conteneur très simple qui imite une matrice (tant que l'utilisateur promet, en améliorant la définition de vecvec ou par une utilisation appropriée, une forme rectangulaire).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X