C++ 不是最后一个模板参数的演绎和参数包:此代码有效吗?
考虑以下最小示例:C++ 不是最后一个模板参数的演绎和参数包:此代码有效吗?,c++,templates,gcc,clang,language-lawyer,C++,Templates,Gcc,Clang,Language Lawyer,考虑以下最小示例: template<typename... A, typename R> void f(A&&..., R(*)(A...)) {} void g(int, char) {} int main() { f<int, char>(42, 'c', g); } 模板 无效f(A&&…,R(*)(A…){} void g(int,char){} int main(){ f(42,'c',g); } 参数包A不是最后一个参数。 无
template<typename... A, typename R>
void f(A&&..., R(*)(A...)) {}
void g(int, char) {}
int main() {
f<int, char>(42, 'c', g);
}
模板
无效f(A&&…,R(*)(A…){}
void g(int,char){}
int main(){
f(42,'c',g);
}
参数包A
不是最后一个参数。无论如何,我认为
R
可以从函数指针推断,因为
GCC(6.2)对此进行了解释,而clang(3.9)则表示无法推断模板参数R
我的期望是错误的,因此GCC不应该接受它,还是一个叮当作响的问题 上述段落: 如果类模板、变量模板或别名模板的模板参数具有默认模板参数,则每个后续模板参数应提供默认模板参数或作为模板参数包。如果主类模板、主变量模板或别名模板的模板参数是模板参数包,则应为最后一个模板参数函数模板的模板参数包后面不得跟有另一个模板参数,除非该模板参数可以从函数模板的参数类型列表([dcl.fct])中推导出来,或者具有默认参数([temp.decrete])。扣减指南模板的模板参数([temp.decrete.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
A&&…
是贪婪的,它将消耗g
作为A&&
而不是R(*)(A…)
说迂腐的话,如:
对于出现在参数声明列表末尾的函数参数包,将对调用的每个剩余参数执行演绎,并将函数参数包的声明器id的类型p作为相应的函数模板参数类型。每个演绎都会为模板参数包由函数参数包展开。当函数参数包出现在非推断上下文()中时,该参数包的类型永远不会推断。
如:
如果p的形式包含或,则将p的各个模板参数列表的每个参数Pi与a的相应模板参数列表的相应参数Ai进行比较。如果p的模板参数列表包含不是最后一个模板参数的包扩展,则整个模板参数列表为非推断上下文。如果Pi是包扩展,则Pi的模式将与a的模板参数列表中的每个剩余参数进行比较。
并且不能像第三个例子中所看到的那样指定它
当拒绝它时,叮当声是正确的。当原型是
R(*)(A…),A&…
?我认为clang
是正确的,因为参数包应该吞下函数指针,因此不会推断R
@StoryTeller的优点。两个编译器都接受代码。无论如何,它并不完全相同。移动函数指针还允许我删除
并作为f调用f
(g,42,'c')
。我不确定这是否是一个问题。可能只是一个GCC增强功能。@StoryTeller好吧,标准是一个。代码段有效或无效。它不能同时有效和无效,并且在这种情况下没有诸如无需诊断或UB之类的语句。我错了吗?我错了。你应该提交该问题[temp.Decreate/1]有一个很好的例子。关于类模板的最后一个片段不是函数模板吗?我正在手机上阅读,我在正确理解它时遇到了一些困难,对不起。14.8.2.5从类型[temp.Decreate.type]推导模板参数。
是14.8函数模板专门化[temp.fct.spec]的一部分
总之,我在[temp.Decrete.call]中添加了一些文字
void f(A&&..., R(*)(A...))