【问题标题】:How do to have a template deduce its parameters如何让模板推断其参数
【发布时间】:2018-03-29 07:27:53
【问题描述】:

我正在尝试为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);

其中outback_insert_iteratorstock_reply 给出预设响应。

【问题讨论】:

  • 尽可能使用 C++17,它已经添加了这个确切的功能:wandbox.org/permlink/RqYk2MohPJQdb72O 在此之前,C++ 只允许为函数模板扣除模板参数。
  • 不行。我工作的平台仅限于 gcc4.8.4。
  • 那么通常的解决方案是使用一个函数,例如make_shared(将sink实例的构造转换为返回一些sink_class实例的函数模板的调用)。
  • "在此之前,C++ 只允许对函数模板进行模板参数的推导。"我实际上并不知道。谢谢。

标签: c++ c++11 templates type-deduction


【解决方案1】:

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 herestd::decay_t 是为了让函数在传递左值时执行正确的操作。

【讨论】:

  • “让它们在你的课堂上保持静态” 我不明白 OP 如何调用它来推断类型......或者你的意思是 sink&lt;dummy&gt;::make(std::back_inserter(c)) 这看起来很丑(因为虚拟类型)?
  • 我去掉了那个建议,这里确实不正确。
  • 你可能想要sink&lt;decay_t&lt;OutputIterator&gt;&gt;,否则你会保留一个参考 - 所以不是真正的接收器。
  • @Barry 编译器不同意你的观点:coliru.stacked-crooked.com/a/437a11c04a5e16fc。您的评论似乎确实有道理,但似乎我没有遇到您正在考虑的特殊情况。
  • @rubenvb 传入左值而不是右值。
猜你喜欢
  • 1970-01-01
  • 2021-11-05
  • 1970-01-01
  • 2023-04-06
  • 2022-12-02
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 2013-02-18
相关资源
最近更新 更多