Question

To measure position/offsets/size of streams, the standard specify std::streampos, std::streamoff and std::streamsize, but they are implementation defined.

How to convert these types to long long int in a secure and portable way ? (for example to measure a file size and inject it in a function that take a long long int as argument)

Was it helpful?

Solution

Well, as far as C++98/03 is concerned, there is no long long int. So I'll assume you're asking about C++11.

The streamsize and streamoff are required to be typedefs of an integral type (streampos is not an integer, so you won't be passing that to anything that takes a long long). Since integral types are basic types, they can only be defined by either C++ or as a compiler-specific definition.

Thus, the only question is this: are these typedefs larger than long long? All integral types are convertible to a larger or equal-sized type (signed/unsigned notwithstanding, but all of the types here are signed, so no problem). But if it is larger... what are you going to do about it?

Assuming you can't change the signature of the function you are "injecting" it into (because if you could, there's no reason not to just take streamsize as the parameter type and thus avoid the problem), you don't have any options. You have a data value that is larger than what the function takes. There's no way of getting around it here.

You can perform a static_cast into a long long to shut the compiler up, but this won't help if the actual size can't fit in a long long.

Ultimately, this is an intractable problem. You have a function that takes a parameter which is potentially too small for what you're passing. The most you can do is detect when it might be a problem via a static_assert. Something like this:

static_assert(sizeof(std::streamsize) <= sizeof(long long), "Oops.");

To be honest, I wouldn't worry about it. Odds are good that long long will be the largest integral size that your compiler natively supports.

OTHER TIPS

Just pass the value to whatever function needs a long long. std::streamoff and std::streamsize are both signed integral types, and std::streampos is implicitly convertible to std::streamoff.

edit: I suppose an assert that streamsize/streamoff is not bigger than long long won't hurt, in case someone comes up with __int128 file sizes.

Short response for MINGW-64: std::streampos has a conversion operator to 64-bit-signed-integer type std::streamoff as

std::streampos pos = ...;
std::streamoff ofs = (std::streamoff) pos;

So, e.g. to find the length of a file you do not need to do more than opening an std::ifstream and evaluate ...

static unsigned long long getStreamSize(std::ifstream& is)
{
    std::streampos savePos = is.tellg();
    is.seekg(0, std::ios::end);
    std::streampos endPos = is.tellg();
    is.seekg(savePos);
    return (std::streampos)endPos;
}

... or think STL was another island ...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top