【问题标题】:Returning std::list trough an iterator NOT using templates通过不使用模板的迭代器返回 std::list
【发布时间】:2011-07-15 12:24:44
【问题描述】:

引用this answer,第二个代码块。我的问题是:

如果我知道我将只处理std::lists<int>,并且只处理<int>。 有没有办法在不使用模板并且不按照 cmets 中的建议通过引用传递列表的情况下编写这个(第二个块和第三个块)?可以给我看看吗?

如果实现只涵盖一种类型,我认为避免使用模板是有意义的,对吗??? (还是我太懒了?)

【问题讨论】:

    标签: c++ stdlist


    【解决方案1】:

    这就是我的答案!

    您可以将std::back_insert_iterator<std::list<int> > 传递给带有或不带有模板的函数。秘密地,您仍然通过引用传递列表,因为迭代器本身持有指向容器的引用或指针。

    typedef std::back_insert_iterator<std::list<int> > OutputIterator;
    
    void getInts(OutputIterator out) {
        for (int i = 0; i < 10; ++i) {
            *(out++) = i;
        }
    }
    

    然后调用者这样做:

    std::list<int> l;
    getInts(std::back_inserter(l));
    

    back_inserter 是一个函数模板,back_insert_iterator 是一个类模板的意义上,你仍然在“使用模板”,但同样list 也是如此。这样您就无需编写任何自己的模板。

    我不同意,如果你只对一种类型感兴趣,那么避免使用模板必然是有意义的——C++ 模板的副作用是通过模板参数推导进行类型推断,这意味着你不必写出荒谬的东西像 std::back_insert_iterator&lt;std::list&lt;int&gt; &gt; 这样的类型,甚至在 typedef 中出现一次。从代码中可以看出,避免模板并不是懒惰,实际上编写模板的文本更少,因为您不必提及类型。但是,如果出于某种原因您想限制该功能仅适用于列表,并且只能附加到列表的后面,那么您可以继续。

    【讨论】:

    • 你太棒了!并感谢您的澄清。同时,我已经在我的代码中实现了你的第一个示例,在这个答案之后,我认为我不会再更改它了。如果您愿意,我可以提出另一个问题,但是,您能谈谈*(out++) 部分吗?这是什么构造?我在哪里可以读到它?只是典型的迭代器语法?
    • @quiuquio:是的,这只是写入输出迭代器的习惯用法。这是输出迭代器支持它的要求(24.1.2,表 73),但它或多或少等同于 *out = i; ++out; - 将值分配给取消引用的迭代器,然后将其递增以准备下一个值。我说“或多或少”,因为就迭代器接口而言,它具有相同的定义含义,但实际上并没有什么可以阻止迭代器对后增量和预增量或通过分配具有不同的副作用复制与原始,因此并不完全相同。
    • 哦,迭代器的惯用语原因是迭代器被设计为指针的泛化。使用输出迭代器的语法与使用指针填充数组的语法相同 - 写入当前元素,然后递增。一个更加面向对象的 API 可能有一个函数调用,它会写入一个值并一次性向前推进,但是指针不会是迭代器,所以 C++ 不会那样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    • 2023-03-05
    • 2011-09-07
    • 2021-05-09
    • 2020-12-02
    • 1970-01-01
    相关资源
    最近更新 更多