C ++返回多个项目

时间:2012-09-25 15:20:59

标签: c++ iterator return-value

我正在用C ++设计一个从HTML页面中提取URL的类。我正在使用Boost的正则表达式库为我做繁重的工作。我开始设计一个类,并意识到我不想限制URL的存储方式。一种选择是通过引用接受std::vector<Url>并在其上调用push_back。我想避免强迫我班级的消费者使用std::vector。所以,我创建了一个使用目标迭代器的成员模板。它看起来像这样:

template <typename TForwardIterator, typename TOutputIterator>
TOutputIterator UrlExtractor::get_urls(
    TForwardIterator begin,
    TForwardIterator end, 
    TOutputIterator dest);

我觉得我过于复杂。我喜欢用C ++编写相当通用的代码,我很难锁定我的接口。但后来我陷入了这些困境,我试图模仿一切。此时,阅读代码的人没有意识到TForwardIterator正在迭代std::string

在我的特殊情况下,我想知道这种通用是否是一件好事。你什么时候开始使代码更明确?是否有一种标准方法可以从函数中获取值?

4 个答案:

答案 0 :(得分:3)

是的,它不仅很好,而且是一个非常好的设计。模仿这种方式是大多数标准库算法的工作方式,如std::fillstd::copy;它们可以与迭代器一起使用,以便您可以填充已包含元素的容器,您可以使用空容器并使用std::back_inserter填充数据。< / p>

这是一个非常好的IMO设计,并充分利用了模板和迭代器概念的强大功能。

你可以像这样使用它(但你已经知道了):

std::list<Url> l;
std::vector<Url> v;

x.get_urls(begin(dat1), end(dat1), std::back_inserter(l));
y.get_urls(begin(dat2), end(dat2), std::back_inserter(v));

我觉得你害怕使用模板,它们不是“正常”的C ++,或者它们应该被避免并且是臃肿的东西。我向你保证,它们是非常正常的,并且是一种强大的语言功能,没有其他语言(我知道),所以只要适合使用它们,就可以使用它们。在这里,这是非常合适的。

答案 1 :(得分:2)

在我看来你的界面错误。

已经有从迭代器到容器的复制算法。在我看来,你的班级正在提供一个网址流(不依赖于修改其来源)。因此,您真正需要的是通过迭代器(转发迭代器)公开内部数据的方法,因此您需要提供begin()和end()。

UrlExtractor             page(/* Some way of constructing page */);
std::vector<std::string> data;

std::copy(page.begin(), page.end(), std::back_inserter(data));

我只提供以下界面:

class UrlExtractor
{
    ...... STUFF
    iterator begin(); 
    iterator end();
};

答案 2 :(得分:0)

是的,你太一般了。模板的要点是您可以生成行为不同的函数的多个副本。您可能不希望这样,因为您应该选择一种表示URL的方法并在整个程序中使用它。

你这么做:

typedef std::string url;

这允许您在将来更改用于网址的类。

也许std::vector在其中实现了与push_back()的某些界面,您的方法可以引用该界面(back_inserter?)。

答案 3 :(得分:0)

如果不了解实际的用例场景,很难说,但是 一般来说,避免模板(或任何其他不必要的模板)更好 复杂性)除非它实际上给你买东西。最明显的 这里的签名是:

std::vector<Url> UrlExtractor::get_urls( std::string const& source );

是否有任何可能的情况,您必须解析任何事情 但std::string? (如果你也支持输入,可能会有 迭代器。但实际上,如果你要解析,那么来源就是 std::stringstd::istream&。除非你真的想要 支持后者,只需使用std::string。)当然还有客户端代码 可以使用返回的向量执行任何操作,包括追加 它到另一种类型的集合。

如果返回std::vector的费用确实成为问题,那么您 可以将std::vector<Url>&作为参数。我什么都看不到 合理的情况,任何额外的灵活性会给你带来很多, 像get_urls这样的函数可能相当复杂,而且 不是那种你想要放在标题中的东西。