簡體   English   中英

C ++如何將成員函數轉換為獨立函數(用作函數參數)?

[英]C++ how to convert member functions to standalone functions (for use as function parameter) generically?

對於模板函數的函數參數,我發現自己經常將成員函數包裝在lambda中以創建相同的獨立函數,第一個參數是對象。

一個(虛擬)示例:

class A
{
public:
    double f1() const;
    double f2(int i) const;

    // some data
};

template <typename Func>
double calculateSum(std::vector<A> as, Func f)
{
    double result = 0.0;
    for (auto a : as)
        result += f(a);
    return result;
}

int main()
{
    std::vector<A> as;
    int i = 0;
    auto sum1 = calculateSum(as, [](const A& a) { return a.f1(); });
    auto sum2 = calculateSum(as, [&i](const A& a) { return a.f2(i); });
    return 0;
}

有沒有辦法更一般地定義這樣的lambdas? 或者有沒有辦法直接引用成員函數而不是使用lambdas?

您可以使用C ++ 14通用lambdas來幫助解決這個問題。 像這樣定義你的通用lambda:

auto bindMem = [](auto f, auto& ... memArgs) { return [f, &memArgs...](auto& a) { return (a.*f)(memArgs...); }; };

要消化:這會創建一個通用的lambda,其調用會產生另一個lambda。 第一拉姆達讓你要調用的成員函數,與任何綁定參數(比其他this對象)。 它生成第二個lambda,然后它就會期望對象本身並使用先前綁定的參數對其應用成員函數調用。

因此,對於您的用例,您看起來很整潔:

auto sum1 = calculateSum(as, bindMem(&A::f1));
auto sum2 = calculateSum(as, bindMem(&A::f2,i));

關於這一點的bindMem是,完全相同的bindMem lambda將適用於任何類和任何成員函數,具有任意參數列表。 因此,你的意思是它真的是通用的。

你可以使用std::bind()

綁定需要一個函數,無論你想要多少參數,都會返回一個很好的std::function對象。 您可以在創建時指定參數,也可以在調用返回的函數時使用占位符指定它們。

#include <functional>
...
auto sum1 = calculateSum(as, std::bind(&A::f1, std::placeholders::_1));
auto sum2 = calculateSum(as, std::bind(&A::f2, std::placeholders::_1, i);

請記住,非靜態成員函數將類實例作為它們的第一個參數(盡管大多數情況下它是隱式完成的,但這不是其中之一),這就是我們使用占位符的原因。 當你現在執行f(a)時, a (類實例)將替換該占位符。

進一步閱讀: 綁定占位符

經過一番研究,感謝@happydave的建議,我將回答以下問題:

auto sum1 = calculateSum(as, std::mem_fn(&A::f1));

第二筆金額不能這樣處理,應該保持為lambda。 但是,一般來說,似乎客戶端代碼是參數的供應商的可能性較小(在這種情況下,參數需要以任何方式傳遞給模板函數(並且lambda捕獲是一種很好的方式))。 在許多情況下,模板函數也提供傳遞函數的參數,std :: mem_fn也沒問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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