所有不同大小的类型如何相互关联?

时间:2021-01-01 14:05:10

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:

目前,我有一个场景,我想检查向filestream写入给定字符串是否会使文件超过给定的大小(这用于logfile旋转)。现在,std:::ofstream::tellp()返回一个streampos,而std:::string::size()返回一个size_t。其影响是,这不起作用:

out_stream.tellp() + string.size() < limit

because apparently there is an ambiguous overload of operator + for these types. This leads me to two questions:

因为对于这些类型,显然存在一个不明确的运算符+重载。这就引出了两个问题:

  1. How can I resolve the above ambiguity?
  2. 如何解决上述歧义?
  3. How do all the different types (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)?
  4. 所有不同的类型(size_t、streamsize、streampos、streamoff)如何相互关联?什么时候可以安全地转换它们,什么是可能的陷阱。我通常对这些类型感到困惑。我所知道的是,它们实现的依赖,和他们确定担保(如size_t总是足够容纳的最大对象的大小适合内存架构的应用程序被编译),但这些类型的担保有关的互操作性(见上面的例子,或者比较streamsize size_t)?

4 个解决方案

#1


4  

You should be able to convert the result from tellp to a std::string::size_type by casting.

您应该能够通过强制转换将tellp的结果转换为std::string::size_type。

static_cast<std::string::size_type>(out_stream.tellp()) + string.size() < limit

static_cast <: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.

编辑:这是安全的,因为您的流偏移量永远不会是负的,并且将安全地转换为无符号值。

#2


3  

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.

真正的问题是:极限的类型是什么?如果仍然有空间,通常的测试方法是:limit - out_stream.tellp() >= string.size(),但是必须确保该限制具有可以减去out_stream.tellp()的类型。

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.)

在理论上,streampos不具有可收敛性,也不能与整型相比较,或者转换为整型,它提供了重要的信息。它需要支持减法或比较。在实践中,我认为您不必过分担心转换成现有的完整类型,并且是单调的(尽管可能是在一些奇异的大型机上…)。但是您不能确定使用它的算法是否有效,因此我可能更喜欢将它显式地转换为streamsize(保证是有符号的整型)。(无论您如何处理这个问题,都必须处理string.size()返回一个size_t,它需要是unsigned,而streamsize需要签名)。

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.

关于你提到的第二个问题:size_t类型定义无符号整型,大到指定大小的任何可能的对象,streamsize typedef签署积分类型,大到指定大小的“对象”流,streamoff是不可或缺的类型定义类型可以指定一个字节的位置的一个文件,和streampos typedef fpo,是一种可以用来维护国家的多字节的流。该标准很少对它们之间的关系做出要求(其中的一些要求在数学上是不可能实现的),所以您基本上是独立的。

#3


1  

I believe the standard says that streamsize is implementation-specific, so no help there. For a practical answer, you can check the headers where these are typedefed.

我相信这个标准说的是流线型是特定于实现的,所以没有帮助。对于实际的答案,您可以检查这些标题的类型。

Considering that size_t might be 4 bytes while your application could conceivably operate on a stream of more than 4GB length, I believe that you should cast to a known-good-size type for interoperating for an airtight solution.

考虑到size_t可能是4个字节,而您的应用程序可以在超过4GB长度的流上运行,我认为您应该使用一个已知的大尺寸类型来进行密闭解决方案的互操作。

Of course, if you know (maybe with a compile-time assertion) that size_t or streamsize is 8 bytes long, you can use that type directly. If you have a stream whose length doesn't fit in 8 bytes, you have more serious problems than casting to the right type.

当然,如果您知道size_t或streamsize为8字节长,您可以直接使用该类型。如果有一个流的长度不能满足8字节,那么就会出现比转换到正确类型更严重的问题。

#4


0  

If you have big sizes, isn't unsigned long long the best you can get. If that isn't big enough, what else is?

如果你有大码,不是没有签名的长,你能得到的最好的。如果这个不够大,还有什么?

#1


4  

You should be able to convert the result from tellp to a std::string::size_type by casting.

您应该能够通过强制转换将tellp的结果转换为std::string::size_type。

static_cast<std::string::size_type>(out_stream.tellp()) + string.size() < limit

static_cast <: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.

编辑:这是安全的,因为您的流偏移量永远不会是负的,并且将安全地转换为无符号值。

#2


3  

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.

真正的问题是:极限的类型是什么?如果仍然有空间,通常的测试方法是:limit - out_stream.tellp() >= string.size(),但是必须确保该限制具有可以减去out_stream.tellp()的类型。

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.)

在理论上,streampos不具有可收敛性,也不能与整型相比较,或者转换为整型,它提供了重要的信息。它需要支持减法或比较。在实践中,我认为您不必过分担心转换成现有的完整类型,并且是单调的(尽管可能是在一些奇异的大型机上…)。但是您不能确定使用它的算法是否有效,因此我可能更喜欢将它显式地转换为streamsize(保证是有符号的整型)。(无论您如何处理这个问题,都必须处理string.size()返回一个size_t,它需要是unsigned,而streamsize需要签名)。

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.

关于你提到的第二个问题:size_t类型定义无符号整型,大到指定大小的任何可能的对象,streamsize typedef签署积分类型,大到指定大小的“对象”流,streamoff是不可或缺的类型定义类型可以指定一个字节的位置的一个文件,和streampos typedef fpo,是一种可以用来维护国家的多字节的流。该标准很少对它们之间的关系做出要求(其中的一些要求在数学上是不可能实现的),所以您基本上是独立的。

#3


1  

I believe the standard says that streamsize is implementation-specific, so no help there. For a practical answer, you can check the headers where these are typedefed.

我相信这个标准说的是流线型是特定于实现的,所以没有帮助。对于实际的答案,您可以检查这些标题的类型。

Considering that size_t might be 4 bytes while your application could conceivably operate on a stream of more than 4GB length, I believe that you should cast to a known-good-size type for interoperating for an airtight solution.

考虑到size_t可能是4个字节,而您的应用程序可以在超过4GB长度的流上运行,我认为您应该使用一个已知的大尺寸类型来进行密闭解决方案的互操作。

Of course, if you know (maybe with a compile-time assertion) that size_t or streamsize is 8 bytes long, you can use that type directly. If you have a stream whose length doesn't fit in 8 bytes, you have more serious problems than casting to the right type.

当然,如果您知道size_t或streamsize为8字节长,您可以直接使用该类型。如果有一个流的长度不能满足8字节,那么就会出现比转换到正确类型更严重的问题。

#4


0  

If you have big sizes, isn't unsigned long long the best you can get. If that isn't big enough, what else is?

如果你有大码,不是没有签名的长,你能得到的最好的。如果这个不够大,还有什么?