rtti problem

1
2
3
4
class GeometricPlace {...};
class CircleArc : public GeometricPlace { vec2 center; double radius; double from; double length; }
class LineSegment : public GeometricPlace { vec2 point, direction; double from; double to; }
class SemiPlane : public GeometricPlace { vec2 point, direction; bool right; }


I want to do intersections between above geometric places.
But I handle all of these with GeometricPlace* pointers.

Can I do this without rtti? I believe not. I ask for sure.

details:
1
2
3
4
5
class Point
{
   GeometricPlace *gp;
   void intersection(GeometricPlace *g) { ... gp = *gp & *g; ... }
}
Last edited on
This is actually a good question. I'm not sure the best way to approach it. All the ways I can think of are maintenance nightmares.

RTTI is one option. Another would be to have nested virtual calls:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class GeometricPlace
{
//...
   // generic collision routine
   virtual foo intersect(const GeometricPlace& v) const = 0;

   // specific collision routines
   virtual foo intersectfine(const CircleArc& v) const = 0;
   virtual foo intersectfine(const LineSegment& v) const = 0;
   virtual foo intersectfine(const SemiPlane& v) const = 0;
};

class CircleArc
{
//..
   // generic collision routine
   virtual foo intersect(const GeometricPlace& v) const { return v.intersectfine(*this); } // hand off to specific collision routine

   // specific collision routines
   virtual foo intersectfine(const CircleArc& v) const { /* do CircleArc/CircleArc collision */ }
   virtual foo intersectfine(const LineSegment& v) const { /* do LineSegment/CircleArc collision */ }
   virtual foo intersectfine(const SemiPlane& v) const { /* do SemiPlane/CircleArc collision */ }
};

// repeat for classes LineSegment, SemiPlane 



EDIT:

I wonder if there's a way to template that and make it easier. If I get some more time today I'll look at it more.


EDIT 2:

OK here's my new idea:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//  global collision functions, using specific types
foo intersect(const CircleArc& a,const CircleArc& b);
foo intersect(const CircleArc& a,const LineSegment& b);
foo intersect(const CircleArc& a,const SemiPlane& b);
foo intersect(const LineSegment& a,const LineSegment& b);
foo intersect(const LineSegment& a,const SemiPlane& b);
foo intersect(const SemiPlane& a,const SemiPlane& b);
// ... add more as needed
//  ..  add transitive ones (LineSegment,CircleArc) and just call the matching one of the above
//  fill out their bodies as you'd expect


class GeometricPlace
{
public:
  virtual foo intersect(const GeometricPlace& b) const = 0;

  virtual foo intersectfine(const CircleArc& b) const = 0;
  virtual foo intersectfine(const LineSegment& b) const = 0;
  virtual foo intersectfine(const SemiPlane& b) const = 0;
};

template <typename T>
class IntersectDispatch
{
public:
  foo intersect(const GeometricPlace& b) const
  {
    return b.intersectfine(static_cast<const T&>(*this));
  }

  foo intersectfine(const CircleArc& b) const { return intersect( static_cast<const T&>(*this),b ); }
  foo intersectfine(const LineSegment& b) const { return intersect( static_cast<const T&>(*this),b ); }
  foo intersectfine(const SemiPlane& b) const { return intersect( static_cast<const T&>(*this),b ); }
};


class CircleArc : public GeometricPlace, public IntersectDispatch<CircleArc>
   // derive from IntersectDispatch< _thisclass_ >
   //  so LineSegment would derive from IntersectDispatch<LineSegment>
{
 // no need to write any intersect functions here
};



The gimmick here is that GeometricPlace's virtual functions will get delegated to the sister class IntersectDispatch.

This still requires you to change multiple things (3) when you add a new Geometric type, but that's the best I can imagine. As a bonus, failure to add any one of the 3 will yield a compiler error instead of compiling and resulting in broken code.

The 3 things you'd have to change for adding new types:

- Add all appropriate global intersect() functions
- Add 1 pure virtual intersectfine() function to GeometricPlace
- Add 1 intersectfine() function to IntersectDispatch. Make it identical to the others, but using the appropriate type as the parameter
Last edited on
whow dude.
Respect.
Be sure to see my update. That new idea is way better and tons more managable.
You might be interested in reading Modern C++ Design by Andrei Alexandrescu. It covers a lot of template dispatching techniques.
Me or chameleon?

I actually have read very little in the ways of design books.
Both but it's not for beginners. Disch, you'd probably like it.
1
2
3
4
template <typename T>
class IntersectDispatch : public GeometricPlace

class CircleArc : public IntersectDispatch<CircleArc>

is a little bit better, I guess!

Thanks again!
Yeah that makes more sense actually XD
Topic archived. No new replies allowed.