如果参数列表绑定(bind)到一个类,我不明白参数包必须位于参数列表末尾的原因,而如果参数列表是成员方法声明的一部分,则放宽约束。
换句话说,这个编译:
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 { };
将分配器类型作为最后一种类型将不胜感激,但我可以以某种方式解决它(无论如何,如果您有建议,我们将不胜感激,也许您的建议比我的优雅得多!)。
也就是说,我得到了错误:
parameter pack 'Args' must be at the end of the template parameter list
所以,我只是想完全理解为什么它在某些情况下被接受,但在其他一些情况下却不是。
Here是一个类似的问题,但它只是解释了如何解决问题,这对我来说很清楚。
最佳答案
它对函数模板有效,但只有当参数推导可以帮助编译器解析模板参数时,你的函数模板示例实际上是无用的,因为
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
。实际上就像@T.C.指出它实际上应该是一个语法错误,因为以这种方式定义的函数模板永远无法实例化。
一个更有用的函数模板是这样的
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
[温度参数]/11
[...]If a template-parameter of a primary class template or alias template is a template parameter pack, it shall be the last template-parameter.[...]
(如果它们被推导出来,就会像函数模板示例中那样模棱两可)。
关于c++ - 参数包必须在参数列表的末尾......何时以及为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34940875/