gpt4 book ai didi

c++ - 为什么不会在函数调用中将模板形参包推导出为多个类型实参?

转载 作者:IT老高 更新时间:2023-10-28 21:57:57 32 4
gpt4 key购买 nike

我有一个在类型参数和参数包上模板化的类,我对这种类型的类型推导感到困惑;在编写输出流操作符时,我在 operator<< 上发现了一个参数包将不匹配模板类的 type 和 pack 参数:

#include <iostream>

template<class T, class... Ts>
struct foo
{ /* ... */ };

template< class... Ts >
std::ostream& operator<<( std::ostream& os, const foo<Ts...>& )
{
return os << 42;
}


int main()
{
std::cout << foo<int>();
}

这在 gcc-4.7.2 和 clang-3.0 上都无法编译,所以我想我在这里误解了规则。

gcc 说(其中第 16 行是输出流调用):

t.cpp:16:28: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/iostream:40:0,
from t.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/ostream:600:5: error: initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = foo<int>]’

clang 说:

t.cpp:16:16: error: invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'foo<int>')
std::cout << foo<int>();
~~~~~~~~~ ^ ~~~~~~~~~~

[--- snip: lots of non-viable candidates from standard library ---]

t.cpp:8:19: note: candidate template ignored: substitution failure [with Ts = <>]
std::ostream& operator<<( std::ostream& os, const foo<Ts...>& )
^

谁能告诉我为什么 operator<< 的参数包不能推论为foo的类型参数参数包?

最佳答案

发生的情况是带有模板参数包的模板函数class... Ts , 参数类型 (P) 为 foo<Ts...>正在根据 foo<int> 的参数类型 (A) 进行推断.

14.8.2.5/9 这么说:

If P has a form that contains <T> or <i> [it does], then each argument Pi [Ts...] of the respective template argument list P is compared with the corresponding argument Ai [int] of the corresponding template argument list of A. If the template argument list of P contains a pack expansion that is not the last template argument, the entire template argument list is a non-deduced context. [the pack expansion is last, so the previous doesnt apply] If Pi is a pack expansion [Ts..., it is], then the pattern of Pi is compared with each remaining argument in the template argument list of A (int). Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by Pi.

所以 class... Ts应该推导出为一个元素列表int ,因此函数模板应使用参数类型 const foo<int>& 进行实例化,并且是可行的。

这是一个编译器错误。您的代码格式正确。

更简洁地说,这是格式良好的:

template<class A, class... B> struct S { };

template<class... C> void f(S<C...>) { }

int main() { f(S<int>()); }

但至少在 gcc 4.7.2 上同样失败:

 error: parameter 1 of ‘void f(S<C ...>) [with C = {int, C}]’
has incomplete type ‘S<int, C>’

C被错误地推断为 C = {int, C} (无意义的递归)而不是 C = {int} . C的破扣导致更多的垃圾 S<int, C>类型不完整。

关于c++ - 为什么不会在函数调用中将模板形参包推导出为多个类型实参?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17277487/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com