将迭代器作为函数参数传递 [英] Pass iterator as a function parameter

查看:178
本文介绍了将迭代器作为函数参数传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试编写一个函数,它将对容器的元素求和。这个容器可以是Vector,List,Queue等......这就是我尝试模板的原因。

I try to write a function, which will sum the elements of a container. This container can be Vector, List, Queue, etc... That's why I tried templates.

不幸的是我收到了这个错误:

Unfortunately I get this error:


'C'不是模板

'C' is not a template

资料来源:

#include <iostream>
#include <vector>

using namespace std;

template<class C, typename T>
T sum( C<T>::iterator begin, C<T>::iterator end ) {
    T s = null;

    for (C<T>::iterator it = begin; it != end; it++) {
        s += *it;
    }

    return s;
}

int main()
{
    vector<int> v = {5, 9, 0, 11};

    cout << sum(v.begin(), v.end()) << endl;

    return 0;
}

我错了什么?我该如何解决?

What do I wrong? How should I fix it?

推荐答案

你得到的特殊错误是因为你需要一个模板模板参数:

The particular error you get is because you'd need a template template argument:

template<template <typename> class C, typename T>
//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
T sum( C<T>::iterator begin, C<T>::iterator end )

但是,标准容器通常只有一个模板参数:

However, the standard containers typically have more than just one template argument:

template < class T, class Alloc = allocator<T> > class vector

并且正确编写这样的函数有点不重要。您可以使用可变参数模板参数,或者您可以像标准库那样进行操作,并且只能根据您的需要进行专门化:

and it is a bit non-trivial to write such function correctly. You could use variadic template arguments, or you could do like the standard library does, and only specialize as much as you really need:

// <algorithm>
namespace std {
    template <class RandomAccessIterator>
    void sort (RandomAccessIterator first, RandomAccessIterator last);
}

在您的情况下(假装您的需求不在标准算法库的涵盖范围内)已经):

In your case (pretending that your need is not covered by the standard algorithms library already):

template <typename Iterator>
auto sum(Iterator begin, Iterator end) 
-> decltype(*begin+*begin) // the type of summing two of them
{
    if (begin == end) throw std::logic_error("....");
    auto s = *begin;
    ++begin;
    for (; begin != end; ++begin) {
        s += *begin;
    }
    return s;
}






还有一些差异来自您的原始代码:


There are some more differences from your original code:


  • 新代码不假定定义了null或默认构造函数( T s = null;

  • 不会引入额外的迭代器( it

  • 使用预增量

  • 在begin == end

  • the new code does not assume a null or a default constructor defined (T s = null;)
  • does not introduce additional iterator (it)
  • uses pre-increment
  • throws an exception when begin==end

如果你添加一个 init 参数,你可以使它几乎 noexcept

If you add an init parameter, you can make it almost noexcept:

template <typename Iterator, typename T>
T sum(Iterator begin, Iterator end, T init)
{
    for (; begin!=end; ++begin)
        init += *begin;
    return init;
}

但差不多,因为 init + = * begin 仍然可以抛出。

But only almost, because init += *begin could still throw.

如果您有这样的签名,那么您已经复制了 std的签名: :累积

If you have such signature, you've by the way reproduced the signature of std::accumulate.

这篇关于将迭代器作为函数参数传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆