![](/img/trans.png)
[英]How does a std::function object which return a std::function work when call by operator()?
[英]How to work around the fact that std::function has no operator==?
問題:以下代碼非常具有表現力和簡潔性,如果不一定快,則不是因為它不能編譯。
它無法編譯,因為您無法將std :: function實例與operator ==()進行比較。 而std :: find()試圖做到這一點。
當然,我可以采用一種完全不同的實現方式,但是我很頑固,因為我喜歡下面的代碼,我正在尋找可行的“盡可能接近”的東西。
誰可以為我提供一個相當重寫的代碼,下面的代碼也做同樣的事情?
#include <functional>
#include <vector>
typedef std::function<bool(int)> Tester_t;
typedef std::vector<Tester_t> TesterSet_t;
bool Test(TesterSet_t &candidates, int foo)
{
TesterSet_t dropouts;
for( auto& tester : candidates )
{
if(!tester(foo))
{
droputs.push_back(tester);
}
}
while(!dropouts.empty())
{
// The following line is not compiling because std::function has no operator==()
TesterSet_t::iterator culprit =
std::find( candidates.begin(), candidates.end(), dropouts.back() );
candidates.erase(culprit);
dropouts.pop_back();
}
return !candidates.empty();
}
正如其他人所說,你不需要比較std::function
s。 使用標准C ++工具,可以有效地(線性復雜性)實現兩行:
bool Test(TesterSet_t &candidates, int foo)
{
candidates.erase(std::remove_if(candidates.begin(), candidates.end(),
[foo](Tester_t& f){ return !f(foo); }), candidates.end());
return !candidates.empty();
}
你這里不需要平等。 隨便擦除
for (auto it = candidates.begin(); it != candidates.end(); ) {
if (! (*it)(foo) ) {
it = candidates.erase(it);
}
else {
++it;
}
}
return !candidates.empty();
即使為std::function
定義了operator==
,這也會比問題中的版本更快。
如果您不需要刪除候選人,您可以寫:
bool Test(TesterSet_t &candidates, int foo)
{
return std::any_of(candidates.begin(), candidates.end(), [&foo](Tester_t &tester) {
return tester(foo);
});
}
UPDATE
好的,你需要刪除候選人
bool Test(TesterSet_t &candidates, int foo)
{
candidates.erase(
std::remove_if(candidates.begin(), candidates.end(), [&foo](Tester_t &tester) {
return !tester(foo);
}),
candidates.end()
);
return !candidates.empty();
}
簡單的答案是在這種情況下不使用std::function<...>
,而是像std::function<...>
那樣定義一個相等運算符。 為function<...>
定義相等運算符的方法是在構造時檢測實際函數對象是否實際包含相等運算符,如果是,則使對象具有可比性。 否則,您要么產生錯誤,要么認為持有此特定函數對象類型的對象是無法比較的。
然而,直接觀察到大多數功能對象無法比較! 例如,lambda函數不具有可比性, std::bind()
和std::mem_fn()
也不會產生類似的函數對象。 同樣,可以有std::bind()
和std::mem_fn()
的自定義實現。 除非有一個空捕獲, 否則無法使lambda函數具有可比性,在這種情況下它們可以轉換為函數指針並進行比較。
相等感知功能對象的實現有點太長,無法快速鍵入響應。 但是,您可以在github上查看我的實現,以獲得相等的bind()
和mem_fn()
。 有關std::function<...>
可比較版本的實現,請參閱此答案 。 如果lambda函數具有相同的簽名並且所有捕獲的值具有相等的可比性,則可能希望使lambda函數具有可比性。
所有這一切,如果你能避免這種需要,最好避免。 但是,我遇到過一些用例,盡管有限制,但是類似的std::function<...>
會相當方便(即不會覆蓋所有的函數對象)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.