Wednesday, June 04, 2008

Circular Template References in C++

I wanted to have three template classes, designed to work together, that could use facilities in one another, in such a way that any of the three classes could be replaced with a different version--something like what "Boris" describes here, just more complex.

It didn't seem possible and I had just about given up--I decided instead that I would give each class a non-template base class with limited functionality, and then each class would access the other two classes through this more limited interface. But on the train on the way home from work it hit me: a special "traits" class would make it possible to use circular references between templates. Here is an example:
#include <stdio.h>

template<class Combo> struct A
typedef typename Combo::b_t B;
B* b;

template<class Combo> struct B
typedef typename Combo::a_t A;
A* a;

struct MyCombo {
typedef A<MyCombo> a_t;
typedef B<MyCombo> b_t;

int main(int argc, char* argv[])
A<MyCombo> a;
B<MyCombo> b;
a.b = &b;
b.a = &a;
return 0;


At 12/16/2011 9:47 AM, Blogger Justin said...

Brilliant! It may be 3+ years later but I found this piece of code to be exactly what I was looking for. Well done!

At 12/17/2011 2:11 PM, Blogger Qwertie said...

Thanks! After using this "combo" technique in C++ with about 8 classes in the combo, I found another scenario in C# where a combo with 6-7 types would have been the perfect solution.

Unfortunately, it turns out that .NET generics can't support the 'combo' concept, as there is no concept of typedefs. To get the same thing in .NET you'd need each of your types to refer to all the others using 6-7 separate type parameters. I settled for using only the two most important type parameters, but it ended up being fairly clumsy.

At 12/20/2013 9:53 AM, Blogger PhysikPraktikum MAVT said...

This comment has been removed by the author.

At 12/20/2013 9:54 AM, Anonymous Gabriel said...

This is soooo awesome!!!
I have solved some stupid circular dependency without templates by taking this code and using templates and avoiding circulare stupid dependencies of typedefs inside A and B

At 7/28/2016 5:17 PM, Anonymous Anonymous said...

This is what I need.

I just wonder whether there is a cleaner way (not that this solution is bad...just exploring the language :)) in C++11/14.

At 7/28/2016 9:49 PM, Blogger Qwertie said...

While I haven't had the opportunity to use C++ 11/14, none of the new features I've heard about seem to be applicable to the general situation I described here.


Post a Comment

<< Home