2008-11-16 3 views
48

Есть ли хороший способ в C++ реализовать (или подделку) тип для векторного вектора векторов?Общий вектор векторов в C++

Игнорировать проблему, когда вектором векторов является хорошей идеей (если только нет эквивалента, который всегда лучше). Предположим, что он точно моделирует проблему и что матрица не точно моделирует проблему. Предположим также, что шаблонные функции, берущие эти параметры как параметры, должны манипулировать структурой (например, вызовом push_back), поэтому они не могут просто взять общий тип, поддерживающий [][].

То, что я хочу сделать, это:

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

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

, но, конечно, это не представляется возможным, так как ЬурейиЕ не может быть шаблонными.

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

близко, и позволит сэкономить дублируя тип через каждую шаблонную функцию, которая работает на vecvecs, но не будет популярны у большинства программистов C++.

ответ

51

Вы хотите иметь шаблон-typedefs. То есть не, но поддерживается в текущем C++. Обойти это сделать

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

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

В следующем C++ (так называемый C++ 0x C++ 1x из-за 2010 г.), это было бы возможно:

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

Я думаю, что они также исправили необходимость пробелов в >> – 2008-11-17 22:56:35

+0

действительно, у них есть :) – 2008-11-18 00:54:16

4

Вы можете просто создать новый шаблон:

#include <string> 
#include <vector> 

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

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

Если вы делаете, что вы должны помнить, что деструктор вектора не является виртуальным, а не делать что-то вроде этого:

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

Вы столкнетесь с потерей всех удобных конструкторов вектора . Вы должны определить их, просто передав аргументы родителям. Возможность, но не скудное решение. – xtofl 2008-11-19 19:58:41

+0

-1 Сам ответ хорошо составлен, и вы указываете на один из основных недостатков представленного решения. Однако этого недостатка и других достаточно для нисходящего потока, говорит. – 2011-06-13 10:10:29

2

Вы можете реализовать основной вектор-из-вектора типа с использованием std::vector в качестве основы:

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

Это просто очень простой контейнер, который имитирует матрицу (до тех пор, как пользователь обещаниям, по улучшая определение vecvec или правильное использование, прямоугольную форму).

Смежные вопросы