Есть ли в C++ хороший способ реализовать (или подделать) тип для общего вектора векторов?
Игнорируйте вопрос о том, когда вектор векторов является хорошей идеей (если нет чего-то эквивалентного, что всегда лучше). Предположим, что он точно моделирует проблему, а матрица неточно моделирует проблему. Предположим также, что шаблонные функции, принимающие эти вещи в качестве параметров, действительно должны манипулировать структурой (например, вызывать push_back), поэтому они не могут просто использовать общий тип, поддерживающий [][].
Что я хочу сделать:
template<typename T>
typedef vector< vector<T> > vecvec;
vecvec<int> intSequences;
vecvec<string> stringSequences;
но, конечно, это невозможно, поскольку typedef нельзя использовать по шаблону.
#define vecvec(T) vector< vector<T> >
близок и сэкономит дублирование типа во всех шаблонных функциях, которые работают с vecvecs, но не будут популярны у большинства программистов на C++.





Вы хотите иметь template-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> >;
Вы можете просто создать новый шаблон:
#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;
}
Вы потеряете все удобные конструкторы vector <T>. Вам нужно определить их, просто передав аргументы родителю. Возможность, но не простое решение.
-1 Сам ответ составлен хорошо, и вы указываете на один из основных недостатков представленного решения. Однако, мне кажется, этого и других недостатков достаточно, чтобы проголосовать против.
Я использую Boost.MultiArray, который реализован в библиотеке boost.
HTH
Вы можете реализовать базовый тип вектора-вектора, взяв за основу 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 или правильного использования прямоугольной формы).
К сожалению, матрица не моделирует проблему. Данные не «прямоугольные», разные строки имеют разную длину.
@Steve Jessop - как правило, при работе с вектором векторов да, такая возможность возникает из-за воздействия push_back и т. д., Но это должна быть иллюстрация, примитивное решение, и я оставил улучшения читателю, т.е. чтобы гарантировать общий размер для строк сохраняется, чтобы не подвергать операции, которые могут изменить размерность вектора-строки и т. д.
Думаю, они также устранили необходимость в пробелах в >>