简体   繁体   English

函数可以返回指向自己类型的指针吗?

[英]Can a function return a pointer to its own type?

I've implemented a very minimal finite state machine in a class, and my original approach was to try this: 我在一个类中实现了一个非常小的有限状态机,我最初的方法是尝试这个:

class Widget {
public:
  void update(float time_interval){
    current_state = current_state_(time_interval);
  }
private:
  std::function<  ??  > off_(float);
  std::function<  ??  > standby_(float);
  std::function<  ??  > locked_(float);

  std::function<  ??  > current_state_; // initialised to off_
};

Each state is a function which returns a state. 每个状态都是一个返回状态的函数。 But I can't work out how to declare a function whose return type includes its return type. 但我无法弄清楚如何声明一个返回类型包含其返回类型的函数。 Is there a way to break the recursion? 有没有办法打破递归?

Instead, I used an enum class and an ugly switch statement. 相反,我使用了enum class和丑陋的switch语句。

If I understand correctly, you want to return a function reference to the next function in the state chain, and that all the state step functions have identical signature? 如果我理解正确,你想要返回一个函数引用到状态链中的下一个函数,并且所有状态步骤函数都具有相同的签名?

I see the problem here is that the return type is the function itself, so declaring the type of the function invokes a recursive type definition. 我看到这里的问题是返回类型是函数本身,因此声明函数的类型会调用递归类型定义。

So you want to write functions of the form RetType fn_(float) but the type of RetType is (basically) RetType fn_(float) . 所以你想编写RetType fn_(float)形式的函数,但RetType的类型是(基本上) RetType fn_(float) So now we have (RetType (*)(float)) fn_(float) or something like that, but however hard we try we can't get rid of RetType. 所以现在我们有(RetType (*)(float)) fn_(float)或类似的东西,但是我们努力尝试我们无法摆脱RetType。

You can't shut down that recursion without forward declaring something. 如果不向前声明某些内容,就无法关闭该递归。 We can forward declare classes, and use them, so let's write a simple class wrapper for your function pointer, which is perhaps what @Jarod was alluding to. 我们可以转发声明类,并使用它们,所以让我们为你的函数指针编写一个简单的类包装器,这可能是@Jarod所暗示的。 Now, std::function is sort-of a class wrapper for your function, but it needs the explicit type declaration, which we don't have. 现在,std :: function是函数的类包装器,但它需要显式类型声明,我们没有。

class Widget;
class StateFn;
class StateFn
{
  Widget * THIS;
  StateFn (Widget::*Fn)(float);
public:
  /// Or you could rely on POD construction
  StateFn(Widget * THIS, StateFn (Widget::*Fn)(float))
  : THIS(THIS), Fn(Fn)
  {}
  StateFn operator()(float f)
  {
    return THIS->*fn(f);
  }
};

So now the recursive definition is broken, our state functions can return StateFn objects, and we can call on them. 所以现在递归定义被破坏了,我们的状态函数可以返回StateFn对象,我们可以调用它们。

I've found a solution - using std::unordered_map to substitute the ugly switch : 我找到了一个解决方案 - 使用std::unordered_map代替丑陋的switch

class Widget {
public:
  enum class State { Off, Standby, Locked };

  void update(float time_interval) {
    current_state_ = (this->*state_fn_.at(state_))(time_interval);
  }

private:
  State off_(float) {return ::has_power() ? State::Standby : State::Off;}
  State standby_(float);
  State locked_(float);

  const std::unordered_map<State, State(Widget::*)(float)> state_fn_{
      {State::Off,     &Widget::off_},
      {State::Standby, &Widget::standby_},
      {State::Locked,  &Widget::locked_}};

  State current_state_{State::Off};
};

It's only 1+3n lines of code worse than the ideal code I put in the question - I'm pretty happy with this! 它只有1 + 3n行代码比我在问题中提出的理想代码更差 - 我对此非常满意!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM