【问题标题】:Misunderstanding variadic templates and template type deduction对可变参数模板和模板类型推导的误解
【发布时间】:2019-10-21 22:33:14
【问题描述】:

我正在使用与此示例类似的代码使用 C++17 进行编译:

#include <iostream>
#include <iterator>

class Foo {};

template <typename... Args,
  typename ostream_type = ::std::basic_ostream<Args...>,
  typename ostreambuf_iterator_type = ::std::ostreambuf_iterator<Args...>>
ostream_type &operator<<(ostream_type &os, const ::Foo f) {
  // Do ostreambuf_iterator_type stuff with 'f' here...
  return os;
}

int main() {
  ::Foo f;
  ::std::cout << f;

  return 0;

}

我发现当我将Args... 应用于ostream_typeostreambuf_iterator_type 的模板参数列表时,模板类型推导失败,但如果我分配char_type 和@987654326 就可以了@来自ostream_type

typename ostreambuf_iterator_type = ::std::ostreambuf_iterator<typename ostream_type::char_type, typename ostream_type::traits_type>>

为什么会这样,::std::basic_ostream::std::ostreambuf_iterator 的模板参数相同?

【问题讨论】:

  • 我已经意识到我可以在函数体中进行更多的推导,我不需要指定迭代器参数,但是这段代码仍然提出了为什么 Args... 没有的问题没有像我预期的那样工作。

标签: c++ variadic-templates variadic-functions template-argument-deduction type-deduction


【解决方案1】:

模板参数推导尝试从函数参数推导出ostream_type。在这样做时,它不受您提供的默认参数的约束。而是简单地忽略默认参数。

ostream_type 将推导出为std::basic_ostream&lt;char&gt;

那么函数参数中的Args就没有剩余了,推断参数包为空。

然后将空的Args 扩展为默认参数ostreambuf_iterator_type = ::std::ostreambuf_iterator&lt;Args...&gt;,这会失败,因为std::ostreambuf_iterator 至少需要一个模板参数。

如果您希望Args 被推导出为模板参数传递给您的函数,您需要在参数中约束模板参数推导:

template <typename... Args,
  typename ostreambuf_iterator_type = ::std::ostreambuf_iterator<Args...>>
auto &operator<<(::std::basic_ostream<Args...> &os, const Foo f) {
  // Do ostreambuf_iterator_type stuff with 'f' here...
  return os;
}

现在推导必须将Args 推导出为os 的模板参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-14
    • 2015-12-09
    • 1970-01-01
    • 1970-01-01
    • 2019-11-29
    • 2018-08-26
    • 1970-01-01
    相关资源
    最近更新 更多