[英]Creating a C++11 std::function<> with state
用狀態創建C ++ 11 std::function<>
的最佳方法是什么?
在純C ++ 98中,我將創建一個從std::unary_function<>
或std::binary_function<>
繼承的函子結構。 因此,給定以下函子,如何從以下函子創建std::function<int(int)>
?
struct Functor
{
int x;
Functor(int val) : x(val) {}
int operator()(int val) { return val + x; }
};
int main()
{
Functor f(10);
int x = f(30);
}
請注意,上面的代碼是我需要的極大簡化。 實際上,函子配置了多個參數,並從文件中讀取數據(每個記錄比int更為復雜)。 有沒有比使用lambda更接近使用函子的解決方案?
編輯 :澄清
為此最容易使用lambda表達式:
std::function<int(int)> f = [](int n) { return n + 30; }
您也可以使用std::bind
:
std::function<int(int)> f = std::bind(std::plus<int>, std::placeholders::_1, 30);
在這兩種情況下, 30
都只是一個示例,可以用捕獲的變量代替(不過,請確保將lambda中的捕獲規范更改為[=]
),並且最好還是使用auto
類型來避免潛在的當只需要一些可調用類型時,創建function
對象的開銷很大。
使用Lambda:
int x = 0;
std::function<int (int)> add = [x](int val) { return x + val; }
auto add2 = [x](int val) { return x + val; }
在此,lambda可以訪問的變量在方括號中。 x作為副本傳遞。 您還可以通過在狀態前面加上“&”並捕獲“ this”來將狀態作為參考
您可以繼續在C ++ 11中使用函子和類,實際上std::bind
和std::function
現在已成為C ++ 11標准的一部分,而以前它們是boost庫的一部分並在tr1中受支持或作為各種標准庫的擴展。 (不是編譯器,它們已經按照C ++ 98/03標准進行了編譯,但是它們是作為庫功能添加的)。
Lambdas是一種新的語言功能,當您確實希望在不適合循環的sort
或remove_if
sort
的算法中真正需要1行或2行表達式時,Lambda非常有用。
在您的情況下,雖然您可以使用lambda進行編寫,但如果您的邏輯像您所看到的那樣復雜,那么在這種情況下,您可能不想使用一個來破壞代碼的邏輯。 您可能仍然可以使用lambda來創建std :: function。
您甚至可能想放棄使用多態性的更古老的“學問”,即傳入具有簽名功能的對象,並將其用作回調。 這樣肯定會更容易維護任何對象的生存期。
現在,讓我們假設您的對象需要一個callback
函數,該函數實際上在某處接受一個int
參數並返回一個int。
std :: bind
bind
實際上是向函數添加了額外的參數,但是該函數必須返回一個int值。 它可以做的是成為類成員函數或采用額外的參數。
如果它是類成員,則需要一個對象來調用它。
std::bind( &MyClass::myFunction, myClassInstance, a, std::placeholders::_1 , b);
myClassInstance
可以是引用包裝器或傳遞值,也可以是類型的對象的指針或std::shared_ptr
或std::unique_ptr
。 reference-wrapper是一個包含引用的特殊類,因為自動模板推導將無法知道您實際上是要傳遞引用還是按值。 使用參考包裝器時要小心。 該引用在函數調用時必須仍然有效,並且這種方式已經發生了許多難以發現的錯誤。 實際上,在早期,我拒絕使用bind和callbacks,但是很難跟蹤此類錯誤。
placeholders::_1
告訴std::function
將傳遞的int
參數放在何處。 如我所說,它可以接受額外的參數,但是其中一個將是您的int。 本質上,它的意思是“將您的int值放在這里”。 a
和b
還有其他參數需要傳遞到此函數中,並由活頁夾提供。
Lambdas
Lambda確實為綁定提供了另一種語法,因為您實際上將在其中調用對函數的調用。 我假設,鑒於復雜性,您將在某個地方編寫一個函數和一個類,而您只想使用lambda將回調綁定到它。
在這種情況下,您可以在lambda的方括號中放入所謂的“捕獲”。 這些就像綁定的其他參數一樣。
std::function< int(int) > myFunc = [ &myClassInstance, a, b ]( int x )
{
return myClassInstance.myFunction( a, x, b );
};
這里的捕獲說myClassInstance是一個引用,而其他兩個是按值。 有關捕獲語法的信息,請參見http://en.cppreference.com/w/cpp/language/lambda 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.