为什么 make_reverse_iterator(make_reverse_iterator(it)) 的结果会导致不同的类型?

7
我认为:

我会认为:

static_assert(is_same_v<
    decltype(make_reverse_iterator(make_reverse_iterator(it)))
  , decltype(it)>);

这段代码看起来应该是可以编译的,但实际上却不能。可能有一些原因导致了这个问题。在写模板时,这可能会导致生成的代码更大。

实现这并不难:

template <typename T>
T make_reverse_iterator(reverse_iterator<T> it) {
  return it.base();
}

如果在调用模板函数时进行双倍或更多次反转,尤其是在该函数使用与其调用的相同的reverse_iterator递归调用自身时,会导致较小的二进制文件大小,而不会通过其他特殊化复杂化代码。


@FrançoisAndrieux,是的,这就是我的意思。为什么它不是必需的?它并不难实现,这样会更清晰,也会导致更小的二进制文件。 - Adrian
@Adrian 随意提交建议 - Mike Vine
@Adrian 通常一个功能不存在的原因是因为没有人提出这个功能的需求,所以没有提案存在,或者提案被拒绝了。我猜测没有人提出这个功能是因为它似乎并不是很必要。如果你愿意付出努力,你可以尝试撰写一份提案。 - François Andrieux
@FrançoisAndrieux,我想我只是认为这种事情应该很明显。 - Adrian
嗯...如果指向原始范围的最后一个元素,则无法对反转的反转进行递增操作...因为它是中间的“begin”? - Swift - Friday Pie
显示剩余4条评论
1个回答

1
有一个简单的问题可以解释这个问题:make_reverse_iterator的返回值是reverse_iterator吗?
可以看到,reverse_iterator不仅仅是一个向后运行的迭代器,它是一种类型。或者更准确地说,它是一个生成一系列类型的模板。而且这个模板需要提供某些行为;这些行为就是使它成为反向迭代器的原因。
而这种行为并不是非反向迭代器类型必须提供的。reverse_iterator>不同于I。例如,您无法获取I的基础内容。
如果用户调用make_reverse_iterator,则他们有权期望会得到一个具有该模板提供的所有功能和特权的reverse_iterator。返回其他任何内容都等同于欺骗用户。
你似乎想要的是make_iterator_go_backwards:一个返回一些向后遍历序列的迭代器类型的函数。这是一个有效的需求。

但那个东西并不是拼写为make_reverse_iterator。如果你有一个名为make_some_type的函数,它应该返回some_type


是的,它是一种具有相关行为附加的类型。当您调用 make_reverse_iterator 时,开发人员可以期望它生成一个 reverse_iterator 模板类型,但更有用的是,他们可以期望它生成一个自反类型。这两种类型都是迭代器,具有从原始迭代器反转的语义,当对其进行添加、减法和索引操作时,但自反类型可以使代码更对称,从而更易于阅读和证明代码。这不是在撒谎,而是简化开发人员的生活,以及那些之后阅读代码的人。 - Adrian
可以使用一个名为 make_iterator_go_backwards 的函数,但在我看来,它缺乏优雅。 - Adrian
@Adrian:“这不是说谎。”函数名称清楚地表明它制作了“reverse_iterator”。如果它没有制作“reverse_iterator”,那么函数名称就是一个谎言。这就像说,如果你只给它一个值,那么“make_tuple”不应该返回一个“tuple”,因为这样会以某种方式“让开发人员的生活更轻松”。 - Nicol Bolas
按照同样的逻辑,make_iterator_go_backwards 将会生成一个 iterator_go_backwards 类型。最好不要使用前缀 make_ - Adrian
@Adrian:但是没有“iterator_go_backwards”类型。有一个tuple类型,一个reverse_iterator类型,shared_ptr类型等等。以make_*命名的函数应该生成该类型,因为...那就是它们的名称。 - Nicol Bolas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接