如何让模板推断出其参数

gra*_*eds 7 c++ templates c++11 type-deduction

我正在尝试编写一个接收器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, ":"));
}
Run Code Online (Sandbox Code Playgroud)

但是这会给出错误:

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));
                  ^
Run Code Online (Sandbox Code Playgroud)

下面的代码可以工作但不太理想,因为它看起来比在std::copy任何地方都有很多函数调用更糟糕.

auto s = sink<std::back_insert_iterator<std::vector<uint8_t>>>(std::back_inserter(c));
Run Code Online (Sandbox Code Playgroud)

如何给编译器提示以自动推断出类型?

最终我想改进系统,所以我可以简单地写

sink(out) << reply::stock_reply(reply::bad_request);
Run Code Online (Sandbox Code Playgroud)

在哪里out是a back_insert_iteratorstock_reply给出一个罐头响应.

rub*_*nvb 8

在需要消除歧义的情况下,C++ 17添加了这个确切的功能以及周围的帮助.它被称为类模板参数推导.

如果这不是一个选项,您可以采用诸如"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));
}
Run Code Online (Sandbox Code Playgroud)

现场演示.这std::decay_t是为了让函数在传递左值时做正确的事情.