[英]Use member function for `std::thread` with `std::ref(*this)` fails to compile
我使用下面的最小示例重現我嘗試創建調用非靜態成員函數的線程以完成其工作時遇到的編譯器錯誤:
#include <thread>
#include <iostream>
class Worker
{
public:
Worker() : m_worker(&Worker::doWork, std::ref(*this), 1)
{}
std::thread m_worker;
void doWork(int a) { std::cout << a << std::endl; }
};
int main(int argc, char* argv[]) {
Worker k;
}
使用gcc4.8-gcc5.1時,由於以下原因,編譯失敗:
In file included from /usr/include/c++/4.8/thread:39:0,
from /tmp/gcc-explorer-compiler115614-69-rgangs/example.cpp:1:
/usr/include/c++/4.8/functional: In instantiation of 'struct std::_Bind_simple<std::_Mem_fn<void (Worker::*)(int)>(std::reference_wrapper<Worker>, int)>':
/usr/include/c++/4.8/thread:137:47: required from 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (Worker::*)(int); _Args = {std::reference_wrapper<Worker>, int}]'
7 : 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 (Worker::*)(int)>(std::reference_wrapper<Worker>, int)>'
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 (Worker::*)(int)>(std::reference_wrapper<Worker>, int)>'
_M_invoke(_Index_tuple<_Indices...>)
^
Compilation failed
另一方面,Clang似乎可以很好地編譯此代碼。 誰在這里是正確的,這是gcc中的錯誤(帶有公開票嗎?)?
編輯:當使用m_worker(&Worker::doWork, this, 1)
初始化線程時,gcc編譯就好了。 那么,在這種情況下使用std::ref(*this)
是否合法? 我想任何std::ref()
,更籠統。
您的thread
構造函數調用依賴於以下語義:
[C++14: 30.3.1.2/3]:
要求:F
和Args
每個Ti
必須滿足MoveConstructible要求。 調用(
DECAY_COPY( std::forward<F>(f)),
DECAY_COPY(std::forward<Args>(args))...)
(20.9.2)是有效的表達式。
並因此定義了INVOKE
:
[C++14: 20.9.2/1]:
定義INVOKE(f, t1, t2, ..., tN)
:
(t1.*f)(t2, ..., tN)
當f
是指向類T
的成員函數的指針並且t1
是類型T
的對象或對類型T
的對象的引用或對T
的引用從T
派生的類型的對象;((*t1).*f)(t2, ..., tN)
當f
是指向類T
的成員函數的指針並且t1
不是上一項中描述的類型之一時;t1.*f
當N == 1
且f
是指向類T
成員數據的指針,並且t1
是類型T
的對象或對類型T
的對象的引用或對從T
派生的類型的對象的引用;(*t1).*f
當N == 1
且f
是指向類T
成員數據的指針並且t1
不是上一項中所述的類型之一時;- 在所有其他情況下
f(t1, t2, ..., tN)
如您所見,這里沒有提供std::reference_wrapper<Worker>
,這就是std::ref(*this)
提供的。 當然,衰減規則中沒有任何幫助( [C++14: 30.2.6/1]
)。
Clang實際上在這里稍微有點槍聲,似乎允許這樣做,因為感謝我們自己的Jonathan Wakely提交的圖書館工作組第2219期,這一天將符合標准。 但是,目前還不是。
無論如何,這整件事都沒有意義。 無需編寫此代碼。 只需寫下:
Worker() : m_worker(&Worker::doWork, this, 1)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.