我认为我会聪明并创建接受输出迭代器的成员函数。这样,我可以避免返回集合或通过引用获取集合。例如:
template <typename TOutIterator>
void getHeaderNames(TOutIterator destination);
template <typename TOutIterator>
void getHeaderValues(std::string const& name, TOutIterator destination);
这些函数会将结果写入传入的迭代器中。这样,我不必担心我是在写一个集合,向量还是ostream。
现在我感觉不那么聪明。我想将这些函数设置为虚拟,以便我可以在测试中删除实现。不幸的是,模板成员函数不能是虚拟的,这是有道理的。
有没有办法让这些函数保持通用(写入任何东西)并允许它们同时是虚拟的?我想避免将所有内容写入向量,只是为了转向并将其写入标准输出或其他任何内容。
如果我需要更清楚地解释我的情况,请告诉我。
答案 0 :(得分:1)
您可以使用type erasure来操纵多态迭代器,例如any_iterator
proposed by Thomas Becker(以及后来的implemented in 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来将此成语应用于可调用对象。
答案 1 :(得分:1)
我遇到了类似的问题,并且我不想将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)); });
答案 2 :(得分:0)
保持它们通用的一种方法,我通常在实践中看到这一点,是流输出操作符的两个重载(如果有意义)或者采用std::ostream&
。
当然这取决于你的确切情况:你在编写迭代器更有意义的算法吗?或者只想转储对象的内容?