[英]Using std::thread and std::function from a std::bind with a function with arguments and a non-void return
[英]Using `std::function<void(…)>` to call non-void function
前一段時間我使用std::function
非常像這樣:
std::function<void(int)> func = [](int i) -> int { return i; };
基本上,我這樣做是因為我想在std::function
存儲不同的函數對象,但我不想限制這些函數的返回類型。 由於這似乎有效,我接受了它。 但我不相信它是安全的,我也無法找到任何文件。 有誰知道這種用法是否合法? 或者更一般地說,對於可以安全地分配給std::function
的對象的規則是什么?
為了澄清,我關心的問題是lambda函數返回一個int
,而func
用return類型void
聲明。 我不確定這是否正常,特別是在調用func()
。
您的代碼具有未定義的行為。 它可能會或可能不會像您期望的那樣工作。 它有未定義行為的原因是因為20.8.11.2.1 [func.wrap.func.con] / p7:
要求:
F
應為CopyConstructible
。 對於參數類型ArgTypes
,f
應為Callable(20.8.11.2)並返回類型R
對於f
為返回類型R
Callable, f
必須返回一些可隱式轉換為std::function
的返回類型的東西(在你的情況下為void
)。 並且int
不能隱式轉換為void
。
我希望您的代碼能夠適用於大多數實現。 但是至少在一個實現( libc ++ )上,它無法編譯:
test.cpp:7:30: error: no viable conversion from 'int (int)' to 'std::function<void (int)>'
std::function<void(int)> ff = f;
^ ~
具有諷刺意味的是,這種行為的基本原理源於另一個SO問題 。
另一個問題是std::function
用法存在問題。 該問題的解決方案涉及讓實現在編譯時強制執行Requires:子句。 相反,這個問題的解決方案是禁止實現強制執行Requires:子句。
您的用例根據標准明確定義。
您正在從可調用對象[1]構造一個std::function
§20.8.11.2.1/ 7:
template<class F> function(F f);
要求:F應為CopyConstructible。 對於參數類型ArgTypes,f應為Callable(20.8.11.2)並返回R類型。
那你的f可以贖回嗎?
§20.8.11.2/ 2說:
類型F的可調用對象f對於參數類型ArgTypes是Callable,如果表達式
INVOKE (f, declval<ArgTypes>()..., R)
被認為是未評估的操作數(第5條),則返回類型R.形成良好(20.8.2)。
INVOKE
的定義是:
§20.8.2
定義
INVOKE (f, t1, t2, ..., tN)
如下:...處理成員函數/ var指針的東西...... -f(t1, t2, ..., tN)
在所有其他情況下。將
INVOKE (f, t1, t2, ..., tN, R) as INVOKE (f, t1, t2, ..., tN)
隱式轉換為R
INVOKE (f, t1, t2, ..., tN, R) as INVOKE (f, t1, t2, ..., tN)
。
並且因為任何類型都可以隱式轉換為 正如下面的litb所指出的,沒有隱含的轉換為void,所以這個定義不明確。 void
,所以使用符合標准的編譯器,您的代碼應該沒問題。
[1]:我認為lambda在這里算作一個可調用的對象,雖然我沒有參考。 您的lambda也可以用作函數指針,因為它不捕獲任何上下文
這看起來對於匿名函數可能沒問題。
引自http://www.alorelang.org/release/0.5/doc/std_function.html (這不是來自C ++標准庫,但看起來他們使用的東西類似於綁定到C ++)
只能使用函數定義,匿名函數表達式或使用點(。)運算符訪問綁定方法來創建函數對象。
另一種可能的方法是將函數指針存儲在auto中,如下所示: http : //en.wikipedia.org/wiki/Anonymous_function (C ++ section)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.