[英]Passing a member function of another class into a std::function parameter
我有一個帶有一個函數的類,它接受一個std::function
並存儲它。 這部分似乎編譯正常(但如果有任何問題,請指出任何問題)
#include <functional>
#include <iostream>
struct worker
{
std::function<bool(std::string)> m_callback;
void do_work(std::function<bool(std::string)> callback)
{
m_callback = std::bind(callback, std::placeholders::_1);
callback("hello world\n");
}
};
// pretty boring class - a cut down of my actual class
struct helper
{
worker the_worker;
bool work_callback(std::string str)
{
std::cout << str << std::endl;
return true;
}
};
int main()
{
helper the_helper;
//the_helper.the_worker.do_work(std::bind(&helper::work_callback, the_helper, std::placeholders::_1)); // <---- SEGFAULT (but works in minimal example)
the_helper.the_worker.do_work(std::bind(&helper::work_callback, &the_helper, std::placeholders::_1)); // <---- SEEMS TO WORK
}
我得到了一個segfault ,但我不知道為什么。 這個我以前用過,其實這個例子是從我用過的地方復制過來的。 唯一真正的區別是成員函數是我從中調用它的類的一部分(即this
而不是the_helper
)。
所以這就是為什么我還要問我是否還有其他什么地方做錯了? 就像我應該將std::function
傳遞為:
void do_work(std::function<bool(std::string)>&& callback)
或者
void do_work(std::function<bool(std::string)>& callback)
我不知道為什么你的代碼段錯誤,因為我被寵壞了,直接跳過了std::bind
到 lambdas。 由於您使用C++11
您應該真正將代碼從std::bind
轉換為 lambdas:
struct worker
{
std::function<bool(std::string)> m_callback;
void do_work(std::function<bool(std::string)> callback)
{
m_callback = callback;
callback("hello world\n");
}
};
現在有了work_callback
和調用do_work
事情需要一些分析。
第一個版本:
struct helper
{
worker the_worker;
bool work_callback(std::string)
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([&](std::string s) { return the_helper.work_callback(s); });
}
現在此版本適用於您的玩具示例。 然而,在野外你需要小心。 傳遞給do_work
然后存儲在the_worker
the_helper
通過引用捕獲the_helper
。 這意味着此代碼僅在作為對 lambda 的引用傳遞的helper
對象比存儲m_callback
的worker
對象更有效時才有效。 在您的示例中, worker
對象是helper
類的子對象,因此這是正確的。 但是,如果在您的真實示例中情況並非如此或您無法證明這一點,那么您需要按值捕獲。
第一次嘗試按值捕獲(不編譯):
struct helper
{
worker the_worker;
bool work_callback(std::string)
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([=](std::string s) { return the_helper.work_callback(s); });
}
這不會編譯,因為存儲在 lambda 對象中的the_helper
的副本默認為const
,因此您不能對其調用work_callback
。
如果您不能使work_callback
const ,一個有問題的解決方案是使 lambda mutable
:
struct helper
{
worker the_worker;
bool work_callback(std::string)
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([=](std::string s) mutable { return the_helper.work_callback(s); });
}
但是您需要考慮這是否是您的意圖。
更有意義的是使work_callback
const:
struct helper
{
worker the_worker;
bool work_callback(std::string) const
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([=](std::string s) { return the_helper.work_callback(s); });
}
獲得SEGFAULT
的原因已經在評論中提到了。
但是,我想指出的是,在您的給定情況下,您既不需要使用std::bind
也不需要使用std::function
。 相反,只需擁有一個lambda和一個函數指針,您就可以處理您打算做的事情。
struct worker
{
typedef bool(*fPtr)(const std::string&); // define fun ptr type
fPtr m_callback;
void do_work(const std::string& str)
{
// define a lambda
m_callback = [](const std::string& str)
{
/* do something with string*/
std::cout << "Call from worker: " << str << "\n";
return true;
};
bool flag = m_callback(str);// just call the lambda here
/* do some other stuff*/
}
};
struct helper
{
worker the_worker;
bool work_callback(const std::string& str)
{
std::cout << "Call from helper: ";
this->the_worker.do_work(str);
return true; ------------------------>// remmeber to keep the promise
}
};
用例是:
int main()
{
helper the_helper;
the_helper.work_callback(std::string("hello world"));
// or if you intend to use
the_helper.the_worker.do_work(std::string("hello world"));
return 0;
}
請參閱此處的輸出:
PS :在上面的例子中,如果worker
在以后的情況下不需要m_callback
(即,只用於do_work()
),那么你可以刪除這個成員,因為可以在聲明它的同一個地方創建和調用lambdas。
struct worker
{
void do_work(const std::string& str)
{
bool flag = [](const std::string& str)->bool
{
/* do something with string*/
std::cout << "Call from worker: " << str << "\n";
return true;
}(str); -------------------------------------> // function call
/* do other stuff */
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.