Currently I have a scenario where I want to check whether writing a given string to a filestream will grow the file beyond a given size (this is used for logfile rotation). Now, std::ofstream::tellp()
returns a streampos
, but std::string::size()
returns a size_t
. The effect is, that this does not work:
out_stream.tellp() + string.size() < limit
because apparently there is an ambiguous overload of operator +
for these types. This leads me to two questions:
size_t
, streamsize
, streampos
, streamoff
) relate to each other? When can they be safely converted, and what are possible pitfalls. I am generally confused about these types. All I know is that they are implementation dependent, and that they make certain guarantees (e.g. size_t
is always large enough to hold the size of the larges object that would fit into memory on the architecture for which the application was compiled), but what are the guarantees concerning interoperability of these types (see example above, or comparing a streamsize
to a size_t
)?To create the different sizes of a scale, the technical designer will change certain “points of measurement”, such as the bust or waist by specific increments to create the other sizes. Ultimately we wear different sizes across different brands because clothing companies use different fit models.
In other words, under time and cost pressures, the waistband could be cut an inch too big, then stitched in the wrong place, which adds up to a few inches difference in actual size. That's how identical items, from the same brands, sometimes don't fit the same.
However, as much as our bodies do change every now and then, the reason why sizes attached on clothing items can be outrageously different from store to store is a result of a retail phenomenon called vanity sizing.
Vanity sizing, or size inflation, is the phenomenon of ready-to-wear clothing of the same nominal size becoming bigger in physical size over time. This has been documented primarily in the United States and the United Kingdom.
You should be able to convert the result from tellp to a std::string::size_type
by casting.
static_cast<std::string::size_type>(out_stream.tellp()) + string.size() < limit
EDIT: This is safe because your stream offset will never be negative and will safely convert to an unsigned value.
The real question is: what is the type of limit? The usual way of testing if there is still room is usually: limit - out_stream.tellp() >= string.size() But you have to ensure that limit has a type from which out_stream.tellp() can be subtracted.
In theory, streampos isn't convertable nor comparable to an integral type, or that, converted to an integral type, it gives significant information. And it needed support subtraction, or comparison, for that matter. In practice, I don't think you have to worry too much about the conversion to an integral type existing, and being monotonic (although perhaps on some exotic mainframe...). But you can't be sure that arithmetic with it will work, so I'd probably prefer converting it explicitly to a streamsize (which is guaranteed to be a signed integral type). (Regardless of how you approach the problem, you'll have to deal with the fact that string.size() returns a size_t, which is required to be unsigned, whereas streamsize is required to be signed.)
With regards to your second question: size_t is a typedef to an unsigned integral type, large enough to specify the size of any possible object, streamsize is a typedef to a signed integral type, large enough to specify the size of an "object" in a stream, streamoff is a typedef to an integral type capable of specifying the position of a byte in a file, and streampos is a typedef to fpos, where something is a type which can be used to maintain the state in the case of a multibyte stream. The standard makes very few requirements concerning the relationships between them (and some of the few it makes are mathematically impossible to realize), so you're pretty much on your own.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With