自我指涉型

pyt*_*hor 4 c c++ types self-reference

什么类型的T使以下代码可编辑?

T f(){ return &f; }
Run Code Online (Sandbox Code Playgroud)

我更喜欢C答案,但我将问题标记为C和C++,以防只有使用模板的答案.

zil*_*n01 9

我希望这不是作弊(仅限C++):

class T {
private:
    T (*_func)();

public:
    T(T (*func)()) : _func(func) {}

    T operator()() {
        return *this;
    }
};

T f() { return &f; }

int main() {
    f()()()()()()()();
}
Run Code Online (Sandbox Code Playgroud)


pae*_*bal 9

有趣的问题,但没有可接受的C解决方案,我想.

为什么C不可能这样做?(这里有一些猜测)

返回T的函数的类型是:

T (*)(void) ;
Run Code Online (Sandbox Code Playgroud)

当然,期望T被定义......但是,由于T是函数本身的类型,因此存在循环依赖.

对于struct T,我们可以:

struct T ;               /* forward declaration */
typedef T * (*f)(void) ; /* f is a function returning a pointer to T */
Run Code Online (Sandbox Code Playgroud)

下一个符号不是很方便吗?

function T ; /* fictional function forward-declaration.
                It won't compile, of course */
T T(void) ;  /* function declaration */
Run Code Online (Sandbox Code Playgroud)

但由于无法向前声明函数,因此无法使用您在问题中编写的构造.

我不是编译器律师,但我认为这种循环依赖只是因为typedef表示法创建的,而不是因为C/C++限制.毕竟,函数指针(我在这里讨论函数,而不是对象方法)都具有相同的大小(以相同的方式,struct或class指针都具有相同的大小).

学习C++解决方案

至于C++解决方案,以前的答案给出了很好的答案(我在考虑zildjohn01的答案,这里).

有趣的是,它们都基于结构和类可以向前声明的事实(并且在其声明体中被认为是向前声明的):

#include <iostream>

class MyFunctor
{
   typedef MyFunctor (*myFunctionPointer)() ;
   myFunctionPointer m_f ;
   public :
      MyFunctor(myFunctionPointer p_f) : m_f(p_f) {}
      MyFunctor operator () ()
      {
         m_f() ;
         return *this ;
      }
} ;

MyFunctor foo()      {
   std::cout << "foo() was called !" << std::endl ;
   return &foo ;
}

MyFunctor barbar()   {
   std::cout << "barbar() was called !" << std::endl ;
   return &barbar ;
}

int main(int argc, char* argv[])
{
   foo()() ;
   barbar()()()()() ;
   return 0 ;
}
Run Code Online (Sandbox Code Playgroud)

哪个输出:

foo() was called !
foo() was called !
barbar() was called !
barbar() was called !
barbar() was called !
barbar() was called !
barbar() was called !
Run Code Online (Sandbox Code Playgroud)

C++解决方案的灵感来达到C解决方案

难道我们不能在C中使用类似的方法来获得可比较的结果吗?

不知何故,是的,但结果并不像C++解决方案那样性感:

#include <stdio.h>

struct MyFuncWrapper ;

typedef struct MyFuncWrapper (*myFuncPtr) () ;

struct MyFuncWrapper { myFuncPtr f ; } ;

struct MyFuncWrapper foo()
{
   printf("foo() was called!\n") ;

   /* Wrapping the function */
   struct MyFuncWrapper w = { &foo } ; return w ;
}

struct MyFuncWrapper barbar()
{
   printf("barbar() was called!\n") ;

   /* Wrapping the function */
   struct MyFuncWrapper w = { &barbar } ; return w ;
}

int main()
{
   foo().f().f().f().f() ;
   barbar().f().f() ;

   return 0 ;
}
Run Code Online (Sandbox Code Playgroud)

哪个输出:

foo() was called!
foo() was called!
foo() was called!
foo() was called!
foo() was called!
barbar() was called!
barbar() was called!
barbar() was called!
Run Code Online (Sandbox Code Playgroud)

结论

您将注意到C++代码在语义上与C代码非常相似:每个源将使用结构作为函数指针的容器,然后,如果需要,使用包含的指针再次调用它.当然,C++解决方案使用operator()重载,使符号私有,并使用特定的构造函数作为语法糖.

(这就是我找到C解决方案的方法:尝试"手动"重现C++解决方案)

我不相信我们可以通过使用宏来改进C解决方案的语法糖,所以我们坚持使用这个C解决方案,我发现它远非令人印象深刻,但在找到它的时候仍然很有趣.

毕竟,寻找奇怪问题的解决方案是学习的可靠方法......

:-)