Pregunta

Suppose I have:

template<typename T>
class A { 
  typedef T t_type;
  void done_work();
};

template<typename T>
class B { 
  typedef T t_type;
  void do_work(){
    // adds work to an asynchronous event queue, eventually T.done_work() is called
  }
};

template<typename T>
class C { 
  typedef T t_type;
  void do_work(){
    // adds work to an asynchronous event queue, eventually T.done_work() is called
  }
};

typedef A<B<A > > a_with_b;
typedef A<C<A > > a_with_C;

void main(int argc, char** argv){
  a_with_b awb;
  a_with_c awc;
}

How do I resolve the typedef a_with_b?

I want to do this because A has a callback to B, and B has a callback to A. For example, A would call B.do_work(), and eventually B would call A.done_work(). Furthermore, these are each asynchronous calls, so I cannot simply call B.do_work() and wait until B returns "done" because A has other important work to do in the meantime.

The reason I can't just have A take a reference to B is because there can be other implementations that replace B, such as C.

¿Fue útil?

Solución

I want to do this because A has a callback to B, and B has a callback to A. For example, A would call B.do_work(), and eventually B would call A.done_work().

Ideally you'd avoid the interdepencies in the first place, e.g.:

template<class T> struct A {
    std::function<void (T)> handler;
    void f(T) {}
    void work() { handler(T()); }
};
template<class T> struct B {
    std::function<void (T)> fn;
    void f(T) {}
    void work() { handler(T()); }
};

// ..
A<int> a;
B<int> b;
a.handler = std::bind(&B::f, &b);
b.handler = std::bind(&A::f, &a);

Otros consejos

Although I like the type-erasure std::function approach better in this case, it is possible to make your original code work.

Use a template template parameter to define A:

template<template<typename> typename T>
class A { 
  typedef T<A> t_type;
  void done_work();
};

template<typename T>
class B { 
  typedef T t_type;
  void do_work(){
    // adds work to an asynchronous event queue, eventually T.done_work() is called
  }
};

template<typename T>
class C { 
  typedef T t_type;
  void do_work(){
    // adds work to an asynchronous event queue, eventually T.done_work() is called
  }
};

typedef A<B> a_with_b;
typedef A<C> a_with_c;

int main(int argc, char** argv){
  a_with_b awb;
  a_with_c awc;
}

Note that there are just a few changes. Now A takes a template instead of a type.

Also note that B and C is unchanged.

You can't.

At least one of them must not be a template in your case.

Are you sure you need template in this case? If the two classes A and B or A and C are so tightly coupled that one explicitly references another, that seems clearly a case where templates should not be used on classes B and C, because you couldn't specialize any of those class with something else without breaking your whole callback magic.

By the way, a callback library like sigc++ might be what you need.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top