当参数是函数参数包时,在部分排序期间导出模板参数 [英] Deducing template arguments during partial ordering when parameters are function parameter pack

查看:112
本文介绍了当参数是函数参数包时,在部分排序期间导出模板参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


N4527 14.8.2.4 [temp.deduct.partial]



3用于确定排序的类型取决于上下文部分排序完成:



(3.1) - 在函数调用的上下文中,使用的类型是函数调用具有参数的那些函数参数类型。 / p>

(3.2) - 在调用转换函数的上下文中,使用转换函数模板的返回类型。



(3.3) - 在其他上下文(14.5.6.2)中使用函数模板的函数类型。



4从参数模板来自参数
模板的相应类型用作 P A 的类型。



8如果 A 从函数参数包转换而来, P 不是参数包,类型扣除失败。
否则,使用结果类型 P A ,然后按14.8中所述完成扣除。 2.5。如果 P
是函数参数包,则参数模板的每个剩余参数类型的类型 A
,与函数参数包的declarator-id的类型 P 相比。每个比较推导
模板参数用于由函数
参数包扩展的模板参数包中的后续位置。如果对给定类型的扣除成功,则来自参数模板的类型被认为是
,其至少与参数模板中的类型相同。
[示例:




  template< class ... Args> void f(Args ... args); //#1 
template< class T1,class ... Args> void f(T1 a1,Args ... args); //#2
template< class T1,class T2> void f(T1a1,T2a2); //#3

f(); // calls#1
f(1,2,3); // calls#2
f(1,2); // calls#3;非可变模板#3比可变参数模板#1和#2专用的
//更多

为什么 f(1,2,3); 来电#2?





1这是什么语境?



从#1转换为 void(U) void(U ...) U 表示唯一类型)


14.5.6.2 [temp.func.order ] / p3



要生成转换的模板,对于每个类型,非类型或模板模板参数(包括
模板参数包(14.5.3) )合成一个唯一的类型,值或类模板
,并在模板的函数类型中为该参数的每次出现替换它。


3在扣除中使用的 P A 的类型是什么?例如

 模板< class T> void f(T); 
int a = 1;
f(a); // P = T,A = int


解决方案


为什么 f(1,2,3); 调用#2?


< blockquote>

问题中有很多问题(每个问题都有一个问题!),所以我会坚持那个问题。首先,我们执行模板扣除。 #3失败,但#1和#2成功:

  template< class ... Args> 
void f(Args ... args); //#1,其中Args = {int,int,int}
template< class T1,class ... Args>
void f(T1 a1,Args ... args); //#2,with T1 = int,Args = {int,int}

int 按值,所以在重载解析中的所有正常tiebreaker无法解决模糊。所以我们到最后一个:


给定这些定义,一个可行的函数 F1 被定义为比另一个可行函数更好的函数 F2 如果对于所有参数 i ,ICS < i ( F1 )不是ICS i F2 ),然后

- [...]

- F1 F2 是函数模板专用化, F1 的函数模板比​​ F2 根据14.5.6.2中描述的部分排序规则。


规则是:



步骤1 :综合类型[temp.func.order]:


为了产生转换的模板,对于每个类型,非类型或模板模板参数(包括其
模板参数包(14.5.3))分别合成唯一的类型,值或类模板


因此,我们有:

  void f(Pack1 ... args); //#1 
void f(U2 al,Pack2 ... args); //#2

步骤2 :按[temp .deduct.partial]。我们所处的上下文是一个函数调用,所以我们使用函数调用具有参数的类型。



首先,我们尝试从#1推导#2。也就是说,我们尝试与(Pack1 ...)匹配( T1,Args ... )。第一部分是 P = T1,A = Pack1 ... 。我们有:


如果A是从函数参数包转换而来的,而P不是参数包,则类型扣除失败。


因此从#1推导#2失败,因此参数 Args ... 至少与 T1,Args ... 相同。



接下来,我们尝试从#2推导出#1。也就是说,我们尝试将(Args ...)(U2,Pack2 ...)匹配。成功,因此 T1,Args ... 至少与 Args ... 相同。 >

由于#2至少与#1和#1一样专业,至少不像#2那样专业,我们可以说#2更专业:


函数模板 F 至少与函数模板一样专门 G if,对于用于
的每对类型,确定排序, F 的类型至少与 G F 更专业
G 如果 F G G 至少与 F


更专业的模板是首选,因此我们称之为#2。


N4527 14.8.2.4 [temp.deduct.partial]

3 The types used to determine the ordering depend on the context in which the partial ordering is done:

(3.1) — In the context of a function call, the types used are those function parameter types for which the function call has arguments.

(3.2) — In the context of a call to a conversion function, the return types of the conversion function templates are used.

(3.3) — In other contexts (14.5.6.2) the function template’s function type is used.

4 Each type nominated above from the parameter template and the corresponding type from the argument template are used as the types of P and A.

8 If A was transformed from a function parameter pack and P is not a parameter pack, type deduction fails. Otherwise, using the resulting types P and A, the deduction is then done as described in 14.8.2.5. If P is a function parameter pack, the type A of each remaining parameter type of the argument template is compared with the type P of the declarator-id of the function parameter pack. Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack. If deduction succeeds for a given type, the type from the argument template is considered to be at least as specialized as the type from the parameter template. [ Example:

template<class... Args>           void f(Args... args);        // #1
template<class T1, class... Args> void f(T1 a1, Args... args); // #2
template<class T1, class T2>      void f(T1 a1, T2 a2);        // #3

f();        // calls #1
f(1, 2, 3); // calls #2
f(1, 2);    // calls #3; non-variadic template #3 is more
            // specialized than the variadic templates #1 and #2

Why f(1, 2, 3); calls #2?

I need more details including:

1 Which context is it?

2 What are the transformed froms?
e.g. the transformed from of #1 is void (U) , void (U...) or other form?(U means an unique type)

14.5.6.2 [temp.func.order]/p3

To produce the transformed template, for each type, non-type, or template template parameter (including template parameter packs (14.5.3) thereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template.

3 What are the types of P and A used in deduction? e.g

template <class T> void f(T);
int a = 1;
f(a);//P = T, A = int

解决方案

Why f(1, 2, 3); calls #2?

There's a lot of questions in your question (one question per question please!), so I will stick to that one. First, we perform template deduction. #3 fails, but #1 and #2 succeed:

template<class... Args>
void f(Args... args);        // #1, with Args = {int, int, int}
template<class T1, class... Args> 
void f(T1 a1, Args... args); // #2, with T1 = int, Args = {int, int}

Both functions take three ints by value, so all the normal tiebreakers in overload resolution fail to resolve the ambiguity. So we get to the very last one:

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then
— [...]
F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.6.2.

The rules are:

Step 1: synthesize types [temp.func.order]:

To produce the transformed template, for each type, non-type, or template template parameter (including template parameter packs (14.5.3) thereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template.

So we have:

void f(Pack1... args);         // #1
void f(U2 a1, Pack2... args);  // #2

Step 2: perform deduction as described in [temp.deduct.partial]. The context we're in is a function call, so we use the types for which the function call has arguments.

First, we try to deduce #2 from #1. That is, we try to match (T1, Args...) against (Pack1...). The first part is then P = T1, A = Pack1.... We have:

If A was transformed from a function parameter pack and P is not a parameter pack, type deduction fails.

So deducing #2 from #1 fails, so the argument Args... is not at least as specialized as T1, Args....

Next, we try to deduce #1 from #2. That is, we try to match (Args...) against (U2, Pack2...). That succeeds, so T1, Args... is at least as specialized as Args....

Since #2 is at least as specialized as #1 and #1 is not at least as specialized as #2, we can say that #2 is more specialized:

Function template F is at least as specialized as function template G if, for each pair of types used to determine the ordering, the type from F is at least as specialized as the type from G. F is more specialized than G if F is at least as specialized as G and G is not at least as specialized as F.

The more specialized template is preferred, so we call #2.

这篇关于当参数是函数参数包时,在部分排序期间导出模板参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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