#include <type_traits>
template<typename T>
void f(T&& a, T&& b)
{}
int main()
{
int n;
f(n, std::move(n));
}
T&&
是转发引用类型,所以我觉得decltype(a)
应该是int&
和decltype(b)
应该是 int&&
。
但是,上面的代码会产生以下错误:
main.cpp(13,2): error : no matching function for call to 'f' f(n, std::move(n));
main.cpp(7,6): note: candidate template ignored: deduced conflicting types for parameter 'T' ('int &' vs. 'int')
void f(T&& a, T&& b)
1 error generated.
当左值引用参数和右值引用参数作为相同的转发引用类型传递时,为什么它不起作用?
我的编译器是 clang 4.0。
最佳答案
编译器错误非常直接,T
不能同时在 int&
和 int
中推导。为了让它工作,你必须提供一个额外的模板参数:
template<typename T1, typename T2>
void f(T1&& a, T2&& b)
{}
推理
在处理 forwarding references 时,模板参数推导遵循特殊规则(又名通用引用)基于 reference collapsing rules
- 你&&变成你&
- 你& && 变成你&
- U&& & 变成 U&
- U&& && 变成 U&&
例如,如果你有一个函数模板:
template<typename T>
void foo(T&&) {}
- 如果
foo
输入是U
类型的左值,T
将减去U&
。遵循上面的引用折叠规则,参数类型将变为U&
。 - 如果
foo
输入是U
类型的右值,T
将被扣除为U
,因此参数类型将为U&&
。
现在按照上面的推理,模板参数推导会将 T
推导为 int&
作为您的第一个参数,因为输入是一个 lvalue
。
模板参数推导将尝试匹配第二个参数的类型,但对于第二个参数,因为输入是遵循上述规则的右值 T
将被推导为 int
.
此时编译器举起双手尖叫“dude T
的推导类型必须匹配所有输入参数”。
关于c++ - 当左值引用参数和右值引用参数作为相同的转发引用类型传递时,为什么它不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42410809/