Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

09.08.2014, 02:05

SimpleLib

Ich möchte hier meine kleine private Library vorstellen.

Eine Dokumentation kann man hier finden.
Den Source Code findet man hier.

Diese Library ist entstanden, weil ich für mich privat nicht immer benötigte Klassen zwischen verschiedenen Projekten herum kopieren wollte.
Letztendlich ist sie eine kleine Ansammlung von Klassen, die teilweise aufeinander aufbauen.

Warum stell ich sie hier vor?
Letztendlich kann sie jeder verwenden. Ich halte den Master Branche ab jetzt auch auf einem konsistenten Zustand, Neuerungen kommen erst in Dev und wenn dort auch ein konsistenter Zustand erreicht wurde wird gemerged.
Allerdings würde mich interessieren, was ihr davon haltet? Ich fände es toll, wenn jemand mal über den Code und die Doku schauen würde, und eventuell Verbesserrungsvorschläge für mich übrig hätte.

Bisher ist der Großteil der Lib dokumentiert, der Rest wird morgen/die nächsten Tage folgen.

mfg

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »anti-freak« (11.08.2015, 19:45)


2

09.08.2014, 02:25

Habe jetzt nur kurz mal rein geschaut, aber mir sind ein paar Dinge sofort aufgefallen. Wo ist der Sinn von maximum<T>(), wenn du sowieso nur std::numeric_limits benutzt? Gleiches bei reverse(std::string). Dann sind da noch so sinnfreie Typedefs für die Integer-Typen, die es auch schon in der Standard-Lib gibt. Und wieso sind so Dinge, wie TILE_SIZE definiert?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Batzer« (09.08.2014, 02:49)


3

09.08.2014, 02:32

Du hast anscheinend nur in den Teil rein geschaut, der überarbeitungsbedürftig ist ;)

Ich finde maximum<T>() ansprechender zu schreiben wie std::numeric_limits<T>::max().
Gleiches bei reverse.


Welche Typedefs findest du denn unsinnig?
TILE_SIZE ist tatsächlich noch ein Überbleibsel aus vergangenen Tagen, werde ich noch entfernen ;)

4

09.08.2014, 02:44

Welche Typedefs findest du denn unsinnig?

Alle, außer evtl. EPSILON.

Kleiner Spaß: round<T>(T) könnte man auch ohne Branch schreiben

C-/C++-Quelltext

1
2
3
4
5
6
7
template <typename T> int sgn(T val) {
    return (T(0) < val) - (val < T(0));
}

template <typename T> inline T round(T num) {
    return sgn(num) * std::floor(std::abs(static_cast<double>(num)) + 0.5);
}

5

09.08.2014, 08:18

Hallo anti-freak,

Ich habe nur mal kurz drüber geschaut.
Was mir aufgefallen ist bei deinen point3d Sachen, bei der Point3Dbase Klasse fängst du gut an das Ganze auf Basis von templates zu machen aber dann hörst du auf und splittest die Klasse in eine extra double Klasse für Point3D und eine für int. Der ganze Code ist redundant in beiden Klassen. Ich würde alles in eine Template klasse packen.

Gruß Koschi
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

6

09.08.2014, 08:42

Hallo Koschi,

ich hatte das damals alles als Template, hat sich aber in gewissen Dingen als eher unpraktisch herausgestellt, deswegen gehe ich jetzt diesen Weg.
Damit ich diesen ganzen redundanten Code aus den Point(3D) Klassen heraus bekomme, wäre vom Prinzip her, die +=, -=,... Operatoren als freie Funktion zu deklarieren. Hätte das denn irgendwelche Nachteile (außer das ich nicht direkt auf die Member zugreifen könnte)? Oder gäbe es einen anderen Weg?

Dann 2 Fragen die mir gerade auf der Seele brennen:
- inline: Ich habe gehört, dass der Compiler sowieso selbst entscheidet, ob er etwas inlined oder nicht. Wofür brauche ich denn nun dieses Keyword?
- static außerhalb von Klassen: Welchen Nutzen bietet mir dieses Keyword?

mfg

7

09.08.2014, 13:25


ich hatte das damals alles als Template, hat sich aber in gewissen Dingen als eher unpraktisch herausgestellt, deswegen gehe ich jetzt diesen Weg.

Mich würde interessieren an welcher stelle sich das als unpraktisch herausgestellt hat.


Damit ich diesen ganzen redundanten Code aus den Point(3D) Klassen heraus bekomme, wäre vom Prinzip her, die +=, -=,... Operatoren als freie Funktion zu deklarieren. Hätte das denn irgendwelche Nachteile (außer das ich nicht direkt auf die Member zugreifen könnte)? Oder gäbe es einen anderen Weg?

Also die Diskussion die Operatoren als freie Funktion oder an die Klasse gebunden hatte wir hier schon mal, mit Keinem Klaren Ergebnis (meiner Meinung nach).

Wie gesagt mein Weg wäre alles in eine Template Klasse packen. Vielleicht mal hier spicken bei der SFML.

Gruß Koschi
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

8

09.08.2014, 14:19


ich hatte das damals alles als Template, hat sich aber in gewissen Dingen als eher unpraktisch herausgestellt, deswegen gehe ich jetzt diesen Weg.

Mich würde interessieren an welcher stelle sich das als unpraktisch herausgestellt hat.

Den genauen Grund kann ich dir leider auch nicht mehr nennen. Ich hatte Point eine sehr sehr lange Zeit als Template, habe mich dann aber schlussendlich dazu entschieden, kein Template zu nutzen.
Es lag dabei aber auch eher daran, das ich mich mittlerweile sehr an QT orientiere und mit Point(F) ein Äquivalent zu QPoint(F) geschaffen habe. Und da ich den Geometrie Namespace so gut es geht einheitlich halten wollte, habe ich mich für dieses Vorgehen entschieden. Ist aber auch kein Beinbruch, wenn jemand einen anderen Datentyp verwenden will, oder gar eine eigene Point Klasse für sein Rectangle nutzen möchte, muss er eben entweder einen typedef für RectangleBase setzen, oder richtig erben lassen. Beides ist kein großartiger Aufwand, da die Mainfunktionalität innerhalb von RectangelBase geschieht (natürlich müssen dann entsprechende Point Funktionen wie "getX" in diesem Point vorhanden sein, aber auch das ließe sich ja bei Bedarf lösen).



Damit ich diesen ganzen redundanten Code aus den Point(3D) Klassen heraus bekomme, wäre vom Prinzip her, die +=, -=,... Operatoren als freie Funktion zu deklarieren. Hätte das denn irgendwelche Nachteile (außer das ich nicht direkt auf die Member zugreifen könnte)? Oder gäbe es einen anderen Weg?

Also die Diskussion die Operatoren als freie Funktion oder an die Klasse gebunden hatte wir hier schon mal, mit Keinem Klaren Ergebnis (meiner Meinung nach).

Wie gesagt mein Weg wäre alles in eine Template Klasse packen. Vielleicht mal hier spicken bei der SFML.

Gruß Koschi

Ich habe mal einen neuen Thread erstellt, da ich den Thread ungern mit Fragen zu generellen C++ Funktionalitäten vollmüllen möchte ;)
Allerdings danke für den Link, habe mir das mal durchgelesen aber so wirklich weiter geholfen hat mir das nicht. Aber immerhin weiß ich jetzt, dass ich mit meiner Verwunderung über freie Operatoren nicht alleine stehe ;)

mfg

9

10.08.2014, 16:52

So, nachdem ich mir gestern nochmal Gedanken gemacht habe, warum ich eigentlich von den Templates abgerückt bin, habe ich mich daran erinnert, das ich entsprechende Operatoren und Funktionen für Point und PointF anders implementieren wollte. Ich kannte Template Spezialisierung bedingt, wusste aber nicht genau, wie mir das in diesem Fall von Nutzen sein konnte.
Jetzt habe ich mich gestern noch ein wenig mehr damit beschäftigt und bin zu einem, wie ich finde, gutem Design gekommen.

Ich nutze jetzt also wieder Templates, allerdings mit Spezialisierung für float und double (nur bei der Point Klasse).
Vll mag jemand nochmal drüber schauen und eine neue Bewertung für den Geometrie Namespace abgeben? Ich wäre euch sehr dankbar ;)

mfg

EDIT: Die Doku wurde natürlich noch nicht angepasst. Wird im Laufe der nächsten Woche aber auf jeden Fall passieren ;)

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »anti-freak« (10.08.2014, 18:00)


10

27.03.2015, 18:53

Listener Pattern

Guten Tag,

Signal.h
Receiver.h
Receiver.cpp
Connection

ich habe diese Woche versucht ein Listener Pattern auf die Beine zu stellen.
An sich ist das ja nicht sonderlich kompliziert zu erstellen, allerdings gibt es ein paar Dinge, die andere Implementierungen ignorieren.

Das größte Problem ist eigentlich die Tatsache, dass sich Connections auch während das Signal in der "emit" Phase ist, lösen können.
Das ist mir vor allem bei der "SigSlot" Implementierung aufgefallen.

Deswegen habe ich jetzt meine eigene Implementierung geschrieben. Die Kernkriterien sind folgende:

- sicheres connecten und disconnecten während des emits
- signal und receiver sollen move und copy able sein
- keine aufräumarbeiten von außen

Allerdings haben die obigen Punkte auch ihren Preis, weswegen ein bisschen Overhead verursacht wird.
Beim disconnecten einer Connection wird diese nicht direkt gelöscht, sondern nur in einen invaliden Status gebracht, den ich beim emiten abfrage.
D.h. es wird teilweise über nicht mehr benötigte Connection iteriert.
Gelöscht werden diese Connections beim Aufruf von signal::emit, jedoch bevor in die eigentliche emit Schleife eingetreten wird.
D.h. im schlechtesten Fall (wenn alle Connections valid sind) muss über jede Connection 2 mal pro signal::emit iteriert werden.

Wie funktioniert das Ganze jetzt eigentlich genau?
An für sich nicht sonderlich kompliziert.
Um eine Connection zu erstellen, benötigt man 2 Dinge:
- ein signal
- einen Receiver

Zuerst einmal zum Receiver:
Ein Receiver bietet entsprechende Funktionen an, die von außen aufgerufen werden können (die so genannten Slots). Um das zu erreichen müssen diese Funktionen entweder public sein, oder die Klasse "signal" als friend deklariert werden.
Ein Receiver meldet sich selbst bei den Signalen, wenn der Destructor aufgerufen wird. D.h. hier sind keine manuellen Aufräumarbeiten von Nöten. Move und copy ist ebenfalls automatisiert.
Damit eine Klasse signale Empfangen kann, muss sie von "Receiver" erben.

Signal:
Signal ist eine variadic template Klasse. Dadurch können beliebig viele Parameter an sie gebunden werden, die später von den Slots erwartet werden. Es ist im Prinzip das Kernstück des ganzen. Ein Signal informiert alle Receiver mit denen es verbunden ist, wenn es sich verändert (move, copy, delete).

Wie nutzen wir das Ganze nun?

Folgendes Beispiel:

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
#include <include/sigslot/signal.h>
#include <include/sigslot/receiver.h>

class Foo : public sl::sigslot::Receiver
{
public:
    Foo() : Receiver()
    {}
    
    void onEmit(int x, float y)
    {
        m_X = x;
        m_Y = y;
    }
    
    int m_X = 0;
    int m_Y = 0.0f;
};

int main()
{
    Foo foo;
    sl::sigslot::signal<int, float> sig;
    sig.connect(&foo, &Foo::onEmit);
    sig(3, 4.5f); // alternativ sig.emit
}


Eigentlich komplett simpel und wie man es erwarten könnte.

Allerdings ist das Ganze bisher nicht thread safe, daran arbeite ich gerade. Vll hat dazu ja jemand Vorschläge?

mfg

PS: Eine Dokumentation findet ihr hier: http://doc.simple-world.org/group__sigslot.html

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »anti-freak« (11.08.2015, 19:50)


Werbeanzeige