
I recall some "detail" code in Boost that does exactly what I want: allocate a probably-good-enough size on the stack but switch to heap if needed. But I can't remember where I saw it.
Looking around, I came across mentions of Boost.AutoBuffer by Thorsten Ottosen, but all links are dead.
I have been a bit busy, but I plan to get it going soon.
It seems that there is an unofficial version in
boost/signals2/auto_buffer.hpp
regards
-Thorsten Thanks. I found that copy, and it had your name on it too, so I figure it must be the same code.
I like the feature of making an "uninitialized" expansion, too. In particular, for dealing with "out" parameters of OS API calls or legacy code, I want to naturally give my buffer as a vector.data(). But it is annoying to me that it needs to zero out the whole buffer just to pass it to code that is expecting uninitialized area for output, anyway. Making "uninitialized" part of this class is natural since the hopefull stack space is used in the same context. And being your own brand new class, it doesn't fiddle with any standard library code to achieve it. <g>. However, I think the existing public API could be improved a little in this manner. Here is what I ended up doing: auto_buffer<wchar_t> buf; buf.uninitialized_grow (buf.capacity()); // start out with as much as fits on the stack (256 elements). int result= ::GetWindowTextW(hWnd,buf.data(),buf.size()); I had to figure out that capacity was the correct way to get the stack-based size, but that's a documentation thing. I called uninitialized_grow rather than uninitialized_resize because I know it was originally zero; the passing of the delta which looks like the new size too bothers me a little. But my real point is that I can't command an uninitialized size on the constructor. The normal constructor arguments work the same as vector, and can take an initial size and a value that defaults to T(). It would be much clearer and simpler for this use case to say what I want directly on the constructor. I think it would be natural to give a special flag where the value would normally go: auto_buffer<whcar_t> buf1 (500 /*count*/, L' ' /* value */); // same as std::vector auto_buffer<wchar_t> buf2 (500, non_initialized); // looks like a "value", but overloaded ctor. and it would be unambiguous to give the non_initialized flag alone, taking the maximum pre-allocated size. auto_buffer<wchar_t> buf3 (non_initialized); And, as a further trick, it is a cheap failsafe to initialize just the last element with a sentinel value. This is not as inefficient as needlessly initializing the whole buffer, but adds a cheap fallback just in case the call that was supposed to write to the buffer didn't to anything. auto_buffer<wchar_t> buf4 (non_initialized, L'\0'); // the last index is set to zero In general, any signature that takes a T after the special non_initialized_t takes it to be a sentinal initialization, and two such arguments are for last and first index (only). Or, since the same value ought to be used for both, maybe it always does first and last, or uses different special flag names for non_initialized-except-for... With the ctor signature it is clear what is being done, and I don't need to explicitly reference the stack-based size separately from the template argument that gives it. And, it generates simple direct code to set it up that way rather than setting it and changing it around again. I don't think the optimizer would figure out that capacity() at this point means the stack-based size, and then optimize out the large case from the resize code! Meanwhile, should the class support uninitialized sizing ONLY for types that support it? That is, PODs, primitives, classes without destructors, and in general those that are marked as such via a metaprogramming type trait.