Hallo
Ich hab gerade ein design-problem mit templates.
Derzeit arbeite ich an generischen Grafik-Datenstrukturen. Z.B. bin ich gerade dabei einen Octree zu implementieren:
|
C-/C++-Quelltext
|
1
|
template<typename TNumeric, typename TNodeData> class Octree ...;
|
Das Problem ist jetzt, damit ein Objekt vom Typ TNodeData eingefügt werden kann, muss ich seine AABB kennen, ergo muss eine Methode von TNodeData aufgerufen werden, die die AABB zurückliefert.
Also habe ich eine Policy-Klasse erstellt, die genau das machen soll:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
template <typename TNumeric, typename TNodeData>
class OctreeAABBPolicy
{
public:
static AxisAlignedBB<TNumeric> getAABB(TNodeData const& data)
{
return data.getAABB();
}
};
template <typename TNumeric, typename TNodeData>
class OctreeAABBPolicy<TNumeric, TNodeData*>
{
public:
static AxisAlignedBB<TNumeric> getAABB(TNodeData const* data)
{
return data->getAABB();
}
};
|
Stellt TNodeData keine Methode getAABB zur Verfügung spezialisiert man die Policy einfach für seine Datenstruktur und gut ist es.
Nun hat sich aber die Situation ergeben, dass die Policy nicht immer für den Datentyp spezialisiert werden kann:
|
C-/C++-Quelltext
|
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
|
template <
typename TNumeric,
typename THalfEdgeStructure
>
class IntersectionCutter
{
typedef typename THalfEdgeStructure::FaceType* FaceType;
typedef Octree<TNumeric, typename THalfEdgeStructure::FaceType*> SpeedUpStructureType;
typedef typename SpeedUpStructureType::AABBType AABBType;
//Speizialisierung müsste hier sein, da erst hier TNumeric u. FaceType bekannt sind
//template<>
//class OctreeAABBPolicy<TNumeric, FaceType> {.... return aabbFromFace(data); };
//das geht aber nicht, da man in diesem Skope keine Spezialisierung machen darf
protected:
AABBType aabb = aabbFromFace(*iter);
dest.addItemAABB(*iter, aabb);
}
AABBType aabbFromFace(typename THalfEdgeStructure::FaceType const* face)
{
typedef THalfEdgeStructure::FaceType::HalfEdgeContainer EdgeContainer;
EdgeContainer edges = face->getHalfEdges();
EdgeContainer::const_iterator iter;
AABBType resultBox;
for(iter = edges.begin(); iter != edges.end(); ++iter)
{
resultBox.expand((*iter)->end()->getCoordinate());
resultBox.expand((*iter)->start()->getCoordinate());
}
return resultBox;
}
};
|
Meine nächste Idee war, die Policy als Template-Argument im Octree zu spezifizieren
|
C-/C++-Quelltext
|
1
2
3
4
5
|
class Octree
<
typename TNumeric,
typename TNodeData,
template<typename, typename> class TAABBPolicy = OctreeAABBPolicy<TNumeric, TNodeData>
|
Leider geht so etwas ja auch nicht (da nicht C++ konform) und ich will auf keinen Fall, dass der User immer die Policy angeben muss, selbst wenn seine Datenstruktur getAABB zur Verfügung stellt. Irgendwie fällt mir einfach keine saubere Lösung für mein Problem ein.
Meine Frage ist nun: Hat jemand von euch eine Idee, wie man dieses Problem lösen könnte (sofern jemand von euch verstanden hat, was ich will
)?