Generic vector of vectors in C++

C++Stl

C++ Problem Overview


Is there a good way in C++ to implement (or fake) a type for a generic vector of vectors?

Ignore the issue of when a vector of vectors is a good idea (unless there's something equivalent which is always better). Assume that it does accurately model the problem, and that a matrix does not accurately model the problem. Assume also that templated functions taking these things as parameters do need to manipulate the structure (e.g. calling push_back), so they can't just take a generic type supporting [][].

What I want to do is:

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

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

but of course that's not possible, since typedef can't be templated.

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

is close, and would save duplicating the type across every templated function which operates on vecvecs, but would not be popular with most C++ programmers.

C++ Solutions


Solution 1 - C++

You want to have template-typedefs. That is not yet supported in the current C++. A workaround is to do

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

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

In the next C++ (called c++0x, c++1x due to 2010), this would be possible:

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

Solution 2 - C++

I use Boost.MultiArray which is implemented in the boost library.

HTH

Solution 3 - C++

You can simply create a new template :

#include <string>
#include <vector>

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

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

If you do that you have to remember that destructor of vector is not virtual and not to do something like this :

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

Solution 4 - C++

You can implement basic vector-of-vector type using std::vector as a basis:

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

It's just a very simple container that mimics a matrix (as long as user promises, by improving vecvec definition or by proper use, rectangular shape).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSteve JessopView Question on Stackoverflow
Solution 1 - C++Johannes Schaub - litbView Answer on Stackoverflow
Solution 2 - C++Łukasz MilewskiView Answer on Stackoverflow
Solution 3 - C++RexxarView Answer on Stackoverflow
Solution 4 - C++mloskotView Answer on Stackoverflow