Re: [boost] Re: static sized strings

Rob Stewart wrote:
From: David Abrahams > John Nagle writes:
If you're willing to accept a call to "new", you can just use std::string and reserve some initial size.
It's not the same thing. You might only be willing to accept a call to "new" if things go beyond a certain length. That's *usually* the only reason I'd ever have a fixed-size buffer. Very occasionally I'll be in code that where I don't want to throw an exception, but then a string that responds to overflow by throwing is no better.
char_string can throw a more meaningful exception than std::bad_alloc.
In the small string optimization or std::string with reserve approaches, the buffer grows when the input is too large, and other, downstream code may overflow or behave badly. Stopping the overflow early may be better and having an automated mechanism for preventing overflow is wise.
There is not meant to be any buffer allocation. char_string is a fixed-capacity string that will not write beyond the length of that buffer.
So you don't need that capabiilty in char_string. char_string is for situations when you don't want to invoke dynamic allocation at all. In desktop applications, that's not too common, but in real time work, inside operating systems, and in embedded applications it's not unusual.
I'm saying, it's almost always better to degrade performance gracefully as the program's input grows than it is to introduce an execution discontinuity like an exception (if possible). In many of those scenarios you've named, exceptions, like dynamic allocation have been banned anyway for similar real and/or imaginary reasons.
There's probably room and need for both types of strings.
I don't intend the char_string buffer to be increased. I intended that the operations on the buffer would not go beyond the buffer (which would lead to overflow) and also that going over the buffer would not generate an exception. It may be beneficial to have an error policy to determin the behaviour in the event of an overflow. I am not advocating this approach, just putting it up for discussion. The only exception I can see keeping is the one in the constructor to test for a buffer of 0, but this would be better re-implemented as a compile-time check using mpl code, e.g.: template< int n, ... > class char_string { class ok{ typedef char value; }; class zero_buffer_error{}; typedef mpl::if_< mpl::equal< n, 0 >, zero_buffer_error, ok >::value value; }; Regards, Reece _________________________________________________________________ Find a cheaper internet access deal - choose one to suit you. http://www.msn.co.uk/internetaccess

Reece wrote:
There is not meant to be any buffer allocation. char_string is a fixed-capacity string that will not write beyond the length of that buffer.
I implemented a fixed_string class with an "overflow" policy, acting both on filling the string and accessing it, where I supplied four implementations, (1) no check (well, this would not help against those buffer overflow attacks someone mentioned...) for out-of-bounds operations, (2) just ignore out-of-bounds, i.e., truncate long fills and ignore operations, (3) throw an exception both on overflow fills and operations and (4) allocate a 'std::string' for the overflow (minus the size used in the union structure...) which would not make it fixed size, just particularly efficient for strings of a maximum fixed length. I would welcome "overflow" policies to the static and fixed size string. /David

From: "Reece Dunn" <msclrhd@hotmail.com>
Rob Stewart wrote:
From: David Abrahams > John Nagle writes:
If you're willing to accept a call to "new", you can just use std::string and reserve some initial size.
It's not the same thing. You might only be willing to accept a call to "new" if things go beyond a certain length. That's *usually* the only reason I'd ever have a fixed-size buffer. Very occasionally I'll be in code that where I don't want to throw an exception, but then a string that responds to overflow by throwing is no better.
char_string can throw a more meaningful exception than std::bad_alloc.
In the small string optimization or std::string with reserve approaches, the buffer grows when the input is too large, and other, downstream code may overflow or behave badly. Stopping the overflow early may be better and having an automated mechanism for preventing overflow is wise.
There is not meant to be any buffer allocation. char_string is a fixed-capacity string that will not write beyond the length of that buffer.
I know that's what you meant, but Dave was suggesting using the small string optimization as a means to get the best of both worlds. It would give the no-allocation behavior of your proposal plus the ability to grow via the free store when that initial allocation was exceeded. There could even be a template parameter to control whether to allow the buffer to grow beyond its initial, stack-based allocation. One way would fit your idea, another would use the small string optimization.
So you don't need that capabiilty in char_string. char_string is for situations when you don't want to invoke dynamic allocation at all. In desktop applications, that's not too common, but in real time work, inside operating systems, and in embedded applications it's not unusual.
I'm saying, it's almost always better to degrade performance gracefully as the program's input grows than it is to introduce an execution discontinuity like an exception (if possible). In many of those scenarios you've named, exceptions, like dynamic allocation have been banned anyway for similar real and/or imaginary reasons.
There's probably room and need for both types of strings.
I don't intend the char_string buffer to be increased. I intended that the operations on the buffer would not go beyond the buffer (which would lead to overflow) and also that going over the buffer would not generate an exception.
I understand that's your intention, but Dave's suggesting that it would be better if instead of dropping information on the floor silently or throwing an exception when there's no room for a null terminator, a less efficient, but correct class might be appropriate. (Actually, I think I'm putting words in Dave's mouth. IIRC, he was only addressing the "exception on insufficient space for a terminator" matter.) Perhaps what you meant to say was that you think a critical design criteria of char_string is that it should *never* grow. I didn't read that from the above.
It may be beneficial to have an error policy to determin the behaviour in the event of an overflow. I am not advocating this approach, just putting it up for discussion.
That's why I suggested there's probably room for both. A policy might be a good way to handle it. A separate class could do it, too. It's a matter of use cases. Are there cases in which the string should never exceed its initial capacity? What will happen if it does (and it is designed to work correctly if it does)? Are there uses cases in which the string should have an initial capacity for efficiency reasons but should grow if the input exceeds its initial capacity? I can imagine uses for both, but I'm not certain that there are.
The only exception I can see keeping is the one in the constructor to test for a buffer of 0, but this would be better re-implemented as a compile-time check using mpl code, e.g.:
template< int n, ... > class char_string { class ok{ typedef char value; }; class zero_buffer_error{};
typedef mpl::if_< mpl::equal< n, 0 >, zero_buffer_error, ok >::value value; };
Yes, that's a good idea. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;
participants (3)
-
David Bergman
-
Reece Dunn
-
Rob Stewart