On 2019-12-05 06:09, Gavin Lambert via Boost wrote:
On 5/12/2019 12:45, Andrey Semashev wrote:
fixed_string can be optimized for speed or space considerations, which may play in favor of embedded systems, but it should not be specialized to embedded systems, let alone to a specific memory layout.
But when one of the stated design goals is to target "embedded environments without a free store", it seems reasonable to consider the memory layout of the type quite closely.
Yes, but only from the implementation efficiency perspective, which is my point.
I think Peter's point is that there is another use case for plain-array-storage strings. I don't quite think that fixed_string in its current role is intended (or suitable) for this case, but other than the storage another type which does implement it would end up looking nearly identical to fixed_string.
For example, if you already have some blittable data structures:
struct ImportantData { int32_t a; int16_t b; int16_t c; char d[32]; };
The memory layout of this type is guaranteed (assuming platform alignments and padding are taken into account or specified explicitly), and it can be safely memcpy'd or stream.write()'d.
Not really, there's also endianness issue. Also, strictly speaking, IIRC up to C++20 binary representation of char is not guaranteed (i.e. it's not required to be two's complement), and even after that its size and signedness are not guaranteed. You should be using (u)int8_t instead.
Wouldn't it be nice if you could replace "d" with a fixed_string<32> (or <31>, depending on how you count the null terminator), and preserve all of those properties, while gaining the string methods?
No, unless you write your own fixed_string, which guarantees the
specific memory representation you require. You can't replace it with a
general purpose fixed_string, which was not written for your specific
use case and is not required to maintain your required memory
representation. Just as well as you can't replace ImportantData with a
std::tuple
The (big) downside is that if you want to actually be able to swap between these two implementations (eg. given existing serialized data in the old format), then you can't do fancy things with the storage such as putting the size at the end (or indeed anywhere).
This then starts leading you down the rabbit-hole of storage adapter policy templates so the user can configure how it reads and writes the length (maybe it keeps it in c; maybe it doesn't store it at all and just uses strlen; maybe it does keep it at the end of d but with some strlen fallback). I hope we can all agree that this would be an over-engineering nightmare, despite the initial attractiveness of the idea of an all-in-one "array-like string" type.
Right.