3

我以为我会很聪明,并创建接受输出迭代器的成员函数。这样,我可以避免返回集合或通过引用获取集合。例如:

template <typename TOutIterator>
void getHeaderNames(TOutIterator destination);

template <typename TOutIterator>
void getHeaderValues(std::string const& name, TOutIterator destination);

这些函数会将它们的结果写入传入的任何迭代器。这样,我不必担心我是在写入集合、向量还是 ostream。

现在我感觉没那么聪明了。我想让这些函数虚拟化,这样我就可以在测试中删除实现。不幸的是,模板成员函数不能是虚拟的,这是有道理的。

有没有办法让这些函数保持通用(写入任何东西)并允许它们同时是虚拟的?我想避免将所有内容都写入向量只是为了转身并将其写入标准输出或其他内容。

如果我需要更清楚地解释我的情况,请告诉我。

4

3 回答 3

1

您可以使用类型擦除来操作多态迭代器,例如any_iteratorThomas Becker 提出的(后来在 Boost.Range 中实现)。你最终会得到一些类似的东西:

typedef any_iterator<
  std::string, // Value
  Writable,    // Access
  Forward,     // Traversal
> StringOutputIterator; // can represent any output iterator accepting strings

virtual void getHeaders(StringOutputIterator destination);

类型擦除的想法是为一组原本不相关的类型(由于使用模板而在 C++ 中经常发生)拥有一个公共基类。例如std::function,通过允许以类似方式操作函数指针、仿函数或 lambda,将这个习惯用法应用于可调用对象。

于 2012-06-14T15:18:41.063 回答
0

保持它们通用的一种方法,我通常在实践中看到这一点,是两个重载流输出运算符(如果有意义的话)或采用std::ostream&.

当然,这取决于您的具体情况:您是否正在编写迭代器更有意义的算法?或者只是想转储一个对象的内容?

于 2012-06-14T15:20:16.547 回答
0

我遇到了类似的问题,我不想将 Boost 添加到我的项目中......所以我决定根本不使用迭代器。

我最终改用了std::function

void getHeaderNames(std::function<void(std::string)> destination);

void getHeaderValues(std::string const& name, std::function<void(std::string)> destination);

然后,std::back_inserter我提供了一个执行的 lambda ,而不是push_back

std::vector<std::string> v;
getHeaderNames([&](auto name) { v.push_back(std::move(name)); });
于 2018-11-11T08:52:33.510 回答