C++类型的去引用迭代器

C++ type of dereferenced iterator

本文关键字:引用 迭代器 类型 C++      更新时间:2023-10-16

我试图制作一个函数,对std::vector:的所有元素求和

template<typename IteratorT>
auto sum(IteratorT first, IteratorT last) -> decltype(*first) {
    decltype(*first) sum = 0;
    for (; first != last; ++first)
        sum += *first;
    return sum;
}

我得到了这个错误:

无法从"int"转换为"int&"

然后经过一些研究,我发现了这个:std::iterator_traits<IteratorT>::difference_type。将我的代码更改为:

template<typename IteratorT>
auto sum(IteratorT first, IteratorT last) -> typename std::iterator_traits<IteratorT>::difference_type {
    std::iterator_traits<IteratorT>::difference_type sum = 0;
    for (; first != last; ++first)
        sum += *first;
    return sum;
}

它确实起了作用,但我不知道为什么,也不知道这是否是一个好的解决方案。总之,我有两个问题:

1) 为什么decltype(*first)返回int&而不是我预期的int
2) std::iterator_traits<IteratorT>::difference_type之前的typename到底做了什么?如果我删除它,为什么sum函数不起作用?

有两个主要问题:

  • 去引用迭代器的类型是引用,它可以是const,对于std::vector,它可以与向量的项类型非常不同。

  • 当项目类型为例如bool时,您不希望在bool类型中求和。

以下代码是一个解决方案:

#include <iterator>     // std::iterator_traits
template< class Iter >
auto sum( Iter first, Iter last )
    -> decltype( typename std::iterator_traits<Iter>::value_type() + 0 )
{
    decltype( typename std::iterator_traits<Iter>::value_type() + 0 ) sum = 0;
    for (; first != last; ++first)
        sum += *first;
    return sum;
}
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
#define ITEMS( x ) begin( x ), end( x )
auto main()
    -> int
{
    vector<double> const v1 = {3, 1, 4, 1, 5};
    cout << sum( ITEMS(v1) ) << endl;
    vector<bool> const v2 = {0, 1, 1, 0, 1};
    cout << sum( ITEMS( v2) ) << endl;
}

请注意,您不必定义自己的sum:有std::accumulate

decltype(*first)返回一个引用,否则我们将无法编写类似的东西

*first = 7;

关于difference_type,还不清楚你想做什么。需要单词typename来告诉编译器所谓的依赖类型(通常情况下是::之后的任何类型)是模板而不是值。

试试这个:

#include <type_traits>
template <
    typename Iter,
    typename Ret = typename std::decay<decltype(*std::declval<Iter>())>::type>
Ret f(Iter first, Iter last)
{
    Ret sum {};
    for (; first != last; ++first) { sum += *first; }
    return sum;
}

您做了一件随机的事情,它是随机工作的。distance_type与您的问题无关,它是一种表示测量两个迭代器之间距离的结果的类型。由于它通常是一个整数类型,所以您最终可以在算术中使用它。

最初的问题是由于这样一个事实,即取消引用迭代器会返回一个指向底层对象的(const)指针,这是需要的,这样像这样的代码

*it = 10;

将执行您希望它执行的操作(或编译const迭代器失败)。

并且typename关键字是必需的,但这里已经有足够多的typename用法重复了。