2013-10-11 38 views
4

使用Visual Studio 2013 RC和C++,我試圖將std::unique_ptr傳遞給使用std::bind綁定的函數。但是,我遇到了麻煩,因爲當我嘗試這個時,VS似乎並不喜歡它。這是我想要編譯的內容:Visual Studio 2013 C++ - 將std :: unique_ptr傳遞給綁定函數

#include <memory> 
#include <iostream> 
#include <functional> 

void func(std::unique_ptr<int> arg) 
{ 
    std::cout << *arg << std::endl; 
} 

int main() 
{ 
    std::function<void (std::unique_ptr<int>)> bound = 
     std::bind(&func, std::placeholders::_1); 

    std::unique_ptr<int> ptr(new int(42)); 
    bound(std::move(ptr)); 

    return 0; 
} 

這個編譯在GCC 4.8.1中,但不是在VS2013 RC中編譯。我在VS中總是遇到移動語義的問題,但我真的很想用std::unique_ptr而不是std::shared_ptr或原始指針。

一個解決辦法,我發現是改變函數簽名接受std::unique_ptr&,這並在VS和GCC編譯,但不會使func服用std::unique_ptr的所有權特別清楚的意圖,也不允許我從安全的異步調用該函數,除非我做的特別難看的東西:

#include <memory> 
#include <iostream> 
#include <functional> 
#include <future> 
#include <string> 

void func(std::unique_ptr<int>& arg) 
{ 
    std::cout << *arg << std::endl; 
} 

int main() 
{ 
    std::function<void (std::unique_ptr<int>&)> bound = 
     std::bind(&func, std::placeholders::_1); 

    std::unique_ptr<int> ptr(new int(42)); 
    std::promise<void> prom; 
    std::async(
     [&bound, &ptr, &prom] 
     { 
      std::unique_ptr<int> movedPtr = std::move(ptr); 
      prom.set_value(); 

      bound(std::move(movedPtr)); 
     }); 

    prom.get_future().wait(); 

    // Wait here 
    std::string dummy; 
    std::cin >> dummy; 
} 

有沒有辦法來解決這個問題,而不改變func的簽名?

謝謝!

+0

您無法通過值傳遞unique_ptr,它沒有複製構造函數。 – yngccc

+1

因此'std :: move()'。調用'func(std :: move(ptr))'可以很好地工作,如果我直接調用它,而不是當它被綁定時。 – mgbowen

+0

然後爲什麼不改變'func'接受'unique_ptr &&'而不是 – yngccc

回答

3

我最近和VS 2012有同樣的問題。我相信這是MSVC中的一個錯誤;至少在MSVC++ 11中,僞變量擴展似乎通過值將參數轉發給一些內部函數。似乎這沒有得到改善。
作爲一種變通方法,我使用Lambda表達式來代替,但需要另外的黑客攻擊,使其工作:

std::function<void (std::unique_ptr<int>)> bound = 
    [] (std::unique_ptr<int> arg) { func(std::move(arg)); }; 

仍然不能編譯。但是,如果你添加任何捕獲的值(即使未使用),它編譯:

int x; 
std::function<void (std::unique_ptr<int>)> bound = 
    [x] (std::unique_ptr<int> arg) { func(std::move(arg)); }; 
+0

啊,那正是我需要的!對於Linux目標也應該很容易。非常感謝! – mgbowen

+0

你剛給我一個重新設計的工作。謝謝。我知道GCC 4.7也可以正確處理佔位符。 – Mranz

+0

在VS 2013(VC12)中,不再需要使用僞造的捕獲值進行破解。 – cdoubleplusgood

0

std::bind綁定的函數不轉發參數,它將它們複製到函數中。因此,從C++ 11開始,std::bind不適用於僅移動類型。這個問題是「更完美轉發」提案背後的想法(like this one)。有一個更新的,但我現在似乎無法找到它。

+0

對於有參數綁定到'std :: function'的函數來說,這可能是正確的,但是我試圖使用的'std :: function'只有佔位符。我的第一個代碼片段在GCC中編譯,但不是VS.我試圖找到一個解決方法,所以我可以保留'func'的簽名,並仍然與VS編譯。 – mgbowen

1

你必須參數進入綁定呼叫func也。不僅在bound調用

bound(std::move(ptr)); 

而且在結合:

std::function<void(std::unique_ptr<int>)> bound = 
    std::bind(func, 
       std::bind(std::move<std::unique_ptr<int>&>, 
         std::placeholders::_1)); 

這在VS2013編譯(更新4)對我來說。

相關問題