c++ Klassen Deklaration/Definition

Gast #4801640
Lesenswert?

Hilfe Forum,

Wie mache ich bei folgendem Code die Deklaration/Definition richtig?
1
#include <memory>
2
#include <set>
3

4
struct A;
5
struct B;
6
struct less;
7

8
struct A {
9
  typedef std::shared_ptr<A> ptr_t;
10
  typedef std::set<ptr_t, less> set_t;
11

12
  int value;
13

14
  A(int _value) : value(_value) {
15
  }
16
};
17

18
struct B {
19
  typedef std::shared_ptr<B> ptr_t;
20
  typedef std::set<ptr_t, less> set_t;
21

22
  int num;
23

24
  A::set_t data;
25

26
  B(int _num) : num(_num) {
27
  }
28
};
29

30
struct less {
31
  bool operator()(const A::ptr_t &lh, const A::ptr_t &rh) {
32
    return lh->value < rh->value;
33
  }
34

35
  bool operator()(const B::ptr_t &lh, const B::ptr_t &rh) {
36
    return lh->num < rh->num;
37
  }
38
};
39

40
struct C {
41
  B::set_t data;
42
};
43

44

45
int main() {
46
  A::ptr_t a1(new A(1));
47
  A::ptr_t a2(new A(2));
48

49
  B::ptr_t b(new(1));
50

51
  b->data.insert(a1);
52
  b->data.insert(a2);
53

54
  C c;
55

56
  c.data.insert(b);
57

58
}

Ich krieg' gleich die Kriese und bin dankbar für jede Hilfe! :/
#4801679
Lesenswert?

Vor der Definition deiner Klassen A und B muss die less Klasse bekannt 
sein. Das kannst du z.B. durch folgende Definition der Klasse erreichen:
1
struct less {
2
  bool operator()(const std::shared_ptr<A> &lh, const std::shared_ptr<A> &rh);
3
  bool operator()(const std::shared_ptr<B> &lh, const std::shared_ptr<B> &rh);
4
};

Die Definition der Funktionen kann dann erst folgen wenn die Klassen A 
und B auch definiert wurden. Eine Möglichkeit direkt die typedefs in 
deiner Klasse zu benutzen fällt mir jetzt nicht ein.
#4801840
Lesenswert?

Mit einem template, da der code strukturell identisch ist, bzw. nur vom 
DT abhängig ist. Ausserdem erfolgt die Instanziierung eines Templates 
"lazy", also erst da, wo sie gebraucht wird.
1
#include <memory>
2
#include <set>
3

4
struct A;
5
struct B;
6
//struct less;
7

8
template<typename T>
9
struct less {
10
  bool operator()(const typename T::ptr_t &lh, const typename T::ptr_t &rh) {
11
    return lh->value < rh->value;
12
  }
13
};
14

15
struct A {
16
  typedef std::shared_ptr<A> ptr_t;
17
  typedef std::set<ptr_t, less<A>> set_t;
18

19
  int value;
20

21
  A(int _value) : value(_value) {
22
  }
23
};
24

25
struct B {
26
  typedef std::shared_ptr<B> ptr_t;
27
  typedef std::set<ptr_t, less<B>> set_t;
28

29
  int num;
30
  int value;
31

32
  A::set_t data;
33

34
  B(int _num) : num(_num) {
35
  }
36
};
37

38

39
struct C {
40
  B::set_t data;
41
};
42

43

44
int main() {
45
  A::ptr_t a1(new A(1));
46
  A::ptr_t a2(new A(2));
47

48
  B::ptr_t b(new B(1));
49

50
  b->data.insert(a1);
51
  b->data.insert(a2);
52

53
  C c;
54

55
  c.data.insert(b);
56

57
}

Wobei ich mal eben Dein Datenelement umbenannt habe in B. Falls dass 
nicht gewüncht ist, müsstest Du das template less für B spezialisieren 
...
Gast #4801851
Lesenswert?

Moin,

Ehrlich.nach das so nicht. Schon bei den kleinen Schnipsel Code ist es 
schon nicht mehr intuitiv durchzusehen was da passieren soll. Lass den 
mal ein wenig größer werden und ein halbes Jahr vergehen. Dann sieht 
keiner mehr durch. Sich du nicht.
Gast #4802737
Lesenswert?

Danke sehr für die zahlreiche Beteiligung!

Wilhelm M. schrieb:
> Warum ist der "normale" Weg für Dich nicht anwendbar?

Funktioniert leider so nicht (auch dein 2ter Vorschlag). Ich schätze, 
weil für std::shared_ptr<T> bereits alle Vergleichsoperatoren definiert 
sind:
http://de.cppreference.com/w/cpp/memory/shared_ptr/operator_cmp

Wilhelm M. schrieb:
> Mit einem template, da der code strukturell identisch ist, bzw. nur vom
> DT abhängig ist.

Ist er leider nicht. Ich habe absichtlich A::value und B::num genannt, 
denn im eigentlichen Code heissen die auch nicht gleich. Ich kann diese 
Variable nicht umbenennen (bzw. ich will nicht, weil dadurch der Sinn 
nicht mehr ersichtlich wäre).

Sebastian V. schrieb:
> Die Definition der Funktionen kann dann erst folgen wenn die Klassen A
> und B auch definiert wurden. Eine Möglichkeit direkt die typedefs in
> deiner Klasse zu benutzen fällt mir jetzt nicht ein.

Ok, trotzdem Danke.

nicht“Gast“ schrieb:
> Moin,
>
> Ehrlich.nach das so nicht. Schon bei den kleinen Schnipsel Code ist es
> schon nicht mehr intuitiv durchzusehen was da passieren soll. Lass den
> mal ein wenig größer werden und ein halbes Jahr vergehen. Dann sieht
> keiner mehr durch. Sich du nicht.

Auf was beziehst du dich?
#4802777
Lesenswert?

Wie wärs damit?
1
#include <memory>
2
#include <set>
3
#include <functional>
4

5
struct A {
6
    int value;
7
    A(int _value) : value(_value) {}
8
};
9

10
namespace std {
11
template<>
12
struct less<std::shared_ptr<A>> {
13
      bool operator()(const std::shared_ptr<A> &lh, const std::shared_ptr<A> &rh) {
14
          std::cout << __PRETTY_FUNCTION__ << std::endl;
15
          return lh->value < rh->value;
16
      }
17
}; 
18
}
19

20
struct B {
21
    typedef std::shared_ptr<A> ptr_t;
22
    typedef std::set<ptr_t, std::less<std::shared_ptr<A>>> set_t;
23
    
24
    int num;
25

26
    set_t data;
27
    
28
    B(int _num) : num(_num) {}
29
};
30

31
namespace std {
32
template<>
33
struct less<std::shared_ptr<B>> {
34
      bool operator()(const std::shared_ptr<B> &lh, const std::shared_ptr<B> &rh) {
35
          std::cout << __PRETTY_FUNCTION__ << std::endl;
36
          return lh->num < rh->num;
37
      }
38
}; 
39
}
40

41
struct C {
42
    typedef std::shared_ptr<B> ptr_t;
43
    typedef std::set<ptr_t, std::less<std::shared_ptr<B>>> set_t;
44
    set_t data;
45
};
46

47

48
int main() {
49
  B::ptr_t a1(new A(1));
50
  B::ptr_t a2(new A(2));
51

52
  C::ptr_t b(new B(1));
53

54
  b->data.insert(a1);
55
  b->data.insert(a2);
56

57
  C c;
58

59
  c.data.insert(b);
60

61
}
#4802790
Lesenswert?

Du kannst auch für std::set den Comparator-Typ-Parameter weglassen fällt 
mir grad auf. Denn die vollständige Spezialisierung hat ja gegenüber dem 
allgemeiner Template Vorrang:
1
struct B {
2
    typedef std::shared_ptr<A> ptr_t;
3
    typedef std::set<ptr_t> set_t;
4
    
5
    int num;
6

7
    set_t data;
8
    
9
    B(int _num) : num(_num) {}
10
};
Gast #4802796
Lesenswert?

Ich hatte noch eine Idee. Und funktioniert sogar ;) Wirkt auf mich 
relativ sauber.
1
#include <memory>
2
#include <set>
3

4
struct A;
5
struct B;
6

7
struct shared_ptr_less {
8
  template <typename T>
9
  bool operator()(const std::shared_ptr<T> &lh, const std::shared_ptr<T> &rh) {
10
    return (*lh) < (*rh);
11
  }
12
};
13

14
struct A {
15
  typedef std::shared_ptr<A> ptr_t;
16
  typedef std::set<ptr_t, shared_ptr_less> set_t;
17

18
  const int value;
19

20
  A(int _value) : value(_value) {
21
  }
22
};
23

24
struct B {
25
  typedef std::shared_ptr<B> ptr_t;
26
  typedef std::set<ptr_t, shared_ptr_less> set_t;
27

28
  const int num;
29

30
  A::set_t data;
31

32
  B(int _num) : num(_num) {
33
  }
34
};
35

36
inline bool operator<(const A &lh, const A &rh) {
37
  return lh.value < rh.value;
38
}
39

40
inline bool operator<(const B &lh, const B &rh) {
41
  return lh.num < rh.num;
42
}
43

44
struct C {
45
  B::set_t data;
46
};
47

48
int main() {
49
  A::ptr_t a1(new A(10));
50
  A::ptr_t a2(new A(2));
51
  A::ptr_t a3(new A(1024));
52
  A::ptr_t a4(new A(128));
53

54
  B::ptr_t b(new B(1));
55

56
  b->data.insert(a1);
57
  b->data.insert(a2);
58
  b->data.insert(a3);
59
  b->data.insert(a4);
60

61
  for (auto it = b->data.begin(); it != b->data.end(); it++) {
62
    printf("%i\n", (*it)->value);
63
  }
64

65
  C c;
66

67
  c.data.insert(b);
68
}

P.S.: oben habe ich noch const vor int vergessen! Das ist natürlich sehr 
wichtig!
#4802804
Lesenswert?

Ja, geht auch, wenn Du auch möchtest, dass die DT A bzw. B generell 
anordnenbar sein sollen. Aber das wird wohl so sein.

Das "normale" Vorgehen, ist allerdings std::less zu spezialisieren - in 
dem Sinne, dass man das gewissermaßen erwartet ... Das kannst Du ja aber 
auch mit Deinem Ansatz kombinieren.
Gast #4802818
Lesenswert?

Wilhelm M. schrieb:
> namespace std {
> template<>
> struct less<std::shared_ptr<A>> {
>       bool operator()(const std::shared_ptr<A> &lh, const
> std::shared_ptr<A> &rh) {
>           std::cout << _PRETTY_FUNCTION_ << std::endl;
>           return lh->value < rh->value;
>       }
> };
> }

Bist du sicher? Ich bekomme:
error: redefinition of 'struct std::less<std::shared_ptr<A> >'

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren