Nir*_*man 3 c++ templates variadic-templates c++11
看起来这个代码不正确,因为我得到编译器错误.我试图理解为什么:
template <class ... Ts>
struct type_list{};
template <class ... Ts, class T_, class ... Ts_>
auto foo(type_list<Ts...>, Ts&&..., T_&&t, Ts_&&...) {
return sizeof(T_);
}
int main() {
std::cerr << foo(type_list<int>{}, 5, 5.0, 3);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
clang产生以下错误:
example.cpp:16:16: error: no matching function for call to 'foo'
std::cerr << foo(type_list<int>{}, 5, 5.0, 3);
^~~
example.cpp:11:6: note: candidate template ignored: deduced conflicting types for parameter 'Ts'
(<int> vs. <>)
auto foo(type_list<Ts...>, Ts&&..., T_&&t, Ts_&&...) {
Run Code Online (Sandbox Code Playgroud)
在我看来,在我的调用中Ts
应该推断出int
(因为这是使第一个参数解决的唯一方法),然后其他一切都将被强制作为结果.为什么这不起作用?
Clang Ts
从两个相互矛盾的来源中推断出来:type_list<Ts...>
和Ts&&...
.因为你打电话foo
跟type_list<int>{}
,Ts
首先推导出{int}
.但是,因为最后一个参数Ts_&&...
具有参数包的类型,所以它可以捕获所有它; 在这种情况下,最后两个参数(而T_&&t
被传递的5
),该推导出Ts_
如{double, int}
(和T_
如int
).这Ts
没有任何争论,所以它被推断为{}
.
因此,Clang的错误消息:Ts
被推断为{}
和{int}
((<int> vs. <>)
在错误消息中).
请注意,GCC以不同的方式做事:
错误:函数'auto foo(type_list,Ts && ...,T _ &&,Ts _ && ...)的参数太少[与Ts = {int}; T_ = int; Ts_ = {double,int}]'
它试图保持Ts
推断为{int}
但仍然推导Ts_
为{double, int}
,因此没有办法给出正确数量的参数.
要进一步解释,请考虑以下事项:
template <class ... Ts>
struct type_list{};
template <class ... Ts>
auto foo(type_list<Ts...>, Ts...) {
return sizeof...(Ts);
}
int main() {
std::cerr << foo(type_list<int>{}, 5, 5.0, 3);
}
Run Code Online (Sandbox Code Playgroud)
Clang正确地调用了这个,因为两个推论是冲突的:
注意:候选模板被忽略:推导出参数'Ts'的冲突类型(
<int>
vs.<int, double, int>
)
麻烦的是,你不能用另一个参数包捕获2个参数,因为如果放在后面(这是你的情况),它将捕获所有内容,如果放在之前没有任何内容:
template <class ... Ts>
struct type_list{};
template <class... Ts, class... Ts_>
auto foo(type_list<Ts...>, Ts_..., Ts...) {
return sizeof...(Ts);
}
int main() {
std::cerr << foo(type_list<int>{}, 5, 5.0, 3);
}
Run Code Online (Sandbox Code Playgroud)
在这里,锵产生相同的错误消息,因为Ts
仍在演绎既{int}
从type_list
,并{int, double, int}
通过捕获所有剩下的参数.
我认为你唯一的选择是以某种方式处理元组或更明确的调用:( 在这种情况下foo<int>(type_list<int>{}, 5, 5.0, 3)
你可以删除type_list
它).这样,Ts
不再推断出:你明确地做到了{int}
.