I guess, this is a matter of design choice: do we want a `resize()` beyond
`capacity()` to be treated as a programmer bug (something that the library
does not offer) or a correct -- even if very occasional -- usage. Both have
their justification and both bring value; but making either choice renders
a different library, even if similar on the face value. The model with
throwing exceptions is the "infinite memory model": programmer can assume
that capacity is infinite and accept that at some point an exception will
remind her that the assumption could no longer be maintained. The UB model
makes the capacity part of the contract, and programmer takes
responsibility of maintaining it.
If all STL containers take the exception model, and this library aims at
being a drop-in replacement for std::string, the it would sound more
reasonable to adapt the "infinite capacity" model.
On the other hand, if the goal is to provide a container suitable for
embedded operations, where you cannot afford throwing exceptions the same
way as you cannot afford heap allocation, one would expect the other model.
This is what static_vector has chosen.
It looks to me that these two design goals cannot be pursued together:
* be a drop-in replacement for std::string
* be a tool for embedded systems (where resource/constraint awareness
changes the way one organize programs)
As they necessitate opposite design trade-offs. Authors of fixed_string
should make the call which goal they want to pursue and document it. And
from this choice the design trade-offs will follow.
static_string came from Beast. My guess is that Beast needs the "infinite
memory" model. If you are doing networking, you can afford occasional
memory allocation required by exceptions. And you want to favor buffer
overflow protection over bleeding edge performance.
This also justifies using different prefix ("fixed_") than in
static_vector, as the latter library chose a different model.
Regards,
&rzej;
pt., 29 lis 2019 o 01:18 Andrey Semashev via Boost
On 2019-11-29 01:44, Zach Laine via Boost wrote:
Ok, I understand your point a bit better now I think. Is it the unboundedly-large nature of a NTBS that has you concerned? That is, do
think that op+=(char) should assert and op+=(char const *) should throw? That position makes sense to me, thought I don't share it -- though I
you think
that's just taste. However, I cannot imagine why I'd ever want op+=(char) or op+=(string_view) to throw.
IIRC, append/insert/push_back will throw with any container or std::string, if the result exceeds max_size(). It is only natural if fixed_string does the same, it is the expected behavior.
You can argue for a separate set of unsafe insert methods that don't perform the check and exhibit undefined behavior if the resulting length exceeds the limit. But it should be very clear that the user must ensure himself that it doesn't happen.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost