2011-07-15 52 views
0

参考this answer,第二个代码块。我的问题是:返回std :: list通过迭代器不使用模板

如果我知道我将只处理std::lists<int>,并且只有<int>。 有没有一种方法可以在不使用模板的情况下编写此代码(第二个代码块和第三个代码块),以及如注释中所建议的那样不通过引用传递列表?你能把它展示给我吗?

我认为这是有道理的,以避免使用模板,如果实现只涵盖一种单一类型的权利? (还是我太懒了?)

回答

4

这是我的答案!

您可以将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<std::list<int> >,即使在typedef中也是如此。从代码中可以看出,避免使用模板不是懒惰,因为您不必提及类型,所以实际上编写模板的文本更少。但是,如果由于某种原因,你想要去限制,它的功能只能用于列表,并且只能附加到列表的后面,那么你可以继续。

+0

你太棒了!并感谢您的澄清。同时我已经在我的代码中实现了你的第一个例子,在这个答案之后,我不认为我会改变它。如果你想要,我可以打开另一个问题,但是,你可以告诉关于'*(out ++)'部分吗?这是什么构造?我在哪里可以读到它?只是典型的迭代器语法? –

+1

@quiuquio:是的,这只是写入输出迭代器的习惯用法。需要输出迭代器支持它(24.1.2,表73),但它或多或少等于'* out = i; ++ out;' - 将值赋给解除引用的迭代器,然后递增它以准备下一个值。我说“或多或少”,因为就迭代器接口而言,它具有相同的定义含义,但实际上并没有什么能够阻止迭代器对后增量和预增量有不同的副作用,或者通过分配复制与原创,所以它不完全相同。 –

+0

哦,和* reason是迭代器的成语,是迭代器被设计为指针的泛化。使用输出迭代器的语法与使用指针填充数组相同 - 写入当前元素,然后递增。更多的object-y API可能只有一个函数调用,它会一次写入一个值并前进,但是指针不会是迭代器,因此C++不会这样做。 –