2016-04-07 89 views
0

所以我有一個具有我想要線程的成員函數的對象。由於這個功能將被操縱的一些資源的對象外,我要通過引用傳遞互斥作爲參數傳遞給該函數:將std :: mutex作爲參數的成員函數的線程化

#include <iostream> 
#include <mutex> 
#include <thread> 

class foo 
{ 
    public: 
     void bar(std::mutex &m) 
     { 
      std::lock_guard<std::mutex> lock(m); 
      std::cout << "Threading this function works!" << std::endl; 
     } 
}; 


int main() 
{ 
    foo a; 
    std::mutex m; 
    std::thread bar_thread(&foo::bar, std::ref(a), std::ref(m)); 
    bar_thread.join(); 
    return 0; 
} 

此編譯和運行在Visual Studio 2013/VC++細。但是,當我嘗試在g ++中編譯時失敗。該錯誤消息也很神祕,這使得它很難理解什麼編譯器抱怨:

/usr/include/c++/4.8/functional: In instantiation of ‘struct std::_Bind_simple<std::_Mem_fn<void (foo::*)(std::mutex&)>(std::reference_wrapper<foo>, std::reference_wrapper<std::mutex>)>’: 
/usr/include/c++/4.8/thread:137:47: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (foo::*)(std::mutex&); _Args = {std::reference_wrapper<foo>, std::reference_wrapper<std::mutex>}]’ 
thread_test.cpp:63:69: required from here 
/usr/include/c++/4.8/functional:1697:61: error: no type named ‘type’ in ‘class std::result_of<std::_Mem_fn<void (foo::*)(std::mutex&)>(std::reference_wrapper<foo>, std::reference_wrapper<std::mutex>)>’ 
     typedef typename result_of<_Callable(_Args...)>::type result_type; 
                  ^
/usr/include/c++/4.8/functional:1727:9: error: no type named ‘type’ in ‘class std::result_of<std::_Mem_fn<void (foo::*)(std::mutex&)>(std::reference_wrapper<foo>, std::reference_wrapper<std::mutex>)>’ 
     _M_invoke(_Index_tuple<_Indices...>) 
     ^

我有這事做性病的非複製性::互斥體,也許是懷疑g ++中的std :: ref實現與vC++中的不同?這只是一個隨機猜測。

任何熟悉兩種不同C++編譯器精妙之處的人都知道是什麼導致了這個問題,以及它如何解決?

+1

版本的gcc? –

+0

@RichardHodges g ++ 4.8.4 –

回答

1

傳遞一個reference_wrapper作爲INVOKE的'this'參數,其中f是一個成員函數指針,它的標準爲C++ 17。

在此之前,它不是嚴格有效的。

替代:

#include <mutex> 

#include <thread> 
#include <iostream> 

class foo 
{ 
    public: 
     void bar(std::mutex &m) 
     { 
      std::lock_guard<std::mutex> lock(m); 
      std::cout << "Threading this function works!" << std::endl; 
     } 
}; 


int main() 
{ 
    foo a; 
    std::mutex m; 
    std::thread bar_thread(&foo::bar, std::addressof(a), std::ref(m)); 
    bar_thread.join(); 
    return 0; 
} 

推理:

std::thread::thread<>(f, args...)在INVOKE方面實現(F,ARGS ...)

一些參考資料這裏:

http://en.cppreference.com/w/cpp/concept/Callable

+0

這似乎工作,謝謝! –

+1

@發大塊它保證按標準工作! –

+0

還有一件事,當函數沒有將互斥體作爲參數時,如何使用std :: ref()工作?或者只有在函數需要參數時才按照INVOKE實現? –

0

當一個指向對象被傳遞,而不是參考(包裝)該編譯以g ++:

std::thread bar_thread(&foo::bar, &a, std::ref(m)); 

顯然,由Richard霍奇作爲回答,引用包裝不支持作爲被叫直到C++ 17。

+0

它不是一個錯誤,除非它不適用於-std = C++ 17 –

+0

@RichardHodges我不熟悉標準的那部分內容,但是我把它和cppreference的單詞當作了它。 – user2079303

+1

我認爲這比歷史上的事情更多是歷史事故。只是在以前的標準中沒有提到想象中的INVOKE函數的arg2引用包裝(可能是因爲沒有人認爲他們需要它)。 std :: invoke()作爲C++ 17的函數而存在。結果是整容了。 –

相關問題