【问题标题】:Getting into a mess with std::function and member function pointers : ( [duplicate]陷入与 std::function 和成员函数指针的混乱:( [重复]
【发布时间】:2018-04-13 02:42:13
【问题描述】:

所以,我以为我已经理解了成员函数指针和 std::fction,但遗憾的是还不是这样。

我有以下代码 - 它是状态机的一些早期部分,但我很挣扎。让我粘贴代码:

#include <iostream>
#include <functional>
#include <map>

//forward decls
class state_t;

enum event_t
{
    ev_start = 0,
    ev_middle,
    ev_end
};

struct transition_t
{

    //std::function<bool()> guard_function();
    std::function<bool()> guard_function;
    state_t *p_next_state;
};

class state_t
{
public:
    std::map<event_t, transition_t> transitions;

    bool some_guard()
    {
        std::cout << "check the guard condition - all is well" << std::endl;
        return true;
    }
};

int main()
{
    std::cout << "Hello World!" << std::endl;

    state_t s1;
    state_t s2;

    // Setup transitions

    s1.transitions[event_t::ev_start]  = transition_t{s1::some_guard, &s2};
    s1.transitions[event_t::ev_middle] = transition_t{nullptr, &s2}; // no guard

    event_t test_event = event_t::ev_start;

    auto trans = s1.transitions.find(event_t::ev_start);
    if (trans != s1.transitions.end())
    {
        // change state - TBD
        std::cout << "changingn state" << std::endl;
    }

    return 0;
}

好的,所以:

  • event_t 只是一些枚举
  • transition_t 包含一个指向某个保护函数的指针,该函数返回一个布尔值和一个指向下一个状态的指针。
  • state_t 有一个事件和转换映射,并包含一些可以存储在 transition_t 中的保护函数。

所以在 main() 中我正在尝试构建一些状态...

s1.transitions[event_t::ev_start]  = transition_t{s1::some_guard, &s2};   // <--- this line fails
s1.transitions[event_t::ev_middle] = transition_t{nullptr, &s2}; // <--- this line works (not so surprised)

但我不太清楚如何排序。我过去用 lambdas 和模板做到了这一点......但我真的很想给 std::function 一个机会,看看它是否更好/更容易......

欢迎任何指针/指南在这里做什么,即使它使用 lambdas :),但我更愿意让 std::function 工作

【问题讨论】:

  • 请注意,以_t 结尾的名称由 POSIX 保留,在这种情况下,您的角色可能无法在 POSIX 系统上运行。
  • @rubenvb 哦,伙计....但是很难找到一个好名字:( ...stateevent - 但好点:)
  • 注:除了提供一个对象来调用成员函数(如副本中所述),您还需要使用正确的语法来形成一个指向成员的指针:&amp;state_t::some_guard not s1::some_guard
  • 只需删除预先构建的 amd 后缀,如果您遇到 Amy 歧义,只需将它们移动到命名空间中;)
  • @JonathanWakely - 是的,我一直在尝试很多东西 - 这是我放弃并来到这里后的最后一次努力!谢谢 :) .. ps 对不起所有的重复

标签: c++ c++11 std-function


【解决方案1】:

这应该可以工作,因为您需要将成员函数绑定到它是实例。

感谢下面的@Barry 评论,使用 lambda 解决方案而不是 bind 看起来要好得多

s1.transitions[event_t::ev_start] = transition_t{ [&s1] { return s1.some_guard(); }, &s1 };
s1.transitions[event_t::ev_start] = transition_t{ std::bind(&state_t::some_guard, &s1), &s1 };

我发现了一些关于 bind vs lambda 的性能线程。 std::bind vs lambda performance

lambda 函数看起来更容易阅读。

【讨论】:

  • 确实如此,先生! - bind 是我还没有使用过的关键成分,谢谢 :)
  • 首选[&amp;s1]{ return s1.some_guard(); } 而不是bind()。它在所有重要方面都更好(在这种情况下,它甚至比 bind() 更短!)
猜你喜欢
  • 2015-03-09
  • 2017-08-27
  • 1970-01-01
  • 2013-05-07
  • 2014-02-11
  • 1970-01-01
  • 1970-01-01
  • 2010-12-27
  • 2019-06-14
相关资源
最近更新 更多