簡體   English   中英

創建一個帶有狀態的C ++ 11 std :: function <>

[英]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::bindstd::function現在已成為C ++ 11標准的一部分,而以前它們是boost庫的一部分並在tr1中受支持或作為各種標准庫的擴展。 (不是編譯器,它們已經按照C ++ 98/03標准進行了編譯,但是它們是作為庫功能添加的)。

Lambdas是一種新的語言功能,當您確實希望在不適合循環的sortremove_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_ptrstd::unique_ptr reference-wrapper是一個包含引用的特殊類,因為自動模板推導將無法知道您實際上是要傳遞引用還是按值。 使用參考包裝器時要小心。 該引用在函數調用時必須仍然有效,並且這種方式已經發生了許多難以發現的錯誤。 實際上,在早期,我拒絕使用bind和callbacks,但是很難跟蹤此類錯誤。

placeholders::_1告訴std::function將傳遞的int參數放在何處。 如我所說,它可以接受額外的參數,但是其中一個將是您的int。 本質上,它的意思是“將您的int值放在這里”。 ab還有其他參數需要傳遞到此函數中,並由活頁夾提供。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM