boost::array support for runtime-sized arrays

Recently I came up with a modified version of boost::array that supports runtime sized arrays. The current boost::array implementation is great but every now and then you'll need runtime-sized arrays: it's simply impossible to know everything at compile time. It is backwards compatible: boost::array<int, 10> sarray; but it can be used this way now: boost::array<int> darray(10); I realize you could simply use std::vector, but sometimes all you want is a fixed-size array (but sized at runtime). Besides, I am not sure about the overhead involved with std::vector for these simple scenarios. Comments welcome, Steven

On 7/19/06, Steven Burns <royalstream@hotmail.com> wrote:
Recently I came up with a modified version of boost::array that supports runtime sized arrays.
It is backwards compatible:
boost::array<int, 10> sarray;
but it can be used this way now:
boost::array<int> darray(10);
How did you implement this? A partial specialisation for when the size is the new default of -1 or something? Of course, with that constructor you no longer have an aggregate, which is one of the big advantages of boost::array.
I realize you could simply use std::vector, but sometimes all you want is a fixed-size array (but sized at runtime). Besides, I am not sure about the overhead involved with std::vector for these simple scenarios.
Up to your implementation, but for most I'd expect it to be only the one extra pointer needed per container to hold the capacity information. Check to see whether in your implementation the initial capacity is the same as the size after construction from a size. I don't think there'd be any speed difference. ~ Scott McMurray

Indeed I did a partial spec. when the size is 0 (size_t cannot be -1) Losing the aggregate behavior was not an option so I only have constructors on this specialization. This means you can still do this: boost::array<int, 5> sarray = {1,2,3,4,5}; // works! but not this: boost::array<int> sarray(5) = {1,2,3,4,5}; // no way jose :( There's simply no way to create runtime-sized aggregates (that I know of) I am looking for a test suite for boost::array (if exists) to make sure I didnt break anything, and I also wanted to hear some opinions on the subject. Steven "me22" <me22.ca@gmail.com> wrote in message news:fa28b9250607192031j73ddcee0q4f892335e06a0d8@mail.gmail.com...
On 7/19/06, Steven Burns <royalstream@hotmail.com> wrote:
Recently I came up with a modified version of boost::array that supports runtime sized arrays.
It is backwards compatible:
boost::array<int, 10> sarray;
but it can be used this way now:
boost::array<int> darray(10);
How did you implement this? A partial specialisation for when the size is the new default of -1 or something?
Of course, with that constructor you no longer have an aggregate, which is one of the big advantages of boost::array.
I realize you could simply use std::vector, but sometimes all you want is a fixed-size array (but sized at runtime). Besides, I am not sure about the overhead involved with std::vector for these simple scenarios.
Up to your implementation, but for most I'd expect it to be only the one extra pointer needed per container to hold the capacity information. Check to see whether in your implementation the initial capacity is the same as the size after construction from a size.
I don't think there'd be any speed difference.
~ Scott McMurray _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 7/20/06, Steven Burns <royalstream@hotmail.com> wrote:
Indeed I did a partial spec. when the size is 0 (size_t cannot be -1) Losing the aggregate behavior was not an option so I only have constructors on this specialization.
In TR1, iirc, array<T,0> is legal. And size_t can of course not be -1, but because 0 is a valid choice for the aggregate version I figured integer_traits::<size_t>::cmax would be the best choice for the specialisation. ~ Scott McMurray

Steven Burns wrote:
Indeed I did a partial spec. when the size is 0 (size_t cannot be -1) Losing the aggregate behavior was not an option so I only have constructors on this specialization.
This means you can still do this:
boost::array<int, 5> sarray = {1,2,3,4,5}; // works!
but not this:
boost::array<int> sarray(5) = {1,2,3,4,5}; // no way jose :(
There's simply no way to create runtime-sized aggregates (that I know of) I am looking for a test suite for boost::array (if exists) to make sure I didnt break anything, and I also wanted to hear some opinions on the subject.
Unfortunately that would break Boost.Array in Boost-1.34 onwards which already has a TR1-compatible partial specialisation for zero-sized arrays. I've been trying to think of what array-like objects I use already and how this would fit in: C style arrays: Hardly ever, except for small immutable arrays. For example tables of coefficients for rational approximations. Boost.Array: Mostly for fixed size tables of immutable data, test data for example. Scoped_array: Useful for temporary buffers whose size is determined at runtime. Doesn't have a container interface though, and probably mostly used for interfacing with legacy C API's. Shared_array: Never used it. Might do if I wanted to write a copy-on-write string/vector, but that's about all. std::vector/std::string: Used for everything else, which encompasses quite a lot :-) So.... you have quite a lot of competition here, and I've yet to see a compelling reason to have yet-another-vector :-) Thinking out loud, the issues, seems to boil down to: Code size: I would be very surprised to see any difference, although vector/string have "fatter" interfaces, you only pay for the member functions you actually use. Indeed if vector<whatever> is instantiated already somewhere else in the program, or if you can use std::string and that's already in use elsewhere, then you may *save* on code size by reusing these. Object size: I guess your runtime-sized array would be sizeof(void*) in size, compared to typically three times that for a vector. There may be times when that's important - embedded systems for example - but then unless you really need a container-like interface scoped_array is probably a better bet. Actually I think I may have just provided a compelling reason for a real lightweight container after all then! It would have to be called something other than array though :-) Just thinking out loud, John.

loufoque wrote:
John Maddock wrote :
Scoped_array: Useful for temporary buffers whose size is determined at runtime. Doesn't have a container interface though, and probably mostly used for interfacing with legacy C API's.
Why not use std::vector here ? You get the interfacing with C using &v[0].
True. And thinking about it, I can't actually remember ever using it either, but that was the motivation for providing it if my memory is correct. My only complaint about std::vector is that the &v[0] always feels like a hack to me, even if it is guarenteed to work. John.

Actually the size of the container I have would be (sizeof(void*) + sizeof(size_t)) because you have to store the array's length, so I have to agree is starting to look like we are better of using std::vector. The problem I see with scoped_array is that it doesnt even have a size() or equivalent method which is kind of mandatory for very array class. Steven. "John Maddock" <john@johnmaddock.co.uk> wrote in message news:005e01c6ac13$0cd8f8e0$ea8c0252@fuji...
Steven Burns wrote:
Indeed I did a partial spec. when the size is 0 (size_t cannot be -1) Losing the aggregate behavior was not an option so I only have constructors on this specialization.
This means you can still do this:
boost::array<int, 5> sarray = {1,2,3,4,5}; // works!
but not this:
boost::array<int> sarray(5) = {1,2,3,4,5}; // no way jose :(
There's simply no way to create runtime-sized aggregates (that I know of) I am looking for a test suite for boost::array (if exists) to make sure I didnt break anything, and I also wanted to hear some opinions on the subject.
Unfortunately that would break Boost.Array in Boost-1.34 onwards which already has a TR1-compatible partial specialisation for zero-sized arrays.
I've been trying to think of what array-like objects I use already and how this would fit in:
C style arrays: Hardly ever, except for small immutable arrays. For example tables of coefficients for rational approximations.
Boost.Array: Mostly for fixed size tables of immutable data, test data for example.
Scoped_array: Useful for temporary buffers whose size is determined at runtime. Doesn't have a container interface though, and probably mostly used for interfacing with legacy C API's.
Shared_array: Never used it. Might do if I wanted to write a copy-on-write string/vector, but that's about all.
std::vector/std::string: Used for everything else, which encompasses quite a lot :-)
So.... you have quite a lot of competition here, and I've yet to see a compelling reason to have yet-another-vector :-)
Thinking out loud, the issues, seems to boil down to:
Code size: I would be very surprised to see any difference, although vector/string have "fatter" interfaces, you only pay for the member functions you actually use. Indeed if vector<whatever> is instantiated already somewhere else in the program, or if you can use std::string and that's already in use elsewhere, then you may *save* on code size by reusing these.
Object size: I guess your runtime-sized array would be sizeof(void*) in size, compared to typically three times that for a vector. There may be times when that's important - embedded systems for example - but then unless you really need a container-like interface scoped_array is probably a better bet.
Actually I think I may have just provided a compelling reason for a real lightweight container after all then! It would have to be called something other than array though :-)
Just thinking out loud,
John.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Steven Burns wrote:
Recently I came up with a modified version of boost::array that supports runtime sized arrays.
The current boost::array implementation is great but every now and then you'll need runtime-sized arrays: it's simply impossible to know everything at compile time.
It is backwards compatible:
boost::array<int, 10> sarray;
but it can be used this way now:
boost::array<int> darray(10);
I realize you could simply use std::vector, but sometimes all you want is a fixed-size array (but sized at runtime). Besides, I am not sure about the overhead involved with std::vector for these simple scenarios.
Comments welcome,
Boost.Array looks deprecated by Boost.Range, IMHO. (Broken compilers still need it, though.) I'm not sure whether or not 'std::vector' made dynamic array deprecated. Well, how's that? :-) template< class Value > struct array_range : private boost::base_from_member< boost::scoped_array<Value> >, boost::iterator_range<Value *>, private boost::noncopyable { private: typedef boost::base_from_member< boost::scoped_array<Value> > scoped_array_bt; typedef boost::iterator_range<Value *> super_t; public: explicit array_range(std::size_t sz) : scoped_array_bt(new Value[sz]), super_t(scoped_array_bt::member.get(), scoped_array_bt::member.get() + sz) { } }; -- Shunsuke Sogame

Shunsuke Sogame wrote:
Steven Burns wrote:
Recently I came up with a modified version of boost::array that supports runtime sized arrays.
The current boost::array implementation is great but every now and then you'll need runtime-sized arrays: it's simply impossible to know everything at compile time.
It is backwards compatible:
boost::array<int, 10> sarray;
but it can be used this way now:
boost::array<int> darray(10);
I realize you could simply use std::vector, but sometimes all you want is a fixed-size array (but sized at runtime). Besides, I am not sure about the overhead involved with std::vector for these simple scenarios.
Comments welcome,
Boost.Array looks deprecated by Boost.Range, IMHO. (Broken compilers still need it, though.) I'm not sure whether or not 'std::vector' made dynamic array deprecated. Well, how's that? :-)
What makes you think Boost.Array is deprecated? Especially by Boost.Range which does something quite different? John.

John Maddock wrote:
Shunsuke Sogame wrote:
Steven Burns wrote:
Recently I came up with a modified version of boost::array that supports runtime sized arrays.
The current boost::array implementation is great but every now and then you'll need runtime-sized arrays: it's simply impossible to know everything at compile time.
It is backwards compatible:
boost::array<int, 10> sarray;
but it can be used this way now:
boost::array<int> darray(10);
I realize you could simply use std::vector, but sometimes all you want is a fixed-size array (but sized at runtime). Besides, I am not sure about the overhead involved with std::vector for these simple scenarios.
Comments welcome, Boost.Array looks deprecated by Boost.Range, IMHO. (Broken compilers still need it, though.) I'm not sure whether or not 'std::vector' made dynamic array deprecated. Well, how's that? :-)
What makes you think Boost.Array is deprecated? Especially by Boost.Range which does something quite different?
I mean I prefer range-concept rather than container-concept. -- Shunsuke Sogame

Steven Burns <royalstream <at> hotmail.com> writes:
Recently I came up with a modified version of boost::array that supports runtime sized arrays....boost::array<int> darray(10);
Something I think would be useful is an implementation similar to std::vector that uses a small-string like optimization, where the size of the stack buffer is a template parameter. For example, myarray<char, 10> v; // allocates 10 bytes on the stack for(int n=0; n<9; n++) v.push_back('.'); // no heap allocations for(int n=0; n<9; n++) v.push_back('.'); // triggers realloc from heap This has a few advantages: (1) For <= 10 chars, it requires no heap allocation and therefore is fast for some things (similar to C arrays and boost::array). (2) It can grow beyond 10 chars via heap allocation (like std::vector but unlike boost::array). (3) It maintains both variable size and capacity (like std::vector but unlike boost::array). In fact, this is the approach I'm taking to reimplement basic_string via flex_string (http://erdani.org/code/main.html), though I had patch flex_string so that it would work with N > 127 : template <size_t N> struct sstring { typedef flex_string< char, std::char_traits<char>, std::allocator<char>, SmallStringOpt<SimpleStringStorage<char>, N> > type; }; sstring<500>::type s; // usage Perhaps there could be a "flex_vector" as well? flex_vector< int, std::allocator<int>, SmallVectorOpt<SimpleVectorStorage<int>, N>
BTW, is there any chance that flex_string might be added to Boost? I see a forked version of it included as a utility in Boost Wave, but it's not a formal part of Boost itself, and it would be nice to have a single version of it maintained. --davidm
participants (6)
-
David Manura
-
John Maddock
-
loufoque
-
me22
-
Shunsuke Sogame
-
Steven Burns