问题描述
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
void wrapper(T& u)
{
g(u);
}
class A {};
void g(const A& a) {}
int main()
{
const A ca;
wrapper(ca);
wrapper(A()); // Error
}
我有一个问题,为什么最后一条语句会导致编译器错误.
Hi I have a question on why the last statement gives a compiler error.
我认为模板类型T
将被推导为const A&
,因为ca
也被推导为const A&
.为什么在这种情况下类型推导失败?
I thought that the template type T
would be deduced as const A&
as the ca
is also deduced as const A&
. Why the type deduction fails in this case?
推荐答案
因为那不是扣减规则的工作原理.他们努力推断出尽可能多的与函数参数类型的匹配.临时不一定是const,它可以绑定到const引用.
Because that's not how the deduction rules work. They strive to deduce as much of a match to the function argument type as possible. A temporary is not necessarily const, it can just bind to a const reference.
但是您的函数模板不接受const引用,而是接受非const左值引用.因此,除非函数参数本身为const(不是),否则不会出现const
.
But your function template does not accept by a const reference, instead it accepts by a non-const lvalue reference. So no const
is gonna spring up unless the function argument is const itself (which it isn't).
正确的解决方案是使用转发引用(对推导的模板参数的右值引用):
The proper solution is to use a forwarding reference (an rvalue reference to a deduced template parameter):
template <typename T>
void wrapper(T&& u)
{
g(std::forward<T>(u));
}
现在u
可以绑定到任何对象.推导的类型将告诉您函数参数的值类别,使您可以将该类别转发给函数调用g(...)
,并确保选择了正确的重载.
Now u
can bind to any object. And the types deduced will tell you the value category of the function argument, allowing you to forward that category to the function call g(...)
, and making sure the proper overload is picked.
顺便说一句,如果您好奇的话,如果直接将const添加到临时类型中,您的原始代码将很好地构建.
By the way, in case you are curious, if you add the const directly to the temporary type, your original code will build just fine.
using CA = A const;
wrapper(CA()); // Not an error anymore
现在,u
最终是一个A const&
,并且可以很好地绑定到临时文件.但这只是好奇,在实践中不太可能有用.使用转发引用.
Now u
ends up being a A const&
and binds to the temporary just fine. But that is just a curiosity that's unlikely to be useful in practice. Use forwarding references.
这篇关于临时值的C ++模板类型推导的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!