【问题标题】:Declare a template function which receives two generic iterator as parameters声明一个接收两个泛型迭代器作为参数的模板函数
【发布时间】:2017-12-31 18:54:25
【问题描述】:

我需要创建一个函数,它从一个容器的开头和结尾接收迭代器。然后它应该在控制台中显示内容。

我的问题是我不知道如何声明迭代器以便它可以与任何类型的容器一起使用

这就是我所做的:

template <class T>
void print(typename iterator<T> &beg, typename iterator<T> &end) {
    while (beg != end) {
        cout << *beg << endl;
        beg++;
    }
}

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    std::iterator 类实际上只是为了方便;标准中没有任何内容要求所有迭代器都从它继承。此外,std::iterator 没有虚拟方法,因此它与在 Java 中使用 Iterator&lt;T&gt; 几乎不同,在 Java 中调用 next() 方法将调用 适当的 @ 987654325@。您希望采用通用类型T,而不仅仅是std::iterator,以便编译器在编译时解析operator++operator* 的正确重载。

    template <typename T>
    void print(T iter, const T& end) {
        // Taking the first argument by value ensures that
        // we don't modify the caller's variables
        while (iter != end) {
            cout << *iter << endl;
            ++iter;
        }
    }
    

    这适用于任何前向迭代器,这是您 99% 的时间都在处理的。

    【讨论】:

    • 稍微简化代码的建议:void print (T iter, const T &amp; end)。如果您收到第一个参数作为可修改副本,则可以避免以下T iter = beg;
    • 谢谢。您将如何在 main 中调用该函数?例如,如果您想将其与向量或列表一起使用
    • 与您打算称呼您的方式相同。 print(vec.begin(), vec.end())。编译器应该能够为您推断模板类型。
    • @Emiliano:你为什么“需要”这样做?
    • @SilvioMayolo:我认为你的措辞听起来好像它的非虚拟析构函数是不继承它的原因之一。我现在知道您不是故意的,但是如果您的目的是为 Java 初学者澄清一些事情,那么您应该重新考虑措辞。
    【解决方案2】:

    我需要创建一个从一开始就接收迭代器的函数 和一个容器的末端。

    看看标准函数是怎么做的,例如std::find

    template< class InputIt, class T >
    InputIt find( InputIt first, InputIt last, const T& value );
    

    观察:

    • InputIt 不需要从(现已过时的)std::iterator 类或任何其他类继承。除了其他优点外,这还允许函数与数组一起使用。
    • 开始和结束使用相同的迭代器类型。
    • 迭代器是passed by value
    • 模板参数未指定迭代器的值类型。

    只需在您自己的代码中完全照做,就可以了:

    #include <iostream>
    #include <vector>
    
    template <class Iterator> // not T
    void print(Iterator beg, Iterator end) {
        while (beg != end) {
            std::cout << *beg << '\n';
            beg++;
        }
    }
    
    int main() {
        std::vector<int> const vec = { 1, 2, 3 };
        int const array[] = { 1, 2, 3 };
        using std::begin;
        using std::end;
        print(begin(vec), end(vec));
        print(begin(array), end(array));
    }
    

    【讨论】:

    • 非常感谢您的观察和示例,它们对我帮助很大
    • 我建议添加一个解释,为什么迭代器通常是按值传递的,即使函数没有修改它们。一种常见的模式是将只读参数声明为 对 const 的引用,这在迭代器的情况下大部分时间都不会这样做。我知道答案,其他读者可能不知道。
    猜你喜欢
    • 2011-06-30
    • 1970-01-01
    • 2020-09-28
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多