2015-04-06 87 views
3

我試圖在構造函數初始化列表中的lambda中捕獲可變參數。這是一個說明問題的簡單例子。Lambda在構造函數初始化列表中捕獲可變參數

#include <functional> 
#include <iostream> 

void foo(int a) 
{ 
    std::cout << a << std::endl; 
} 

template<typename ...Args> 
class Widget 
{ 
public: 
    Widget(std::function<void(Args...)> f, Args... args) 
     : _f([=]() { f(args...); }) // compiler error here 
    { 
    } 

    void print() const { _f(); } 

private: 
    std::function<void()> _f; 
}; 

int main(int argc, char* argv[]) 
{ 
    Widget<int> w(foo, 7); 
    w.print();  
    return 0; 
} 

在VS2013我得到以下編譯錯誤:

error C3546: '...' : there are no parameter packs available to expand 
error C2065: 'args' : undeclared identifier 

Widget構造編譯和工作的下列版本。

Widget(std::function<void(Args...)> f, Args... args) 
{ 
    _f = [=]() { f(args...); }; 
} 

Widget(std::function<void(Args...)> f, Args... args) 
    : _f(std::bind(f, args...)) 
{ 
} 

更新:的微軟的Visual C++編譯器團隊已經修復了這個問題,將其納入在Visual C++(see)即將發佈。

+2

看起來像是另一個bug。 – 0x499602D2

+0

是的,它看起來像一個錯誤。我已經向MS Connect提交了一份報告。 – Frank

回答

2

Lambda捕獲可能是編譯器最終實現的C++ 11的最後一部分,如果某個特定的編譯器尚未實現它,或者如果它的實現有問題,這也不足爲奇。據說,gcc直到最近纔得到這個權利。

典型的方法是使用元組來解決這個問題。使用std::make_tuple將所有可變參數放入一個元組中,然後捕獲該元組。

然後,將元組轉換回參數包。搜索stackoverflow,有幾個如何做到這一點的例子。

這將產生一大堆行李代碼。但事實是,它是什麼,當編譯器最終得到它的時候,這個解決方法可以被刪除,同時你會有一些工作。或多或少。

+0

謝謝。元組將起作用。 'std :: bind'正常工作,並且將函數分配給構造函數體內的lambda也可以,所以這些都是很好的解決方法。 – Frank

相關問題