自定义迭代器中distance_type的目的 - std::d istance(first, last) 将返回错误的
The purpose of the distance_type in a custom iterator - std::distance(first, last) will return a wrong result, if first and last are too far way
我想为自定义类实现一个迭代器
template</*...*/>
class foo
{
public:
using value_type = /* depends on template parameters */;
using size_type = /* depends on template parameters */;
class iterator
: public std::iterator<std::random_access_iterator_tag, value_type, /* some suitable difference_type compatible to size_type */>
{
public:
iterator(foo& bar, size_type i)
: m_bar(bar), m_i(i),
m_dereferenceable(i != bar.size())
{ }
private:
foo& m_bar;
size_type m_i;
bool m_dereferenceable;
};
size_type size() const { /* ... */ }
value_type operator[](size_type) { /* ... */ }
};
并想知道我应该如何实施operator+=(difference_type)
.我已经将difference_type
定义为对我来说完全有意义的std::make_signed_t<size_type>
原因。
关键的一点是:我认为将m_i
定义为类型 size_type
是合理的,确保其值被固定为[0, m_bar.size()]
并使用标志m_dereferenceable
来处理具有m_i == 0
的iterator
递减的情况。
这有点复杂,如果我将m_i
类型更改为签名类型difference_type
,一切都会更容易。但是,如果m_bar
的大小正在利用整个size_type
范围,这将阻止我迭代整个范围。
现在,我意识到(例如(std::distance
的返回类型是 difference_type
。一方面,这是合理的,因为我们可能会有负距离。另一方面,如果m_bar
的大小正在利用整个size_type
范围,std::distance
可能会返回错误的结果。
所以,问题是:请记住(例如(
std::distance
可能会返回错误的结果,如果我将m_i
定义为类型size_type
,我是否应该简单地使用difference_type
代替(并从更容易的实现中受益(?
编辑:让我强调以下几点:假设我们有一个vector x
vector = std::vector</* ... */>
并执行x.resize(std::numeric_limits<vector::size_type>::max())
。
由于d = std::distance(x.begin(), x.end())
的类型是vector::difference_type
的,s = x.size()
的类型是vector::size_type
的,我很好奇d
是否会等于s
。
这个问题不是关于vector
,而是一个关于size_type
、difference_type
的整个概念以及它们对迭代器的目的的问题。
请忽略任何技术问题(内存处理等(,并将size_type
视为"复杂的东西"(即对"大小"表示的理解的抽象(。
显然,d
必须是有符号类型,因为我们可能有负距离。当然,我可以想到一些技术问题,这些问题阻止了标准保证difference_type
对象必须能够存储size_type
对象。但是由于STL是关于泛型编程的,我很惊讶。
你应该知道,size_type
和difference_type
只是容器分配器或迭代器自己的typedef的typedef。它们与向量本身完全无关。
除此之外,我认为你从整体上想得太多了。 size_type
和difference_type
是两种概念上不同的类型:
difference_type: 有符号整数类型,表示序列中任意两个元素的地址之差
size_type: 表示序列长度的无符号整数类型
每当使用返回其中任一类型的函数时,它们都会返回与其定义一致的值。有了std::distance
你真的找到了容器的尺寸吗?不,您正在发现两个迭代器之间的区别。使用std::size
,您没有发现迭代器之间的任何差异,您正在检索一个应该具有逻辑意义的值,一个表示容器大小的unsigned
整数类型。这只是比返回signed
类型的更好表示形式,如您所知,容器的长度将始终为正数。
因此,您可以侥幸使用difference_type
,毕竟您将始终能够安全地使用std::distance
计算容器的大小。
但是你应该吗?
size_type
只是无符号difference_type
的表示形式。仅此而已,只是保证能够保存代表容器大小的值。
判决
你可以少打字,从代码中省略size_type
,但我强烈建议不要这样做。这是标准的一部分,在逻辑上是有意义的。当你计算两个对象的差值时,结果必须能够处理负数,但大小永远不会有这个问题,那么为什么要将其定义为signed
。
- C++算法标头中,为什么要使用 "!(val < *first)" ?
- 迭代嵌套映射与范围为循环:没有名为"first"的成员
- 为什么 std::set.erase(first, last) 会影响从中获取 (first, last) 的容器?
- std::adjacent_find(last, last) 是未定义的吗?
- 如何理解"Temporary objs are destroyed as the last step in evaluating the full-expression"?谁能用一些简单的例子来说明这
- 为什么Eigen不能解析内置符号?(all、last、seq等)
- 为什么 std::d istance() 对于 std:list:<int>:itrator 在 last 在 first 之前时不返回负数?
- c std :: vector迭代器构造函数,first == last
- QSqlQuery last 不起作用
- 如何声明pair<int,int>::first
- 自动,错误:MAP ITERATOR没有名为“ First”的成员
- "Node<T*> *first"和"Node<T> *first"有什么区别?
- 如何从unordered_set获取"last"元素?
- 为什么 std::find_if(first, last, p) 不通过引用获取谓词?
- 我怎样才能保持'first'和'second'用结构替换 std::p air?
- 为什么"begin/end"与"first/last"的差异?
- 自定义迭代器中distance_type的目的 - std::d istance(first, last) 将返回错误的
- 创建一个算法,要求用户输入两个正数,将它们称为 "first" 和 "last" ,并打印第一个正数之间的所有数字的总和
- container.erase(first,last),其中first == last在STL容器中
- 如何使用一对迭代器[first, last]在模板中创建容器