My model would best use some
v int[30][i][N_i];
structure that is 30 vectors of tuples of ints, where
v[0] is a dummy,
v[1] are plain ints (N_0 of them), v[2] are pairs of int (N_1 pairs) ... v[29] would be 29-tuples of int (N_29 of them)This is not vector<vector<int>>
like in "generic-vector-of-开发者_运维知识库vectors-in-c"
Apparently, the outer fixed dim=30 is no problem, the inner one is taken care of by the self-extending STL vector class.
Is there any way to get the middle dimension fixed, but not constant?
As I wrote in a comment to your question, I'm not sure to understand what you are looking for (and I'm very interested by the "as in Java" part, BTW).
But since I thought it would be fun to see how it could be generated with Boost.MPL (and Fusion... and Array), I'm assuming that you want a statically defined structure whose Ntn element is a vector of int arrays of size 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;
}
The best way to do what you want is write wrapper functions around the vector accessors. The best way to wrap existing behavior is to write a new class that is implemented with your fancy vector of vector of what ever.
I'm Michael (the initial author) now having ID La-AIDA
Firstly, thank you all, Boost & Fusion where new to me.
To Éric: One Typo: v[1] should have N_1 entries, v[2] N_2 and so forth. I would like STL-like stuff, not C-arrays (lacking bounds check with no option to add it).
New comment to Éric: I tried your solution, it worked (almost, after removing the dummy query) immediately! Thank you! But: I need something like
for (i = 1;i < 30;i++) {
cout << s.At<i>[0] << endl;
}
that is, the index for At<..> should be variable (that is the whole point, to be able to run an index instead of treating 30 hard-coded things separately)
but gcc complains with error: 'i' cannot appear in a constant-expression
About the "as in Java": AfaIk, a two-dim matrix in Java is not some int v[10][10]; with fixed dimensions, but something like int[][] v; where you first have a
v = new int[10][];
(or similar syntax) and then, and this is the point:
v[0] = new int[1];
...
v[9] = new a[10];
which makes a triangular matrix, or of course any form you like. In fact a regular 10-by-10 matrix as well requires 1 plus 10 new's.
About the structure itself: An equivalent data structure would be
vector<int> v1;
vector<pair<int,int>> v2;
vector<int,int,int> v3;
...
vector<int[29]> v29;
where however we would have to address each of the 30 parts separately.
I would like to be able to say v[5][3][123] = 99;
to set the 3rd component in the 123rd 5-tuple to 99, without defining
vector<int> v[30][30];
which would do the trick, but wasting enormous space, since
v[1][2..30][0..\infty] or more generally v[i][i+1..30][*]
are never used.
So, in my problem, I have a list of int's , another of pairs, of triples,..., of 30-tuples of int's, which all should be sortable etc., within a single structure, without wasting space.
精彩评论