为什么不将模板参数包推导到函数调用中的多个类型参数? [英] Why won't template parameter pack be deduced to multiple type arguments in function call?

查看:323
本文介绍了为什么不将模板参数包推导到函数调用中的多个类型参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类模板化类型参数和参数包,并且困惑这种类型的类型推导;当写入输出流操作符时,我发现 operator 上的参数包将不匹配模板类的类型和包参数:

I have a class templated on a type parameter and parameter pack, and am confused about type-deduction of this type; while writing an output-streaming operator I discovered a parameter pack on operator<< will not match both the type and pack parameters for the template class:

#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上编译,所以我想我误解了这里的规则。

This fails to compile on both gcc-4.7.2 and clang-3.0, so I guess I'm misunderstanding the rules here.

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

gcc says (where line 16 is the output stream call):

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...>& )
                  ^

$ b b

有人可以告诉我为什么运算符<< 的参数包不能被推导为类型参数 / em>参数包 foo

Could someone please enlighten me as to why the parameter pack for operator<< cannot be deduced to be the type parameter and parameter pack for foo?

推荐答案

具有模板参数包 class ... Ts foo< Ts ...>的参数类型(P)的模板函数。 是根据 foo< int> 的参数类型(A)推导出的。

What is happening is that a template function with a template parameter pack class... Ts, and a parameter type (P) of foo<Ts...> is being deduced against an argument type (A) of foo<int>.

14.8.2.5/9说明:

14.8.2.5/9 says of this:


如果P有一个包含< T& / code>或< i> [it does],则每个参数Pi [ Ts ... ]与相应模板参数列表的对应参数Ai [ int ]进行比较。如果
P的模板参数列表包含不是最后一个模板参数的包扩展,
整个模板参数列表是非推导的上下文。 [包扩展是最后的,所以前面的没有应用] 如果Pi是包扩展[ Ts ... ,则是]
与A( int )的模板参数列表中的每个剩余参数进行比较。每个比较对于由Pi扩展的模板参数包中的后续位置推导
模板参数。

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 ,并且可行。

So class... Ts should be deduced as the one element list int, and consequently the function template should be instantiated with the parameter type const foo<int>&, and be viable.

您的代码格式正确。

更简洁的格式是:

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

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

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

但至少在gcc 4.7.2上失败类似:

but fails similarly on at least gcc 4.7.2 with:

 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 具有不完整类型的进一步垃圾。

C is incorrectly deduced as C = {int, C} (a nonsensical recursion) instead of C = {int}. The broken deduction of C leads to further garbage that S<int, C> has an incomplete type.

这篇关于为什么不将模板参数包推导到函数调用中的多个类型参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆