[英]Why does the C++ standard algorithm “count” return a difference_type instead of size_t?
Why is the return type of std::count
the difference_type
of the iterators (often a ptrdiff_t
). 为什么
std::count
的返回类型是迭代器的difference_type
(通常是ptrdiff_t
)。
Since count can never be negative, isn't size_t
technically the right choice? 因为count永远不会是负数,所以
size_t
技术上不是正确的选择吗? And what if the count exceeds the range of ptrdiff_t
since the theoretical possible size of an array can be size_t
? 如果计数超出
ptrdiff_t
的范围怎么办,因为数组的理论可能大小可以是size_t
?
EDIT: So far there is no suitable answer as to why the function returns ptrdiff_t
. 编辑:到目前为止,没有合适的答案为什么函数返回
ptrdiff_t
。 Some explanation gathered from the answers below is that the return type is iterator_traits<InputIterator>::difference_type
which is generic and can be anything. 从下面的答案中收集的一些解释是返回类型是
iterator_traits<InputIterator>::difference_type
,它是通用的,可以是任何东西。 Up until that point it makes sense. 直到那时它才有意义。 There are cases where the count may exceed
size_t
. 有些情况下,计数可能超过
size_t
。 However, it still does not make sense why the return type is typedef ptrdiff_t iterator_traits<InputIterator>::difference_type
for the standard iterators instead of typedef size_t iterator_traits<InputIterator>::difference_type
. 但是,为什么返回类型是标准迭代器的
typedef ptrdiff_t iterator_traits<InputIterator>::difference_type
而不是typedef size_t iterator_traits<InputIterator>::difference_type
仍然没有意义。
The std::count()
algorithm relies on the iterator type to define an integral type large enough to represent any size of a range. std::count()
算法依赖于迭代器类型来定义一个足以表示范围的任何大小的整数类型。 Possible implementation of containers include files and network streams, etc. There is no guarantee that the entire range fits into the process' address space at once, so std::size_t
might be too small. 容器的可能实现包括文件和网络流等。不能保证整个范围一次适合进程的地址空间,因此
std::size_t
可能太小。
The only integral type offered by the standard std::iterator_traits<>
is std::iterator_traits<>::difference_type
, which is suitable for representing "distances" between two iterators. 标准
std::iterator_traits<>
提供的唯一整数类型是std::iterator_traits<>::difference_type
,它适用于表示两个迭代器之间的“距离”。 For iterators implemented as (wrappers of) pointers, this type is std::ptrdiff_t
. 对于实现为(包装)指针的迭代器,此类型为
std::ptrdiff_t
。 There is no size_type
or the like from iterator traits, so there is no other choice. 迭代器特征没有
size_type
等,所以没有其他选择。
size_t
is not technically the correct choice, since it might not be big enough. size_t
在技术上不是正确的选择,因为它可能不够大。 Iterators are permitted to iterate over "something" that is larger than any object in memory -- for example a file on disk. 允许迭代器迭代比内存中任何对象更大的“东西” - 例如磁盘上的文件。 When they do so, the iterator can define a type larger than
size_t
as its difference_type
, if one is available. 当它们这样做时,迭代器可以将大于
size_t
的类型定义为其difference_type
(如果有的话)。
difference_type
needs to be signed because in contexts other than std::count
it represents offsets between iterators in both directions . difference_type
需要签名,因为在除std::count
之外的上下文中,它表示两个方向上的迭代器之间的偏移量。 For random access iterators, it + difference
is a perfectly sensible operation even when difference
is negative. 对于随机访问迭代器,即使
difference
为负, it + difference
也是一种非常明智的操作。
iterator_traits
doesn't offer an unsigned type. iterator_traits
不提供无符号类型。 Maybe it should, but given that it doesn't iterator_traits<InputIterator>::difference_type
is the best type available. 也许它应该,但鉴于它没有
iterator_traits<InputIterator>::difference_type
是可用的最佳类型。
The issue of whether iterators should offer an unsigned type probably relates to a massive conflict of coding styles, whether unsigned types should be used for counts at all. 迭代器是否应该提供无符号类型的问题可能与编码样式的大量冲突有关,无论是否应使用无符号类型进行计数。 I don't propose to reproduce that argument here, you can look it up.
我不打算在这里重现那个论点,你可以查一查。
ptrdiff_t
does have a weakness that on some systems it cannot represent all valid pointer differences, and hence also cannot represent all expected results of std::count
. ptrdiff_t
确实有一个弱点,在某些系统上它不能代表所有有效的指针差异,因此也不能代表std::count
所有预期结果。
As far as I can tell, even in C++03 the standard actually forbade this, maybe by accident. 据我所知,即使在C ++ 03中,该标准实际上禁止了这一点,也许是偶然的。 5.7/6 talks about subtraction possibly overflowing
ptrdiff_t
, just like C does. 5.7 / 6谈论减法可能溢出
ptrdiff_t
,就像C一样。 But table 32 (allocator requirements) says that X::difference_type
can represent the difference between any two pointers, and std::allocator
is guaranteed to use ptrdiff_t
as its difference_type
(20.1.5/4). 但是表32(分配器要求)说
X::difference_type
可以表示任何两个指针之间的差异,并且std::allocator
保证使用ptrdiff_t
作为其difference_type
(20.1.5 / 4)。 C++11 is similar. C ++ 11是类似的。 So one part of the standard thinks that pointer subtraction can overflow
ptrdiff_t
, and another part of the standard says it can't. 因此标准的一部分认为指针减法可以溢出
ptrdiff_t
,而标准的另一部分则认为它不能。
std::count
presumably was designed under the same (possibly defective) assumption as the allocator requirements, that ptrdiff_t
is big enough to express the size of any object and (in general) an iterator's difference_type
can express the count of iterands between any two iterators. std::count
可能是在与分配器要求相同(可能是有缺陷的)假设下设计的, ptrdiff_t
足够大以表示任何对象的大小,并且(通常)迭代器的difference_type
可以表示任意两个迭代器之间的迭代计数。
The return type is typename iterator_traits<InputIterator>::difference_type
which in this particular case happens to be ptrdiff_t
. 返回类型是
typename iterator_traits<InputIterator>::difference_type
,在这种特殊情况下恰好是ptrdiff_t
。
Presumably difference_type
was selected because the maximum number of matching elements in the range would be the iterator difference last - first
. 大概是选择了
difference_type
,因为该范围内的匹配元素的最大数量将是last - first
的迭代器差异last - first
。
Originally std::count
was: 最初
std::count
是:
template <class InputIterator, class EqualityComparable, class Size>
void count(InputIterator first, InputIterator last,
const EqualityComparable& value,
Size& n);
In that function Size
is a template parameter. 在该函数中,
Size
是模板参数。 It can be whatever you like, and it's your responsibility to make sure it's correct. 它可以是你喜欢的任何东西,你有责任确保它是正确的。 It could be the longest type on your platform.
它可能是您平台上最长的类型。
My suspicion is that when the newer form: 我的怀疑是,当更新的形式:
template <class InputIterator, class EqualityComparable>
iterator_traits<InputIterator>::difference_type
count(InputIterator first, InputIterator last,
const EqualityComparable& value);
was added iterator_traits
was already in existence, so re-using the existing type had the advantage that it kept the changes to the standard small and localised, compared to adding another typedef
in iterator_traits
. 添加
iterator_traits
已经存在,因此重新使用现有类型的优势在于,与在iterator_traits
添加另一个typedef
相比,它保持对标准的更改小和本地化。
Doing it this way, using iterator_traits
as opposed to simply using std::size_type
means that every possible iterator gets the option to specify exactly what type should be returned by std::count
. 这样做,使用
iterator_traits
而不是简单地使用std::size_type
意味着每个可能的迭代器都会获得用于指定std::count
应该返回什么类型的选项。 This includes custom iterators which read from a network, or disk, which can use something much larger than either ptrdiff_t
or size_type
and friends. 这包括从网络或磁盘读取的自定义迭代器,它可以使用比
ptrdiff_t
或size_type
和朋友大得多的东西。 (It could be some kind of "BigInt" if needed). (如果需要,它可能是某种“BigInt”)。 It also means that the user isn't responsible for deducing the appropriate type to use though, which can be tricky, precisely because of the custom iterator possibility.
这也意味着用户不负责推断使用的相应类型,这可能很棘手,正是因为自定义迭代器的可能性。
即使计数不能为负数,返回类型也指定为iterator_traits<InputIterator>::difference_type
,两个迭代器之间的差异可以为负数。
If the iterator was an array, it would imply the result is within the range of the array. 如果迭代器是一个数组,则意味着结果在数组的范围内。
For this specific algorithm I can't think of a reason that is interesting. 对于这个特定的算法,我无法想到一个有趣的原因。 For someone using this as a component it may be interesting, though.
对于使用它作为组件的人来说,它可能很有趣。
The page does say that it would do something equivalent . 页面确实说它会做同等的事情。 So for the case of an array it may do something like a direct pointer difference.
因此对于数组的情况,它可能会做类似直接指针差异的事情。 This would be a pretty fast specialization if it were applicable.
如果它适用的话,这将是一个非常快速的专业化。
difference_type
usually denotes the type suitable to denote a distance in an array or similar. difference_type
通常表示适合表示阵列中的距离或类似的类型。 The following wording is from the allocator requirements, but whenever the standard talks about difference_type
it means the same concept: 以下措辞来自分配器要求,但每当标准谈到
difference_type
它意味着相同的概念:
a type that can represent the difference between any two pointers in the allocation model
一种类型,可以表示分配模型中任何两个指针之间的差异
The natural type for this is ptrdiff_t. 这种自然类型是ptrdiff_t。
For the size_type
it says: 对于
size_type
它说:
a type that can represent the size of the largest object in the allocation model.
一种类型,可以表示分配模型中最大对象的大小。
The natural type here is size_t. 这里的自然类型是size_t。
Now for the count of any elements in a range (or an array) does need at least the type suitable to specify the difference last-first
. 现在对于任何元件的一个范围中的计数(或阵列)确实需要至少适合于指定的差的类型
last-first
。 It seems most natural to chose that one. 选择那一个似乎是最自然的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.