简体   繁体   English

为什么C ++标准算法“count”会返回difference_type而不是size_t?

[英]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_tsize_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.

相关问题 为什么C ++哈希函数的返回类型为std :: size_t,而不是与平台无关的类型? - Why C++ hash functions' return type is std::size_t, instead of a platform-independent type? size_t仅适用于C ++标准或C标准吗? - Is size_t only in C++ standard or C standard as well? 标准 C++ 库中 size_t 的签名变体 - Signed variant of size_t in standard C++ library C++ 中的 size_t 和 int 有什么区别? - What's the difference between size_t and int in C++? C ++标准是否保证std :: uintmax_t可以保存std :: size_t的所有值? - Does the C++ standard guarantee that std::uintmax_t can hold all values of std::size_t? 为什么C ++数组索引值是带符号的,而不是围绕size_t类型构建的(或者我错了)? - Why are C++ array index values signed and not built around the size_t type (or am I wrong in that)? 为什么不能比较 c++ 中的 int 和 size_t - Why can't compare int and size_t in c++ Why we use pointer to integer for max stl function instead for size_t data type(which is generally use) for array of characters in c++? - Why we use pointer to integer for max stl function instead for size_t data type(which is generally use) for array of characters in c++? 为什么我需要在C ++中使用`size_t`? - Why do I need to use `size_t` in C++? 类型size_t无法解析C ++ eclipse - Type size_t could not be resolve C++ eclipse
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM