【问题标题】:How to typedef a pointer to method which returns a pointer the method?如何键入一个指向方法的指针,该方法返回该方法的指针?
【发布时间】:2010-09-14 17:29:35
【问题描述】:

基本上我有以下课程:

class StateMachine {
...
StateMethod stateA();
StateMethod stateB();
...
};

stateA() 和 stateB() 方法应该能够返回指向 stateA() 和 stateB() 的指针。 StateMethod如何typedef?

【问题讨论】:

  • 哇,在我看来,这个问题比想象的要困难得多。如果您愿意破坏完整的类型安全,有各种各样的方法可以解决它,但除此之外......哇。

标签: c++ member-function-pointers


【解决方案1】:

我永远记不起可怕的 C++ 函数 declspec,所以每当我必须找出描述成员函数的语法时,我只会引发一个故意的编译器错误,该错误通常会为我显示正确的语法。

所以给定:

class StateMachine { 
    bool stateA(int someArg); 
};

stateA 的 typedef 的语法是什么?不知道..所以让我们试着给它分配一些不相关的东西,看看编译器是怎么说的:

char c = StateMachine::stateA

编译器说:

error: a value of type "bool (StateMachine::*)(int)" cannot be used to initialize 
       an entity of type "char" 

它是:“bool (StateMachine::*)(int)”是我们的类型定义。

【讨论】:

    【解决方案2】:

    编辑:njsf 在这里证明我错了。但是,您可能会发现静态转换更易于维护,因此我将把剩下的留在这里。

    没有“正确”的静态类型,因为完整类型是递归的:

    typedef StateMethod (StateMachine::*StateMethod)();
    

    最好的办法是使用typedef void (StateMachine::*StateMethod)();,然后使用丑陋的state = (StateMethod)(this->*state)();

    PS:boost::function 需要明确的返回类型,至少从我对docs 的阅读来看:boost::function0<ReturnType>

    【讨论】:

    • 是的,这是我在问题 cmets.xml 中提到的“中断类型安全”方法。太糟糕了,真的。我确实希望有一种方法可以干净地解决这个问题。也许 C++0x 会提供一种方法?
    • 不,这实际上是 不可能 具有热切评估的类型系统 - 不仅仅是 C++ 的。你需要一个惰性求值的类型系统。
    【解决方案3】:

    GotW #57 表示为此目的使用具有隐式转换的代理类。

    struct StateMethod;
    typedef StateMethod (StateMachine:: *FuncPtr)(); 
    struct StateMethod
    {
      StateMethod( FuncPtr pp ) : p( pp ) { }
      operator FuncPtr() { return p; }
      FuncPtr p;
    };
    
    class StateMachine {
      StateMethod stateA();
      StateMethod stateB();
    };
    
    int main()
    {
      StateMachine *fsm = new StateMachine();
      FuncPtr a = fsm->stateA();  // natural usage syntax
      return 0;
    }    
    
    StateMethod StateMachine::stateA
    {
      return stateA; // natural return syntax
    }
    
    StateMethod StateMachine::stateB
    {
      return stateB;
    }
    

    这个解决方案有三个主要的 强项:

    1. 它可以根据需要解决问题。更好的是,它是类型安全的,并且 便携。

    2. 它的机制是透明的:您可以获得自然的语法 调用者/用户和自然语法 函数自己的“返回状态A;” 声明。

    3. 它的开销可能为零:在现代编译器上,代理类, 以其存储和功能,应 内联并优化到无。

    【讨论】:

    • 不能将成员函数指针转换为常规函数指针,但在其他方面很酷。我应该指出,你仍然只是在给演员加糖:)。
    • 我已经 5 年没有做过任何 C++ 开发了,并且很高兴地忘记了成员函数指针。是的,我同意这只是你回答中演员的糖:)
    • 如果你改变 typedef 应该没问题吧? typedef StateMethod (StateMachine:: *FuncPtr)();
    • 啊,这就是我想要的语法。谢谢!
    【解决方案4】:

    只使用 typedef:

    class StateMachine {  
    
     public:  
    
      class StateMethod;     
      typedef StateMethod (StateMachine::*statemethod)();   
    
      class StateMethod {  
    
        statemethod   method; 
        StateMachine& obj; 
    
       public:  
    
        StateMethod(statemethod method_, StateMachine *obj_)  
          : method(method_), obj(*obj_) {} 
    
        StateMethod operator()() { return (obj.*(method))(); }  
      };  
    
      StateMethod stateA()  { return StateMethod(&StateMachine::stateA, this); }  
    
      StateMethod stateB()  { return StateMethod(&StateMachine::stateB, this); }  
    
    };    
    

    【讨论】:

      【解决方案5】:

      我的理念是不要使用原始成员函数指针。我什至不知道如何使用原始指针 typedef 来做你想做的事,语法太可怕了。我喜欢使用 boost::function。

      几乎肯定是错的:

      class X
      {
        public:
          typedef const boost::function0<Method> Method;
      
          // some kind of mutually recursive state machine
          Method stateA()
          { return boost::bind(&X::stateB, this); }
          Method stateB()
          { return boost::bind(&X::stateA, this); }
      };
      

      这个问题肯定比第一次看到要难很多

      【讨论】:

      • 嘿,我看到了你之前的回答。这可能是最好的折衷方案;我在 IRC 上讨论过这个问题并得出结论,引用自身的 typedef 可能是一个“太难”的问题。
      • 不过,在内部的 boost::function0 中,你不必提供返回类型,然后再次进行递归吗?
      • 可能,我没有坐在编译器前
      • 这听起来像是用模板元编程语言编写的 Y 组合器的完美工作
      • @1800 信息:是的,我的第一个想法是“好吧,我将在 typedefs 上写一个 Y Combinator ......哦,男孩。:(”
      猜你喜欢
      • 1970-01-01
      • 2021-09-21
      • 1970-01-01
      • 2011-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-05
      • 1970-01-01
      相关资源
      最近更新 更多