Forum: PC-Programmierung C++ Verständnis (Boost-Library)


von Stefan (Gast)


Lesenswert?

Hallo,

ich beschäftige mich gerade etwas mit C++, da ich einige Funktionen der 
CGAL bzw. Boost Bibliothek verwenden möchte...

Eine der Sachen, die ich nicht durchschaue, und zu der mir jetzt auch 
kein Stichwort für Google einfällt:

http://www.boost.org/doc/libs/1_52_0/doc/html/heap/concepts.html#heap.concepts.basic

Fast ganz unten auf der Seite

>Note that handles can be stored inside the value_type:

>    (*handle).handle = handle; // store handle in node

handle ist doch kein Zeiger, sondern eher ein opaker Datentyp. Was ist 
dann (*handle).handle bzw. etwas weiter unten dieses

>*t3 = 4;

Ist das ein Zugriff auf spezielle öffentliche Bereiche der Handle 
Datenstruktur? Und die noch wichtigere Frage: Was hat man davon, dass 
man wie hier handle in handle speichert? Sinn würde es machen, wenn man 
von struct heap_data irgendwie wieder an handle herankäme, aber das sehe 
ich nicht.

Viel findet man mit Suchmaschienen leider nicht zu den Boost 
Heap-Datenstrukturen, und die dortigen Beispiele speichern leider nur 
einfache int-Werte statt strukturierter Typen ein. Und ein ganzes C++ 
Buch möchte ich jetzt nicht durcharbeiten -- ich will lediglich ein paar 
kleine Routinen von Ruby aus nutzbar machen, was auch schon teilweise 
funktioniert.

von Stefan (Gast)


Lesenswert?

Stefan schrieb:
> Sinn würde es machen, wenn man
> von struct heap_data irgendwie wieder an handle herankäme

Ah!

>struct heap_data
>{
>    fibonacci_heap<heap_data>::handle_type handle;

Den Eintrag habe ich doch glatt die ganze Zeit übersehen. Dann komme ich 
von heap_data tatsächlich an handle heran, so macht das Sinn.

Bleibt nur noch die Frage was eigentlich

>*t3 = 4;
>(*handle).handle =

bedeutet. Wenn t3 ein Pointer wäre, würde man den Ort, wo er hin zeigt, 
mit dem Wert 4 überschreiben. Sollte es so sein, dass hier der erste 
Speicherplatz von handle mit eben diesem Wert beschrieben wird?
Glaube ich fast. Aber was ist

>(*handle).handle =

von Arc N. (arc)


Lesenswert?

Auf der Seite ist irgendwo noch folgendes zu finden:
1
class mutable_heap_interface
2
{
3
public:
4
    typedef unspecified iterator;
5
    struct handle_type
6
    {
7
        value_type & operator*() const;
8
    };
9
...

von Stefan (Gast)


Lesenswert?

Ja -- nicht, dass ich das schon wirklich verstehe, aber immerhin 
funktioniert das bei mir soweit.

Ein (hoffentlich)  letztes Problem hätte ich noch: Wie kann ich die 
Struktur PriorityQueue um eine int Variable erweitern, auf die ich 
zugreifen kann?

Ich habe mich ja weitgehend an dem Beispiel interface.cpp

http://www.ssalewski.de/tmp/interface.cpp

orientiert, da steht dann etwa
>template <typename PriorityQueue>
>void iterator_interface(void)
>{
>PriorityQueue pq;
>pq.push(2);

Was ich nun haben möchte:
pq.my_int_stefan = -1

cout << pq.my_int_stefan

Ich hoffe mal, es ist klar was ich meine -- wenn nicht werde ich meinen 
eigenen Qulelltext online stellen, wenn ich ihn etwas aufgeräumt habe. 
Wie man eine Klasse erweitert weiß ich schon in etwa, nur mit diesen 
Funktions-Templates verheddere ich mich irgendwie. (Und wenn sich wer 
fragt, warum: Ich möchte die PriorityQueue von Ruby aus ohne 
Neukompilierung als Min- oder Max-Queue benutzen können, daher muss eine 
Variable mit ihr verknüpft sein, so dass ich dann beim Einspeichern und 
Ausgeben bei Bedarf das Vorzeichen der Schlüssel invertieren kann.

von Stefan (Gast)


Lesenswert?

1
#include <iostream>
2
#include <iomanip>
3
#include <boost/heap/fibonacci_heap.hpp>
4
using std::cout;
5
using std::endl;
6
using namespace boost::heap;
7
8
class XQ : public boost::heap::fibonacci_heap<int>
9
//class XQ : public PriorityQueue<int>
10
11
{
12
public:
13
int x;
14
};
15
16
class A
17
{
18
public:
19
int a;
20
};
21
22
class B : public A
23
{
24
public:
25
int b;
26
};
27
28
template <typename PriorityQueue>
29
//template <typename XQ>
30
void basic_interface(void)
31
{
32
  PriorityQueue pq;
33
  pq.x = -1;
34
35
  pq.push(2);
36
}
37
38
int main(void)
39
{
40
XQ q;
41
B b;
42
b.a = 7;
43
b.b = 3;
44
q.x = 1;
45
cout << b.a << endl;
46
cout << b.b << endl;
47
cout << q.x << endl;
48
using boost::heap::fibonacci_heap;
49
50
basic_interface<fibonacci_heap<int> >();
51
52
return 0;
53
}
stefan@AMD64X2 ~/newboosttest $ make ttt
g++     ttt.cpp   -o ttt
ttt.cpp: In function 'void basic_interface() [with PriorityQueue = 
boost::heap::fibonacci_heap<int>]':
ttt.cpp:50:39:   instantiated from here
ttt.cpp:33:2: error: 'class boost::heap::fibonacci_heap<int>' has no 
member named 'x'
make: *** [ttt] Error 1

Was soll mir das sagen?

von Stefan Salewski (Gast)


Lesenswert?

Nun gut, da Herr Buchegger wohl schon im Weihnachtsurlaub ist, habe ich 
versucht selbst etwas hinzufrikeln:

[c]
#include <iostream>
#include <iomanip>
#include <boost/heap/fibonacci_heap.hpp>
using std::cout;
using std::endl;
using namespace boost::heap;

class XQ : public boost::heap::fibonacci_heap<int>
{
public:
int x;
};

typedef XQ XXX;

template <typename XXX>
void basic_interface(void)
{
  XQ pq;
  pq.x = -1;
  pq.push(2);
  cout << pq.top()*pq.x << endl;
}

int main(void)
{
  //XQ q;
  using boost::heap::fibonacci_heap;
  basic_interface<fibonacci_heap<int> >();
  return 0;
}
[\c]

stefan@AMD64X2 ~/newboosttest $ ./ttt
-2

Das ist in etwa das, was ich wollte -- hoffe ich jedenfalls.

von Rolf Magnus (Gast)


Lesenswert?

Stefan Salewski schrieb:
> Das ist in etwa das, was ich wollte -- hoffe ich jedenfalls.

Es ergibt leider nicht sehr viel Sinn...

> typedef XQ XXX;

Dieses typedef wird nirgendwo benutzt.

> template <typename XXX>

Das Template-Argument wird ebenfalls nirgendwo benutzt, und somit hat es 
keinerlei Effekt, daß du hier überhaupt ein Template verwendest. Das XXX 
hier hat übrigens keinen Zusammenhang zum XXX oben.
Den selben Effekt hätte es, wenn du stattdessen schreibst:
1
void basic_interface(void)
2
{
3
  XQ pq;
4
  pq.x = -1;
5
  pq.push(2);
6
  cout << pq.top()*pq.x << endl;
7
}
8
9
int main(void)
10
{
11
  basic_interface();
12
  return 0;
13
}

von Stefan Salewski (Gast)


Lesenswert?

@Rolf Magnus

Ah, Dich gibt es hier also auch noch, neben Karl Heinz B. als C++ 
Experten...

Was Du schreibst habe ich dann gestern Abend auch noch bemerkt -- 
wichtig war mir zunächst, irgendwie dieses Template-Gewirr zu bändigen.

Für mich war der wesentliche Trick
1
class XPQ : public boost::heap::fibonacci_heap<heap_data>
2
{
3
public:
4
  int x;
5
};
Dann habe ich eine ganz harmlose C++ Klasse mit meinem Struct heap_data 
als Knoten der Vorrang-Schlange und kann etwa schreiben
1
XPQ* new_fqueue(void)
2
{
3
  XPQ *pq = new XPQ;
4
  pq->x = 77; // Test
5
  cout << pq->x << endl; // Test
6
  return pq;
7
}
Dass man so einfach aus einer Klasse mit Template eine erweiterte Klasse 
ohne Template machen kann hatte ich nicht gewusst und auch nirgendwo 
gefunden, letztlich dann erraten.

Gruß

Stefan

von Stefan Salewski (Gast)


Lesenswert?

@Rolf Magnus

Falls Du noch da bist...

Im Beispiel für Iteratoren schreiben sie
http://www.boost.org/doc/libs/1_52_0/doc/html/heap/concepts.html#heap.concepts.mutability
1
template <typename PriorityQueue>
2
void iterator_interface(void)
3
{
4
    PriorityQueue pq;
5
    pq.push(2); pq.push(3); pq.push(1);
6
7
    typename PriorityQueue::iterator begin = pq.begin();
8
    typename PriorityQueue::iterator end = pq.end();
9
10
    cout << "Priority Queue: iteration" << endl;
11
    for (typename PriorityQueue::iterator it = begin; it != end; ++it)
12
        cout << *it << " "; // 1, 2, 3 in unspecified order
13
    cout << endl;
14
}
Welchen Sinn machen da die Hilfsvariablen begin und end -- eigentlich 
doch keinen, wenn man die Queue wahrend der Iteration nicht ändert, und 
das darf man doch wohl eh nicht?

Also warum nicht einfach
1
for (typename PriorityQueue::iterator it = pq.begin(); it != pq.end(); ++it)

von Rolf Magnus (Gast)


Lesenswert?

Stefan Salewski schrieb:
> Welchen Sinn machen da die Hilfsvariablen begin und end -- eigentlich
> doch keinen, wenn man die Queue wahrend der Iteration nicht ändert, und
> das darf man doch wohl eh nicht?

Eigentlich braucht man sie nicht. Bei end könnte man sich noch 
vorstellen, daß der Schreiber des Programms vielleicht vermeiden wollte, 
daß die Funktion end() und die Erzeugung des entsprechenden Iterators 
bei jedem Schleifendurchlauf aufs Neue gemacht wird.

> Also warum nicht einfach
> for (typename PriorityQueue::iterator it = pq.begin(); it != pq.end();
> ++it)

Geht genauso. Ich hätte das auch so geschrieben.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.