简体   繁体   English

模板成员函数写入输出迭代器

[英]Template Member Function to Write to Output Iterator

I thought I would be smart and create member functions that accepted output iterators. 我以为我会聪明并创建接受输出迭代器的成员函数。 This way, I could avoid returning a collection or taking a collection by reference. 这样,我可以避免返回集合或通过引用获取集合。 For example: 例如:

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

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

These functions will write their results to whatever iterator is passed in. This way, I don't have to worry whether I'm writing to a set, vector or ostream. 这些函数会将结果写入传入的迭代器中。这样,我不必担心我是在写一个集合,向量还是ostream。

Now I don't feel so smart. 现在我感觉不那么聪明。 I want to make these functions virtual so I can stub out the implementation in test. 我想将这些函数设置为虚拟,以便我可以在测试中删除实现。 Unfortunately, template member functions can't be virtual, which makes sense. 不幸的是,模板成员函数不能是虚拟的,这是有道理的。

Is there a way to keep these functions generic (write to anything) and allow them to be virtual at the same time? 有没有办法保持这些函数通用(写入任何东西)并允许它们同时是虚拟的? I want to avoid writing everything to a vector only to turn around and write it to standard out or whatever. 我想避免将所有内容写入向量,只是转向并将其写入标准输出或其他任何内容。

Let me know if I need to explain my situation more clearly. 如果我需要更清楚地解释我的情况,请告诉我。

You could use type erasure to manipulate polymorphic iterators, like the any_iterator proposed by Thomas Becker (and later implemented in Boost.Range ). 您可以使用类型擦除来操作多态迭代器,例如Thomas Becker提出any_iterator (后来在Boost.Range中实现 )。 You would end up with something along those lines: 你最终会得到一些东西:

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

virtual void getHeaders(StringOutputIterator destination);

The idea of type erasure is to have a common base class for a set of otherwise unrelated types (which happen very often in C++, due to the use of templates). 类型擦除的想法是为一组其他不相关的类型(由于使用模板而在C ++中经常发生)具有公共基类。 For instance, std::function applies this idiom to callable objects, by allowing the manipulation of function pointers, functors or lambdas in a similar way. 例如, std::function通过允许以类似方式操作函数指针,仿函数或lambda来将此成语应用于可调用对象。

I faced a similar problem, and I didn't want to add Boost to my project... so I decided not to use iterators at all. 我遇到了类似的问题,我不想将Boost添加到我的项目中......所以我决定不使用迭代器。

I ended up using a std::function instead: 我最终使用std::function代替:

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

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

Then, instead of std::back_inserter , I provide a lambda that executes push_back : 然后,我提供了一个执行push_back的lambda,而不是std::back_inserter

std::vector<std::string> v;
getHeaderNames([&](auto name) { v.push_back(std::move(name)); });

One way to keep them generic, and I usually see this in practice, is two overload a stream output operator (if it makes sense) or take an std::ostream& . 保持它们通用的一种方法,我通常在实践中看到这是两个重载流输出操作符(如果它有意义)或采取std::ostream&

Of course it depends on your exact situation: Are you writing an algorithm for which iterators make more sense? 当然这取决于你的确切情况:你在编写迭代器更有意义的算法吗? Or just want to dump an object's content? 或者只想转储对象的内容?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM