2016-11-20 41 views
3

考虑下面的小例子:不是最后一个模板参数的扣减和参数包是这个有效的代码吗?

template<typename... A, typename R> 
void f(A&&..., R(*)(A...)) {} 

void g(int, char) {} 

int main() { 
    f<int, char>(42, 'c', g); 
} 

的参数包A不是最后一个参数。
无论如何,我认为R可能已经从函数指针推导出来,因为[temp.param]/11

GCC(6.2)本agrees with me,而铛(3.9)rejects the code,并说,它不能推断出模板参数R

我的期望是否错误,因此GCC不应该接受它,或者是铿锵声的问题?

+0

当原型是'R(*)(A ...),A && ...'时会发生什么?我认为'clang'是正确的,因为参数包应该吞下函数指针,因此不能推导出'R'。 – StoryTeller

+0

@StoryTeller好点。两个编译器都接受这些代码。无论如何,这是不完全一样的。移动函数指针允许我也删除''并将'f'作为f(g,42,'c')'调用。 – skypjack

+0

我不确定*它是一个问题。可能只是一个GCC增强。 – StoryTeller

回答

1

从这提到的段落:

如果一个类模板,模板变量或别名模板的模板参数具有默认模板参数,以后每次模板参数应要么有一个默认的模板 - 参数提供或作为模板参数包。如果主类模板,主变量模板或别名模板的模板参数是模板参数包,则它应该是最后一个模板参数。 除非可以从函数模板的参数类型列表([dcl.fct])推导出模板参数,否则函数模板的模板参数包不应跟随其他模板参数,或者具有默认参数([temp.deduct])没有默认参数的扣减指南模板([temp.deduct.guide])的模板参数可以从扣减指南模板的参数类型列表中推导出来。 [实施例:

template<class T1 = int, class T2> class B; // error 

// U can be neither deduced from the parameter-type-list nor specified 
template<class... T, class... U> void f() { } // error 
template<class... T, class U> void g() { } // error 

- 端示例]

在这种情况下,template<typename... A, typename R>不能从功能模板的参数类型列表推导出因为:

void f(A&&..., R(*)(A...)) 

A&&...是贪婪的,它会消耗g作为A&&而不是R(*)(A...)

说到迂腐,如在temp.deduct.call-1

对于发生在参数声明列表,扣除用于呼叫的每个剩余参数进行的端部的函数参数包,取的在P型函数参数包的declarator-id作为相应的函数模板参数类型。每个推导都推导模板参数,以便在由函数参数包扩展的模板参数包中随后的位置。 当函数参数包出现在未推导的上下文中时([temp.deduct.type]),该参数包的类型永远不会被推断出来。

并且如在temp.deduct.type#9

如果P具有包含< T A形式>或< I>,则P的相应模板参数列表的每个参数Pi的与相应的比较A的相应模板参数列表的参数Ai。如果P的模板参数列表包含不是最后一个模板参数的包扩展,则整个模板参数列表是非推导的上下文。如果Pi为一包的扩展,那么Pi的图案与A.

的模板参数列表中的每个其余参数相比,它不能被指定为可以在第三个例子中看到。

锵当拒绝它是正确的。

+1

是不是关于类模板的最后一个片段,而不是函数模板?我正在从手机阅读它,我有一些困难,正确的,对不起。 – skypjack

+0

'14.8.2.5从类型[temp.deduct.type]中推导模板参数'是'14.8函数模板特殊化[temp.fct.spec]' – Danh

+0

的一部分无论如何,我添加了一些来自[temp.deduct.call] – Danh

相关问题