Вернуть указатель функции на себя? - PullRequest
7 голосов
/ 07 мая 2011

Следующий код не компилируется ... но есть ли способ получить указатель на функцию для возврата другого указателя на функцию, который эквивалентен самому себе?

typedef FunctionPtr (*FunctionPtr)(int, int);

FunctionPtr Second(int, int);
FunctionPtr First(int, int)
{
    // do something
    return Second;
}

FunctionPtr Second(int, int)
{
    // do something
    return First;
}

int main()
{
    FunctionPtr a = First(1, 2);
    FunctionPtr b = a(2, 3);
    FunctionPtr c = b(4, 5);
    c(5, 6);
}

Ответы [ 4 ]

5 голосов
/ 08 мая 2011

Краткий ответ: Нет, вы не можете сделать это напрямую. Вы можете приблизиться, используя указатели void, но это нестандартно, поскольку указатель void не обязательно будет достаточно большим, чтобы соответствовать указателю функции. Подробнее см. Гуру недели # 57 .

Ближайший совместимый со стандартами подход заключается в определении типа оболочки для указателя функции:

 struct Wrapper;
 typedef Wrapper (*FunctionPtr)(int, int);
 struct Wrapper {
    Wrapper(FunctionPtr ptr): wrapped(ptr) { }
    operator FunctionPtr() { return wrapped; }
    FunctionPtr wrapped;
 };

Теперь вы можете написать:

Wrapper Second(int, int);
Wrapper First(int, int) {
    // do something
    return Second;
}

Wrapper Second(int, int) {
    // do something
    return First;
}

int main() {
    FunctionPtr a = First(1, 2);
    FunctionPtr b = a(2, 3);
    FunctionPtr c = b(4, 5);
    c(5, 6);
}
2 голосов
/ 08 мая 2011

Здесь есть несколько умных решений C ++, но я всегда видел решение C на чистом языке, просто использующее небольшое приведение:

typedef void (*func)(void);

func myfunc(int, int) { return (func)myfunc); }
// optional
typedef func (*myfunctype)(int, int);

// calling code
myfunctype x = myfunc;
while(x) x = (myfunctype)x(2, 3);

Стандарт требует, чтобы указатель функции, приведенный к другому типу указателя функции и обратно , был равен исходному указателю функции, что делает этот код полностью надежным.

1 голос
/ 08 мая 2011

Это было ближе всего к 15 минутам ...:

#include <stdio.h>

struct container
{
    typedef container (*Ptr)(int, int);
    const Ptr _ptr;
    explicit container(Ptr ptr) : _ptr(ptr) { }
    operator Ptr() const { return _ptr; }
};

struct container narcissus(int a, int b)
{
  printf("Narcissus: %i %i.\n", a, b);

  return container(narcissus);
}

int main(void)
{
  narcissus(3, 4)(5, 6)(7, 8);
  return 0;
}

Теперь, чтобы сделать этого ребенка общим для N параметров, оставляем читателю в качестве упражнения:)

0 голосов
/ 08 мая 2011

Это невозможно из-за проверки типа.Это потребовало бы, чтобы компиляторы решали фиксированные точки при проверке их типов, и в настоящее время компиляторы не могут это сделать.

Самое близкое, что вы можете сделать, это абстрагировать возвращаемый тип с помощью наследования:

template<class T>
class Function { public: virtual void Map(T t)=0; };

template<class T, class K>
class FunctionPtr : public Function<T> {
public:
  FunctionPtr(K (*fptr)(T)) : fptr(fptr) { }
  void Map(T t) { fptr(t); }
private:
  K (*fptr)(T);
};

Function<int> *my_function(int i)
{
   return new FunctionPtr<int,Function<int>*>(&my_function);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...