我正在尝试为back_inserter
编写一个接收器,以减少扩散代码的std::copy()
命令的数量。
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
template <typename OutputIterator>
class sink
{
public:
sink(OutputIterator out) : _out(out) { }
OutputIterator _out;
};
template <typename OI, typename C>
sink<OI>& operator<<(sink<OI>& s, const C& c)
{
std::copy(c.begin(), c.end(), s._out);
return s;
}
int main(int, const char*[])
{
std::vector<uint8_t> c;
// auto s = sink<std::back_insert_iterator<std::vector<uint8_t>>>(std::back_inserter(c));
auto s = sink(std::back_inserter(c));
s << std::vector<uint8_t>{'F','e','e','d','i','n','g',' ','f','r','o','g','g','i','e','s'};
s << std::string("Hungry hippos");
std::copy(c.begin(), c.end(), std::ostream_iterator<int>(std::cout, ":"));
}
但是这会产生错误:
main.cpp: In function 'int main(int, const char**)':
main.cpp:27:18: error: missing template arguments before '(' token
auto s = sink(std::back_inserter(c));
^
下面的代码可行,但不太理想,因为它看起来比在任何地方都有很多std::copy
函数调用更糟糕。
auto s = sink<std::back_insert_iterator<std::vector<uint8_t>>>(std::back_inserter(c));
如何将提示提供给编译器以自动推断出类型?
最终我想改进系统,所以我可以简单地写一下
sink(out) << reply::stock_reply(reply::bad_request);
其中out
是back_insert_iterator
,stock_reply
给出了预设回复。
答案 0 :(得分:8)
在需要消除歧义的情况下,C ++ 17添加了这个确切的功能以及周围的帮助。它被称为class template argument deduction。
如果这不是一个选项,您可以采用诸如“make”辅助函数之类的解决方法。这就是你的情况(在这里forward
并不是绝对必要的):
template<typename OutputIterator>
sink<std::decay_t<OutputIterator>> make_sink(OutputIterator&& output_iterator)
{
return sink<std::decay_t<OutputIterator>>(std::forward<OutputIterator>(output_iterator));
}
Live demo here。 std::decay_t
使得函数在传递左值时做正确的事。