陷入混乱 std::function 和成员函数指针:(
Getting into a mess with std::function and member function pointers : (
所以,我以为我已经理解了成员函数指针和 std::fuction,但遗憾的是,事实并非如此。
我有以下代码 - 它是状态机的一些早期部分,但我正在努力。让我粘贴代码:
#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
意味着包含一个指向某个保护函数的指针,returns 一个 bool 和一个指向下一个状态的指针。
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)
但我不太明白如何对此进行排序。我过去曾使用 lambda 和模板完成过此操作...但我真的很想 std::function 去看看它是否更好/更容易...
任何 pointers/guides 这里做什么都会受到欢迎,即使它使用 lambdas :),但我更愿意 std::function 工作
这应该可以工作,因为您需要将成员函数绑定到它的实例。
感谢下面的@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 };
我发现了一些关于绑定与 lambda 的性能线程。
std::bind vs lambda performance
lambda 函数看起来更易于阅读。
所以,我以为我已经理解了成员函数指针和 std::fuction,但遗憾的是,事实并非如此。
我有以下代码 - 它是状态机的一些早期部分,但我正在努力。让我粘贴代码:
#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
意味着包含一个指向某个保护函数的指针,returns 一个 bool 和一个指向下一个状态的指针。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)
但我不太明白如何对此进行排序。我过去曾使用 lambda 和模板完成过此操作...但我真的很想 std::function 去看看它是否更好/更容易...
任何 pointers/guides 这里做什么都会受到欢迎,即使它使用 lambdas :),但我更愿意 std::function 工作
这应该可以工作,因为您需要将成员函数绑定到它的实例。
感谢下面的@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 };
我发现了一些关于绑定与 lambda 的性能线程。 std::bind vs lambda performance
lambda 函数看起来更易于阅读。