On Thu, Dec 5, 2019 at 9:45 AM Andrey Semashev via Boost
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. Why? There are two goals: usability and efficiency. You should weight
What do you mean by specialized? It is designed to also favour embedded systems. these and not just unconditionally focus on one aspect. In practice I believe that efficiency will not suffer measurably no matter how you represent the length.
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]; };
Gavin expresses my point of view quite precisely except that we are a bit stricter wrt. alignment.
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.
That does not really matter. As an embedded developer we know our hardware. We do not require it to be ultra portable and might be happy with working on platforms with 8-bit two-complement characters.
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. Or it is provided by boost?
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
> and expect it to preserve the memory layout. It may actually do preserve, but by a pure coincidence. There is not such a guarantee for std::tuple. This is not a surprise - we program against a standard. 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.