何时使用迭代器的`value_type`?

7

我试图理解什么时候会使用iterator::value_type。因为,所有迭代器的运算符似乎都只使用iterator::pointeriterator::reference

问题:iterator::value_type是否真正被用到了?

额外问题:一个继承自

std::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t, bool*, bool&>

提出一些语义问题?

编辑:为了理解我提出这个问题的原因,是因为我正在为一个类型编写迭代器,其中pointerreference是代理类。


关于EDIT,在这种情况下,将value_type作为单独的typedef显然是有用的,因为remove_reference_t<decltype(*begin)>不再是底层值的类型,而是代理的类型。 - vsoftco
1个回答

8

我认为它适用于通用代码。假设您正在编写一个在C++11中对范围求和的通用函数。您可以这样编写:

template<typename It>
auto sum(It begin, It end) -> typename It::value_type
{
    typename It::value_type _sum{}; 
    // compute the sum
    return _sum;
}

在C++14中,我想不到一个真正好的用途,因为您可以在函数返回上使用auto类型推导。当然,您可以使用decltype(*begin),但使用value_type看起来更整洁、更优雅。
编辑:如@Luc Danton在评论中提到的那样,使用decltype(*begin)大多数情况下会产生一个引用,所以您需要使用std::remove_reference,这使得它看起来相当丑陋。因此,value_type非常方便。

2
如果It是例如std::vector<int>::iterator,那么decltype(*begin)int&,它更对应于reference而不是value_type - Luc Danton
2
@LucDanton 而且它甚至不能保证返回值类型,因为原则上迭代器可以通过代理而不一定是指针实现。 - vsoftco
请注意,当我说“引用(reference)”时,我指的是std::iterator_traits<It>::reference,它不一定是引用类型(令人困惑)。它对应于*it的类型(对于适当的it),因此与decltype(*begin)有关。 - Luc Danton
是的,你说得对,我也意识到了这一点,这就是为什么我也评论了代理版本,在这种情况下,引用只是一个代理,你可以通过 operator= 写入。 - vsoftco
2
使用 std::iterator_traits<It>::value_type 似乎比 It::value_type 更好,因为它也处理指针。 - Jarod42

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