如何使用lambdas使用std ::函数与成员函数?

发布于 01-21 22:26 字数 1296 浏览 3 评论 0原文

我正在尝试在课堂内移动一些全局功能。当前的代码看起来像这样:

struct S{};

void f(S* s, int x, double d){}
void g(S* s, int x, double d){}
/*
...
...*/
void z(S* s, int x, double d){}

int main()
{
    function<void(S*, int, double)> fp;
    
    //switch(something)
    //case 1:
        fp = f;
    //case 2:
        fp = g;
    //case n:
        fp = z;
}

假设我想将上述代码更新为类似的代码(此代码bellow不编译):

#include <iostream>
#include <functional>

using namespace std;

struct S
{
    void f(int x, double d){}
    void g(int x, double d){}
    /*
    ...
    ...*/
    void z(int x, double d){}    

    void method_that_has_some_logic_to_use_the_others_above(int x, double d)
    {
        function<void(int, double)> fp; // How do I have to declare here?
        //switch(something)
        //case 1:
        fp = f; // How can achieve something like this using lambdas here?
    //case 2:
        fp = g;
    //case n:
        fp = z;

        fp(x, d);
    }

};


int main()
{
    S s;
    s.method_that_has_some_logic_to_use_the_others_above(10, 5.0);
}

我使用std :: bind看到了一些解决方案,但在某个地方读取以避免使用它并更喜欢lambdas。我正在使用C ++ 17,但是我在Lambdas方面几乎没有经验,无法通过在其他答案中找到的示例来弄清楚如何解决它。

I'm trying to move some global functions inside a class. The current code looks like this:

struct S{};

void f(S* s, int x, double d){}
void g(S* s, int x, double d){}
/*
...
...*/
void z(S* s, int x, double d){}

int main()
{
    function<void(S*, int, double)> fp;
    
    //switch(something)
    //case 1:
        fp = f;
    //case 2:
        fp = g;
    //case n:
        fp = z;
}

Suppose I wanted to update the code above to something like (this code bellow doesn't compile):

#include <iostream>
#include <functional>

using namespace std;

struct S
{
    void f(int x, double d){}
    void g(int x, double d){}
    /*
    ...
    ...*/
    void z(int x, double d){}    

    void method_that_has_some_logic_to_use_the_others_above(int x, double d)
    {
        function<void(int, double)> fp; // How do I have to declare here?
        //switch(something)
        //case 1:
        fp = f; // How can achieve something like this using lambdas here?
    //case 2:
        fp = g;
    //case n:
        fp = z;

        fp(x, d);
    }

};


int main()
{
    S s;
    s.method_that_has_some_logic_to_use_the_others_above(10, 5.0);
}

I've seen some solutions using std::bind but read somewhere to avoid using it and prefer lambdas. I'm using C++17, but I have little experience with lambdas and wasn't able to figure out how to solve it with the examples I've found in other answers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

简单气质女生网名 2025-01-28 22:26:58

成员函数需要一个特定的类对象来调用,因此您需要做

function<void(S*, int, double)> fp = &S::f; 
fp(this, x, d);

或使用lambda捕获特定的类对象并在内部调用其成员函数

function<void(int, double)> fp = [this](int x, double d) { this->f(x, d); };
fp(x, d);

demo

Member functions require a specific class object to invoke, so you need to do

function<void(S*, int, double)> fp = &S::f; 
fp(this, x, d);

Or use lambda to capture a specific class object and invoke its member function internally

function<void(int, double)> fp = [this](int x, double d) { this->f(x, d); };
fp(x, d);

Demo

小巷里的女流氓 2025-01-28 22:26:58

注意:我正在提出另一种方法 。


只要您只是在成员函数之间选择具有相同签名以调用的给出 。开销可能并不重要,如果您需要扩展简单的会员功能调用,则确实具有更大的灵活性。另一方面,指针到会员功能提供了类似的功能,而无需开销。

缺点(对我来说)是语法。在这种情况下,类型为void(s ::*)(int,double),如果您不习惯指向成员,则很难阅读。最重要的是,被声明的变量在类型的中间进行,这再次损害了可读性。不过,如果您可以接受语法:

// Placeholder for the decision-making process:
char choose_fun() { return 'g'; }

// Same setup for `S` as in the question, except with the following added:
void S::other_method(int x, double d)
{
    void (S::* fp)(int, double);  // Manual type specification
    // decltype(&S::other_method) fp;  // Possibly easier to read

    switch (choose_fun()) {
        case 'f': fp = &S::f; break;
        case 'g': fp = &S::g; break;
        // ...
    }

    // More processing?

    // The syntax for invoking a pointer-to-member is also a bit weird.
    (this->*fp)(x, d);
}

实际上,如果设置的确与问题所示的简单(简单的switch来决定要拨打什么),我可能不会打扰任何一个指针或std :: function在此设置中。我将存储switch使用的值,然后通过助手函数调用功能。 (如果没有其他处理,则ether_method简化了助手功能。)

// The helper function.
void S::choose_method(char choice, int x, double d)
{
    switch (choice) {
        // Returning void is legal and takes the place of having a `break`.
        case 'f': return f(x, d);
        case 'g': return g(x, d);
        // ...
    }
}

// Now the other method needs very little code in addition to the additional
// processing, whatever that is. This also brings the code closer to the
// ideal of one task per function.
void S::other_method(int x, double d)
{
    char choice = choose_fun();

    // More processing
        
    choose_method(choice, x, d);
}

Note: I'm presenting an alternative approach because the OP could not justify the use of std::function (and because an answer to the literal question has already been given by 康桓瑋).


As long as you are just choosing between member functions with the same signature to invoke, a std::function is has unnecessary overhead. The overhead is probably not critical, and you do have more flexibility if you need to expand beyond a simple member function call. On the other hand, a pointer-to-member-function provides similar functionality without the overhead.

The downside (for me) is the syntax. The type in this case is void (S::*)(int, double), which is hard to read if you're not used to pointers-to-member. On top of that, the variable being declared goes in the middle of the type, which again hurts readability. Still, if you can accept the syntax:

// Placeholder for the decision-making process:
char choose_fun() { return 'g'; }

// Same setup for `S` as in the question, except with the following added:
void S::other_method(int x, double d)
{
    void (S::* fp)(int, double);  // Manual type specification
    // decltype(&S::other_method) fp;  // Possibly easier to read

    switch (choose_fun()) {
        case 'f': fp = &S::f; break;
        case 'g': fp = &S::g; break;
        // ...
    }

    // More processing?

    // The syntax for invoking a pointer-to-member is also a bit weird.
    (this->*fp)(x, d);
}

Actually, if the setup really is as simple as presented in the question (a simple switch to decide what to call), I probably wouldn't bother with either pointers or std::function in this setup. I would store the value used by the switch, then call the functions via a helper function. (If there is no additional processing, then other_method simplifies to the helper function.)

// The helper function.
void S::choose_method(char choice, int x, double d)
{
    switch (choice) {
        // Returning void is legal and takes the place of having a `break`.
        case 'f': return f(x, d);
        case 'g': return g(x, d);
        // ...
    }
}

// Now the other method needs very little code in addition to the additional
// processing, whatever that is. This also brings the code closer to the
// ideal of one task per function.
void S::other_method(int x, double d)
{
    char choice = choose_fun();

    // More processing
        
    choose_method(choice, x, d);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文