mat*_*scp 8 c++ templates variadic-functions variadic-templates c++11
以下代码编译并运行正常.
void foo() {
}
template <typename T, typename... Args>
void foo(T x, Args... args) {
cout << x << endl;
foo(args...);
}
// inside main()
foo(1,1,1);
Run Code Online (Sandbox Code Playgroud)
这个其他代码不编译:
void foo() {
}
template <typename... Args, typename T>
void foo(Args... args, T x) {
foo(args...);
cout << x << endl;
}
// inside main()
foo(1,1,1);
Run Code Online (Sandbox Code Playgroud)
编译器说调用没有匹配函数,foo(1,1,1)并且说它foo(Args... args, T x)是候选函数,但模板参数推导/替换失败,因为候选者需要1个参数,但提供了3个参数.
这种情况是否存在任何编译器无法处理的歧义?这个编译错误对我来说似乎不合逻辑.也许这与C++标准有意无关?
Clang的错误信息中有趣的部分是:
main.cpp:11:6: note: candidate template ignored: couldn't infer template argument 'T'
void foo(Args... args, T x) {
^
Run Code Online (Sandbox Code Playgroud)
的问题是,所述参数包Args...发生之前到T.
Args...是"贪婪的",所以没有任何参数留给编译器推断T,因此它失败了.
引用标准(强调我的):
[temp.param]/11
函数模板的模板参数包不能跟随 另一个模板参数,除非该模板参数可以从函数模板的参数类型列表中推导出来或者具有默认参数.[例:
Run Code Online (Sandbox Code Playgroud)... // 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- 结束例子]
(这个答案基于@ JohannesSchaub-litb的评论)
根据该标准,如果模板参数包用于不在参数列表末尾的函数参数包中,则该参数包不可推导.
§14.8.2.1/ 1从函数调用中减去模板参数[temp.deduct.call]:
当函数参数包出现在非推导的上下文([temp.deduct.type])中时,永远不会推导出该参数包的类型.[例如:
Run Code Online (Sandbox Code Playgroud)template<class T1, class ... Types> void g1(Types ..., T1); void h(int x, float& y) { const int z = x; g1(x, y, z); // error: Types is not deduced g1<int, int, int>(x, y, z); // OK, no deduction occurs }- 结束例子]
关于非推导的上下文,§14.8.2.5/ 5从类型[temp.deduct.type]中推导出模板参数:
函数参数包,不会出现在参数声明列表的末尾.
因此foo(1,1,1);失败的直接原因Args是不推导出模板参数,这对于使函数调用有效是必要的.
为了解释错误消息,一个未推导出的模板参数包将被推导出一个空的模板参数序列[1],这意味着它将被省略.然后foo(1,1,1);失败因为参数的数量不匹配,这就是编译器所抱怨的.
正如所示的标准示例一样,您可以明确指定模板参数以避免类型推导,即使它不符合代码的原始意图.如:
template <typename T, typename... Args>
void foo(Args... args, T x) {
}
int main() {
// inside main()
foo<int, int, int>(1, 1, 1);
}
Run Code Online (Sandbox Code Playgroud)
这里有一些额外的信息.
[1]我无法在标准中找到关于此的直接表达.最贴近一个是此,"A尾随模板参数包([temp.variadic])没有另外推导出将被推断为模板参数空序列".
| 归档时间: |
|
| 查看次数: |
884 次 |
| 最近记录: |