代码之家  ›  专栏  ›  技术社区  ›  P Shved

我可以声明一个可以将指向自身的指针作为参数的函数吗?

  •  11
  • P Shved  · 技术社区  · 15 年前

    foo ,以下是正确的:

    foo(foo);
    

    void*

    void foo(void (*)());
    

    虽然这在C语言中是可以的(并且可以在C++中使用强制转换),但我想知道,是否可以在没有如此困难的“重新解释”强制转换或丢失类型信息的情况下完成。

    换言之,我需要以下声明:

    void foo( void (*)( void (*)( void (*) ( ... ))));
    

    typedef 打电话也没用。

    C++模板是受欢迎的,即使它们生成调用代码( foo(foo) 有限的 .

    C风格的答案表明,一个人如何在不使用强制转换的情况下删除类型信息,或者其他类似的技巧当然很有趣,但不会被接受。

    8 回复  |  直到 15 年前
        1
  •  3
  •   Antoine    9 年前

    总的来说,我同意达里奥的观点——在类型层面上这样做似乎是不可能的。

    class A {
      void evil(A a) {       // a pointer to A is ok too
      }
    };
    

    您甚至可以添加运算符():

      void operator()(A a) { return evil(a); }
    

    data Evil = Evil (Evil -> Integer)
    

    这使用了一个包装器( Evil

    来自提问者 当前位置此答案所缺乏的是将多个不同函数作为其中一个函数的参数传递的能力。这可以通过以下两种方法解决: evil() 虚拟或显式地在对象中存储实现它的函数指针(基本相同)。

    有了这一澄清,答案足够好,可以接受。

        2
  •  5
  •   Community noseratio    7 年前

    this thread . 这里需要的类型总是无限的。

        3
  •  5
  •   Vadakkumpadath    15 年前

    void Foo( ... )
    {
    }
    
    int main()
    {
     Foo( Foo );
    }
    

    上述程序将编译没有任何错误。但它不是递归的。下面修改的函数是带限制器的递归版本。

    #define RECURSIVE_DEPTH (5)
    
    typedef void ( *FooType )( int, ... );
    
    void Foo( int Depth, ... )
    {
     void ( *This )( int, ... );
    
     va_list Arguments;
    
     va_start( Arguments, Depth );
    
     if( Depth )
     {
      This = va_arg( Arguments, FooType );
    
      This( Depth - 1, This );
     }
    
     va_end ( Arguments );  
    }
    
    int main()
    {
     Foo( RECURSIVE_DEPTH, Foo );
    }
    
        4
  •  4
  •   MSalters    15 年前

    它是 "Can you write a function that returns a pointer to itself?" ,除了在您的示例中,函数类型递归地显示为argumkent,而不是返回类型。不过,Herb Sutters的答案是可重用的:将指针封装在前向声明的代理类中。

        5
  •  2
  •   Christoph    15 年前

    一个相关的问题是返回相同类型的函数指针。它在实现状态机时出现,因此它有自己的 entry in the C FAQ .

    同样的解决方法也适用于您的问题。

        6
  •  1
  •   ZachS    15 年前

    我不相信你能有一个函数,它可以在C++中作为一个自变量,而不需要某种欺骗,比如把你的函数放在一个类中,并让函数把这个类当作一个参数。

    一旦新的C++标准命中,另一种可能的方法是使用lambda,并使lambda自己捕获。我想应该是这样的:

    auto recursive_lambda = [&recursive_lambda] { recursive_lambda(); };
    

    请注意,这种语句在任何支持lambdas的编译器中都是完全未经测试的。您的里程可能会有所不同。

        7
  •  0
  •   DigitalRoss    15 年前

    这是一个非常有效的用法 void * .

    typedef void T(void *);
    
    void f(T *probably_me)
    {
      (*probably_me)(f);
    }
    
        8
  •  0
  •   newacct    15 年前

    如果函数可以将自身作为参数,那么它可以通过调用自身来执行匿名递归。但在简单类型的lambda演算中,递归是不可能的(这基本上就是这里的函数类型)。为了执行匿名递归,需要使用递归函数或递归类型实现定点组合器。