![](/img/trans.png)
[英]Why am I getting the error “parameter pack 'F' must be at the end of the template parameter list”
[英]Parameter pack must be at the end of the parameter list… When and why?
如果参数列表必须位于参数列表的末尾,如果后者绑定到类,则不会得到参数列表的原因,如果参数列表是成员方法声明的一部分,则放宽约束。
换句话说,这个编译:
class C {
template<typename T, typename... Args, typename S>
void fn() { }
};
以下不是:
template<typename T, typename... Args, typename S>
class C { };
为什么第一种情况是正确的,第二种情况不是?
我的意思是,如果它是合法的语法,那么在这两种情况下都不应该这样吗?
要清楚,真正的问题是我正在定义一个类似于下面的类:
template<typename T, typename... Args, typename Allocator>
class C { };
将分配器类型作为最后一种类型将不胜感激,但我可以以某种方式解决它(无论如何,如果你有一个建议,它的赞赏,也许你的优雅比我的更优雅!)。
那就是说,我收到了错误:
参数包'Args'必须位于模板参数列表的末尾
所以,我只是很好奇地完全理解为什么它在某些情况下被接受,但它不在其他一些情况下。
这是一个类似的问题,但它只是解释了如何解决问题,这对我来说非常清楚。
它对函数模板有效,但只有当参数推导可以帮助编译器解析模板参数时,因为它代表你的函数模板示例实际上是无用的,因为
template<typename T, typename... Args, typename S> void fn() { }
int main() { fn<int, int, int>(); }
test.cpp: In function 'int main()':
test.cpp:2:32: error: no matching function for call to 'fn()'
int main() { fn<int, int, int>(); }
^
test.cpp:1:57: note: candidate: template<class T, class ... Args, class S> void fn()
template<typename T, typename... Args, typename S> void fn() { }
^
test.cpp:1:57: note: template argument deduction/substitution failed:
test.cpp:2:32: note: couldn't deduce template parameter 'S'
int main() { fn<int, int, int>(); }
编译器无法确定哪些模板参数属于参数包,哪些模板参数属于S
事实上,正如@TC所指出的,它实际上应该是语法错误,因为以这种方式定义的函数模板不能被实例化。
一个更有用的功能模板就像是
template<typename T, typename... Args, typename S> void fn(S s) { }
现在,编译器能够明确地将函数参数s
与模板类型S
匹配,副作用是S
将始终推导出 - 第一个之后的所有显式模板参数都属于Args
。
这些都不适用于(主)类模板,不推导出参数,并且明确禁止参数:
来自草案n4567
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4567.pdf
[temp.param] / 11
[...]如果主类模板或别名模板的模板参数是一个模板参数包,它应是最后一个模板参数 。[...]
(如果推断它们会像函数模板示例中那样模糊不清)。
第一个是不对的。 编译器只是错误并且无法诊断它。 [temp.param] / 11 :
函数模板的模板参数包不能跟随另一个模板参数,除非该模板参数可以从函数模板的参数类型列表中推导出来或者具有默认参数(14.8.2)。
如果函数类型T(Args...)
对最终用户有意义,解决此问题的一种方法是使用部分特化:
template<class F, class Alloc> class C; //undefined
template<class T, class... Args, class Alloc>
class C<T(Args...), Alloc> {
// implementation
};
根据实际需求,类型擦除分配器也可能值得考虑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.