2014-06-15 91 views
1

我有一個這樣的模板函數:模板函數接受拉姆達問題

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上面的調用是合法的嗎?

+0

這個錯誤沒有說*完全*有什麼問題? –

+0

但不是函數調用是否正確? – KaiserJohaan

+0

不,因爲你提供了一個左值,它不能綁定到右值引用。 –

回答

2

在這種情況下,應該不需要明確指定類型模板參數RenderableFunc。編譯器會推斷出這一點,一切都會好起來的:

DrawModels(renderQueue, preDrawRenderable); 

如果你確實指定它則由於preDrawRenderable是加括號的ID表達,你得到的實際閉合類型爲RenderableFunc,果然RenderableFunc&&到右值參考。當然,正如編譯器告訴你的,你不能將左值preDrawRenderable綁定到右值引用。

當你離開的編譯器來推斷型,適用於表單T&&參數的特殊規則,並RenderableFunc實際上推導出左值參考閉合類型。根據引用合攏規則,RenderableFunc&&也是一個左值引用,並且一切正常。如果你真的想指定模板參數,你可以做

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

額外的對括號改變由decltype回到左值參考因爲preDrawRenderable是左值的類型。同樣,引用合攏規則也適用,並且所有內容的工作方式都與編譯器推斷該類型的方式相同。