2012-03-25 130 views
2

我試圖實現一個代理類以下Herb Sutter's Example。本文中有幾個部分重複了幾個模板;列表中參數個數的一個模板(示例7,第41 - 59行)1。我試圖用一個可變模板替換它。Variadic模板lambda擴展

void operator()() const { 
    for_each(begin(l_), end(l_), [](function<F> i) { 
      i(); 
    }); 
} 

template<typename... Ts> 
    void operator()(Ts... vs) const { 
     for_each(begin(l_), end(l_), [&, vs...](function<F> i) //g++-4.6.1: expected ',' before '...' token; expected identifier before '...' token 
     { 
       i(vs...); 
     }); 
    } 

我發現這個answer,但我認爲我的問題是VS沒有擴大。什麼是正確的方法來做到這一點?

+0

這不是轉發功能正確的成語。你想要的是把你的參數作爲'(Ts && ... vs)',然後將它們轉發給函數'i(std :: forward(vs)...)'。這可能不會解決你的問題,但這是在C++ 11中完成轉發的完美方式。 – 2012-03-25 01:36:28

+0

我可能不理解你的觀點,但我不想提出這些觀點。在這種情況下,副本是正確的。每個回調都獲取事件參數的副本。可能會出現移動語義會起作用的情況,但副本更一般。對? – 2012-03-25 05:37:49

+0

轉發將根據需要移動或複製參數。完美轉發背後的想法是它*完美*:與您直接調用'i'相同。因此,如果'i'按值取其參數,並且通過左值,則它將被複制。如果你傳遞一個右值,它將會移動,這正好*如果你直接調用'i',會發生什麼。如果用戶想要移入函數參數,則不能(也不應該)阻止它們。這是他們的業務。所有你需要擔心的是完美的轉發參數,這就是C++ 11的語法。 – 2012-03-25 05:59:50

回答

1

這似乎是舊的gcc bug仍然存在。可能想給維護者一個友善的推動。

一種解決方法可以是:

#include <vector> 
#include <algorithm> 
#include <functional> 
#include <tuple> 

using namespace std; 

template<typename F> 
struct Foo { 
    template<typename... Ts> 
    void operator()(Ts... vs) const { 
    auto t = tie(vs...); 

    for_each(begin(l_), end(l_), 
      [&t](function<F> i) 
      { 
       // figure out the function arity and unpack the tuple 
       // onto it. This is could be more difficult than one 
       // thinks. 

       // i(vs...); 
      } 
    ); 
    } 
    vector< function<F> > l_; 
}; 
+0

謝謝我刪除了拉姆達: '模板 void運算符()(TS ... VS)const的{ 爲(自動I =開始(L_); I =結束(l_); ++ i) { (* i)(vs ...); } }' – 2012-03-25 04:10:55

+0

你仍然可以通過使用'auto i:l_'來改善它:) – pmr 2012-03-25 12:33:35

2

我不確定爲什麼vs沒有擴展,但也許簡單的解決方法是按值傳遞參數作爲默認值,並命名需要通過引用傳遞的已知對象。這樣,捕獲列表中的擴展就不需要了。就個人而言,如果這是一個gcc中的錯誤,我不會感到驚訝(您的示例不完整 - 否則我會嘗試使用最近的gcc和clang的SVN版本)。