c++ - 接受 lambda 问题的模板化函数

标签 c++ c++11 lambda visual-studio-2013

我有一个这样的模板化函数:

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/

相关文章:

c++ - -错误=格式: how can the compiler know

C++ Vector Sort 方法编译失败,返回预期的表达式

Java8 Lambda 与匿名类

c++ - 为什么当我取消引用数组指针时,结果值是指向数组第一个元素的指针,而不是整个数组对象?

c++ - 具有用户定义的指针成员的对象的赋值运算符

c++ - 关于类定义的问题

c++ - 非成员函数不推荐静态关键字的基本原理

c++ - 为什么通过引用捕获变量的 lambda 不能转换为函数指针?

c++ - 如何复制 shared_ptr 的 vector ?

java - 从匿名类到 lambda 表达式