我有一个这样的模板化函数:
template<class RenderableFunc>
void DrawModels(const RenderQueue& renderQueue, RenderableFunc&& preDrawFunc)
{
// .......
}
然后这样调用它:
auto preDrawRenderable = [this](const Renderable& renderable)
{
// ...........
};
DrawModels<decltype(preDrawRenderable)>(renderQueue, preDrawRenderable);
然而,当使用 VS2013 进行编译时,我得到了这个:
error C2664:
with
[
RenderableFunc=JonsEngine::OpenGLRenderer::GeometryStage::<lambda_411ef98538bba0cf82404b7a6f008e46>
]
You cannot bind an lvalue to an rvalue reference
这是为什么? Afaik 上面的调用是合法的,不是吗?
最佳答案
在这种情况下,不需要显式指定类型模板参数 RenderableFunc
。编译器会推导出它,一切都会好起来的:
DrawModels(renderQueue, preDrawRenderable);
如果您实际指定它,那么由于 preDrawRenderable
是一个未加括号的 id-expression,您将获得作为 RenderableFunc
的实际闭包类型,它变成RenderableFunc&&
为右值引用。当然,正如编译器告诉您的那样,您不能将左值 preDrawRenderable
绑定(bind)到右值引用。
当您让编译器推导类型时,适用于 T&&
形式参数的特殊规则适用,并且 RenderableFunc
实际上被推导为 lvalue引用闭包类型。根据引用折叠规则,RenderableFunc&&
也是左值引用,一切正常。如果你真的想指定模板参数,你可以这样做
DrawModels<decltype((preDrawRenderable))>(renderQueue, preDrawRenderable);
额外的一对括号将 decltype
返回的类型更改为左值引用,因为 preDrawRenderable
是一个左值。再次应用引用折叠规则,一切都像让编译器推断类型一样工作。
关于c++ - 接受 lambda 问题的模板化函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24231298/