C ++ как в Java ?: вектор векторов с * переменной * длиной целого - PullRequest
0 голосов
/ 16 ноября 2009

Моя модель лучше всего будет использовать

v int [30] [i] [N_i];

структура, которая составляет 30 векторов кортежей целых, где

v [0] - пустышка,
v [1] - простые целые числа (из них N_0),
v [2] пары int (N_1 пар)
...
v [29] будет 29-кратным числом int (из них N_29)

Это , а не vector<vector<int>>, как в "универсальном векторе векторов в c"

Очевидно, что внешний фиксированный dim = 30 не проблема, о внутреннем заботится саморасширяющийся векторный класс STL.

Есть ли способ зафиксировать среднее измерение, но не постоянное?

Ответы [ 3 ]

2 голосов
/ 17 ноября 2009

Как я уже писал в комментарии к вашему вопросу, я не уверен, что понимаю, что вы ищете (и меня очень интересует часть "как в Java", кстати).

Но так как я думал, что было бы интересно посмотреть, как его можно сгенерировать с помощью Boost. MPL Fusion ... и Array ), Я предполагаю, что вам нужна статически определенная структура, чей элемент Ntn является вектором массивов int размером N:

#define FUSION_MAX_VECTOR_SIZE 30

#include <boost/mpl/transform.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/inserter.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/size_t.hpp>

#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <boost/fusion/include/as_vector.hpp>

#include <boost/array.hpp>

#include <vector>


namespace bf = boost::fusion;
namespace bmpl = boost::mpl;

// Type generator used for elements 2..N
// For those elements, the type of the n'th element is
// std::vector<boost::array<int, n>>
template<class SizeT>
struct VectorOfArray
{
    typedef std::vector<boost::array<int, SizeT::type::value> > type;
};

// The dummy type used for the first element
struct Dummy{};

// The container itself
template<size_t Size>
struct StrangeContainer
{

    // Define a fusion::vector (this is, more or less, equivalent to a tuple)
    // of "Size" elements, where:
    // - the type of element 0 is Dummy, 
    // - the type of element 1 is vector<int>
    // - the type of the n'th element is vector<array<int, n>>
    typedef typename bf::result_of::as_vector<
        typename bmpl::transform<
            bmpl::range_c<size_t, 2, Size>,
            VectorOfArray<bmpl::_1>,
            bmpl::back_inserter<
                bmpl::vector<Dummy, std::vector<int> >
            >
        >::type
    >::type ContentsType;

    // Helper struct to compute the return type of the "At()" member
    template<size_t I>
    struct ElemType
    {
        typedef typename VectorOfArray<bmpl::size_t<I> >::type type;
    };

    // Specialize "At()"'s return type for element 1
    template<>
    struct ElemType<static_cast<size_t>(1)>
    {
        typedef std::vector<int> type;
    };

    // Specialize "At()"'s return type for element 0
    template<>
    struct ElemType<static_cast<size_t>(0)>
    {
        typedef Dummy type;
    };

    // Get the I'th element
    template<size_t I>
    typename ElemType<I>::type& 
    At()
    {
        return bf::at_c<I>(m_Contents);
    }

    // The fusion vector holding the elements
    ContentsType m_Contents;
};

int main()
{
    StrangeContainer<30> s;
    Dummy& d = s.At<0>();
    s.At<1>().push_back(1);
    s.At<2>().push_back(boost::array<int, 2>());
    s.At<3>().push_back(boost::array<int, 3>());
    s.At<29>().push_back(boost::array<int, 29>());
    s.At<29>()[0][0] = 1234;

    return 0;
}
0 голосов
/ 01 декабря 2009

Я - Майкл (первоначальный автор), теперь у меня есть удостоверение личности La-AIDA

Во-первых, спасибо всем, Boost & Fusion, где я новичок.

Для Эрика: Одна опечатка: v [1] должно иметь N_1 записей, v [2] N_2 и так далее. Я бы хотел STL-подобные вещи, а не C-массивы (отсутствует проверка границ без возможности добавить их).

Новый комментарий к Эрику: Я попробовал ваше решение, оно сработало (почти, после удаления пустого запроса) немедленно! Спасибо! Но: мне нужно что-то вроде

 for (i = 1;i < 30;i++) {
    cout << s.At<i>[0] << endl; 
 }

то есть индекс для At <..> должен быть переменным (то есть весь смысл, чтобы можно было запустить индекс вместо обработки 30 жестко закодированных вещей отдельно)
но gcc выдает ошибку: «я» не может появляться в константном выражении

По поводу "как на Java": AfaIk, двумерная матрица в Java - это не int v [10] [10]; с фиксированными размерами, но что-то вроде на телевидении; где у вас впервые есть

v = new int[10][];

(или аналогичный синтаксис), а затем, и это точка:

v[0] = new int[1];
...
v[9] = new a[10];

, которая образует треугольную матрицу или, конечно, любую форму, которая вам нравится. На самом деле обычная матрица 10 на 10 также требует 1 плюс 10 новых.

О самой структуре: Эквивалентная структура данных будет

vector<int> v1;
vector<pair<int,int>> v2;
vector<int,int,int> v3;
...
vector<int[29]> v29;

где, однако, мы должны были бы обратиться к каждой из 30 частей в отдельности.

Я бы хотел сказать v[5][3][123] = 99; установить 3-й компонент в 123-м 5-кортеже на 99, не определяя

vector<int> v[30][30];

, который бы справился, но потратил огромное пространство, так как v[1][2..30][0..\infty] or more generally v[i][i+1..30][*] никогда не используются.

Итак, в моей задаче у меня есть список целых, еще пар, троек, ..., 30 кортежей целых, которые должны быть отсортированы и т. Д., В пределах одной структуры, не тратя пространство .

0 голосов
/ 16 ноября 2009

Лучший способ сделать то, что вы хотите, это написать функции-обертки вокруг векторных методов доступа. Лучший способ обернуть существующее поведение - это написать новый класс, который будет реализован с вашим причудливым вектором вектора того, что когда-либо.

...