Reputation: 2591
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.
Upvotes: 2
Views: 1335
Reputation: 697
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.
Upvotes: 2
Reputation: 13443
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.
Upvotes: 1
Reputation: 98984
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);
Upvotes: 2