【问题标题】:Templated function accepting lambda issue接受 lambda 问题的模板化函数
【发布时间】:2014-08-05 13:07:08
【问题描述】:

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

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 上面的调用是合法的,不是吗?

【问题讨论】:

  • 错误不是说确切出了什么问题吗?
  • 但是函数调用不正确吗?
  • 不,因为你提供了一个左值,它不能绑定到右值引用。

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


【解决方案1】:

在这种情况下,不需要显式指定类型模板参数RenderableFunc。编译器会推导出来,一切都会好起来的:

DrawModels(renderQueue, preDrawRenderable);

如果您实际指定它,那么由于preDrawRenderable 是一个未加括号的id 表达式,您将获得实际的闭包类型RenderableFunc,这会将RenderableFunc&amp;&amp; 转换为右值引用。当然,正如编译器告诉你的那样,你不能将左值 preDrawRenderable 绑定到右值引用。

当您让编译器推断类型时,适用于 T&amp;&amp; 形式的参数的特殊规则适用,RenderableFunc 实际上被推断为 对闭包类型的左值引用。根据引用折叠规则,RenderableFunc&amp;&amp; 也是一个左值引用,一切正常。如果你真的想指定模板参数,你可以这样做

DrawModels<decltype((preDrawRenderable))>(renderQueue, preDrawRenderable);

额外的一对括号将decltype 返回的类型更改为左值引用,因为preDrawRenderable 是左值。引用折叠规则再次适用,一切都与让编译器推断类型一样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    • 2014-09-04
    • 1970-01-01
    相关资源
    最近更新 更多