Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare two functions taking each other's signature as argument?

Is it possible to emulate something like this:

typedef boost::function<void(A)> B;
typedef boost::function<void(B)> A;

The main goal is to be able to write code like this (in pseudo-c++):

void a_(B b) {
  // ...
  b(a_);
}
void b_(A a) {
  // ...
  f(boost::bind(a, b_));
}

f(boost::bind(a_, b_));
like image 885
abyss.7 Avatar asked Dec 13 '11 08:12

abyss.7


2 Answers

Your question is not technically precise. A signature is not something you pass as argument. I try my best to make sense of your question.

The following function objects can be passed as argument to each other

struct foo { 
  template<typename T> void operator()(T);
};

struct bar {
  template<typename T> void operator()(T);
};

foo f; bar b;
like image 90
Johannes Schaub - litb Avatar answered Nov 13 '22 20:11

Johannes Schaub - litb


Not directly possible with typedefs; wherever a typedef is used, it is equivalent to the original type, so if you write

typedef boost::function<void(A)> B;
typedef boost::function<void(B)> A;

then B would be equivalent to boost::function<void(A)>, which is equivalent to boost::function<void(boost::function<void(B)>)>, and so on, until you get

boost::function<void(boost::function<void(boost::function<void(...)>)>)>

, which is a type of infinite length.

You can, however, define (at least) one of the two types as a struct or class:

struct A;
typedef boost::function<void(A)> B;
struct A
{
    B b;
    A(B b) : b(b) {}

    // optional:
    void operator() (A a) { b(a); }
};

You might need to add more constructors and/or a conversion operator to make the type behave completely "transparently", or you could just access the struct explicitly.

like image 22
wolfgang Avatar answered Nov 13 '22 21:11

wolfgang