我正在使用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_type
和ostreambuf_iterator_type
的模板参数列表时,我发现模板类型推导失败,但是如果我分配了{ {1}中的{1}}和char_type
中的traits_type
。
ostream_type
为什么typename ostreambuf_iterator_type = ::std::ostreambuf_iterator<typename ostream_type::char_type, typename ostream_type::traits_type>>
和::std::basic_ostream
的模板参数相同?
答案 0 :(得分:3)
模板自变量推导尝试从函数自变量推导ostream_type
。这样做不受您提供的默认参数的约束。而是简单地忽略了默认参数。
ostream_type
将被推导为std::basic_ostream<char>
。
然后,根据函数参数中的Args
,什么都没有剩下,并且推导出参数包为空。
然后将空的Args
扩展为默认参数ostreambuf_iterator_type = ::std::ostreambuf_iterator<Args...>
,该参数失败,因为std::ostreambuf_iterator
需要至少一个模板参数。
如果要将Args
推导为传递给函数的std::basic_ofstream
的模板参数,则需要在参数中限制模板参数的推导:
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
的模板参数。