Array of arrays of different sizes

I have code that creates a set of tr1 :: array of different sizes, but the same type, for example

array<int, 2> array<int, 4> array<int, 6> 

the number of these arrays and their sizes are given at compile time, so I know for sure how many there will be and how many there will be (but they can be different).

Problem: I would like to put them in a collection (using array <> would be great), but the type should be equal for all members, and that is not the case.

I was thinking about using boost :: variant, but how do I specify a variant with a specific list of types at compile time (I think about the heavy use of the preprocessor ...)? How about using boost :: any? Other methods? (Wild pointers?)

TIA ~ Aki

Correction: the preprocessor is not used in this case.

+4
source share
3 answers

I would use the Boost MPL and Fusion libraries. There are two ways to get a list of types: generate them or explicitly define them. The first bit is more flexible, but itโ€™s hard to say what suits you because we donโ€™t know how you get the values โ€‹โ€‹that you have.

In any case, giving rise to:

 #include <boost/mpl/for_each.hpp> #include <boost/mpl/range_c.hpp> #include <boost/mpl/transform.hpp> #include <boost/mpl/vector.hpp> #include <array> #include <iostream> namespace bmpl = boost::mpl; // turns an index into an array template <typename T> struct make_array { // or whatever scheme you have static const std::size_t size = T::value * 2; // define generated type typedef std::array<int, size> type; }; // list of values to convert typedef bmpl::range_c<size_t, 1, 10> array_range; // transform that list into arrays, into a vector typedef bmpl::transform<array_range, make_array<bmpl::_1>, bmpl::back_inserter<bmpl::vector<>> >::type array_collection; 

Or explicitly indicating:

 #include <boost/mpl/vector.hpp> #include <array> #include <iostream> namespace bmpl = boost::mpl; // list all array types typedef bmpl::vector< std::array<int, 2>, std::array<int, 4>, std::array<int, 6>, std::array<int, 8>, std::array<int, 10>, std::array<int, 12>, std::array<int, 14>, std::array<int, 16>, std::array<int, 18> > array_collection; 

In any case, you can use it as follows:

 #include <boost/fusion/algorithm.hpp> #include <boost/fusion/container/vector.hpp> #include <boost/fusion/mpl.hpp> #include <boost/fusion/sequence.hpp> #include <boost/mpl/for_each.hpp> #include <typeinfo> // fusion "fuses" the bridge between MPL and runtime namespace bf = boost::fusion; struct print_type { template <typename T> void operator()(const T&) const { std::cout << typeid(T).name() << "\n"; } }; struct print_values { template <typename T> void operator()(const T& pArray) const { std::cout << "Printing array with size " << pArray.size() << ":\n"; std::for_each(pArray.begin(), pArray.end(), [](int pX) { std::cout << pX << " "; }); std::cout << std::endl; } }; int main(void) { // print all the types you have bmpl::for_each<array_collection>(print_type()); std::cout.flush(); // make a usable type out of the typelist typedef bf::result_of::as_vector<array_collection>::type array_fusion; array_fusion arrays; // now have an array of different arrays, // compile-time generated but run-time usable // access like this: bf::at_c<0>(arrays)[1] = 5; bf::at_c<1>(arrays)[2] = 7; bf::at_c<2>(arrays)[0] = 135; // for_each: bf::for_each(arrays, print_values()); } 
+3
source

The only way to place classes in an STL container is if the container contains pointers (references do not work because they are not constructive by default) for some basic type, and the objects you want to collect inherit from this type. Note that a container (or any template class) of a type that inherits from a base class does not inherit from a container of a base type. You can just use void *, but you need to do a lot of ugly and dangerous casting, and you have to remember to free the memory yourself. Why don't you write an array of arrays with a fixed size that allows you to set the size in the constructor? if you write as a wrapper around araray, this should not be too much work. If you want to use some kind of smart pointer-based solution, you wonโ€™t be tempted to use auto_ptr because copy semantics are wrong for STL containers - go for something like boost shared_ptr.

0
source

You do not say why you need to collect arrays of static size in different sizes. This is pretty weird. Why not use a collection of arrays with dynamic size?

Your options:

  • use std :: vector instead of std :: tr1 :: array.

  • Save the pointer to the array and the size of the array in your collection. It might look something like this: std::vector<std::pair<int *, size_t> > . Just make sure that the lifetime of arrays is not less than the lifetime of a vector!

  • I would expect boost :: variant to work, but it would be rather difficult to use in practice.

boost::variant<array<int, 2>, array<int, 4>, array<int, 6>, ... >

0
source

All Articles