Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » factory

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
30.03.2011, 14:54 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


Hallo,

hab gerade irgendwie einen kleinen Hänger:

Ich habe folgendes:

Basisklasse - nennen wir sie "data" - diese enthält im groben 3 Felder: data-id, length und content und eine methode "receive" in dieser methode werden die 3 felder von einem socket gelesen und dann in den korrekten typen je nach data-id umgewandelt.
Das ganze steckt in einer bibliothek "protocoll".

nun habe ich spezielle klassen, nennen wir sie "data_foo" und "data_bar" - diese sind jeweils in den bibliotheken "protocoll_foo" und "protocoll_bar".

wie kriege ich das nun hin, das ich aus "data_foo" und "data_bar" diese typen für die "receive"-funktion statisch (also beim kompilieren von protocoll_foo/bar) zu registrieren, damit "procotoll" keine abhängigkeit zu protocoll_foo und protocoll_bar hat?

irgendwie steh ich da gerade auf dem schlauch ...
--
class God : public ChuckNorris { };

Dieser Post wurde am 30.03.2011 um 14:56 Uhr von FloSoft editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
31.03.2011, 11:33 Uhr
TOSHMAX



Also wenn ich dein Problem richtig verstanden habe, und du "protocoll" verändern kannst, könntest du etwas in der Art machen, wir 0xdeadbeef hier gepostet hat.

Anstatt std::string könntest du dann eine data-id als Key benutzen.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
31.03.2011, 19:00 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


ja die factory an sich ist ja nicht verkehrt - nur möchte ich das


C++:
  fct.register_type<B>("Typ B");
  fct.register_type<C>("Typ C");



in der jeweiligen sub-bibliothek haben, und nicht in der basisbibliothek - die darf ja schließlich nicht weiter verändert werden - nur gefüllt.
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
01.04.2011, 09:08 Uhr
TOSHMAX



Ich kenne den Code deiner Bibliotheken nicht, aber eine Möglichkeit eine einmalige Inititalisierung durchzuführen wäre folgende:

C++:
// B.cpp
const int reg = (fct.register_type<B>("Typ B"), 0);
// C.cpp
const int reg = (fct.register_type<C>("Typ C"), 0);

Ich finde es selbst nicht sehr schön und kenne auch einige Probleme, vor allem mit dynamisch gelinkten Bibliotheken, aber so im Ansatz sollte es funktionieren.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
01.04.2011, 14:00 Uhr
0xdeadbeef
Gott
(Operator)


Vorsicht, Initialisierungsreihenfolge!

Du wirst die Factory in einer Funktion zur Verfügung stellen müssen, damit sie auf jeden Fall vor den register_type-Aufrufen existiert:

C++:
factory<std::string, A> &get_factory() {
  static factory<std::string, A> self;
  return self;
}

...

int const reg_B = (get_factory().register_type<B>("Typ B"), 0);


wäre denkbar.

Ansonsten - wenn es um eine Plugin-Architektur geht und das ganze zur Laufzeit per dlopen/dlsym o.ä. rangelinkt wird, könntest du natürlich auch beim Laden des betreffenden Plugins einen Funktionszeiger in eine Map speichern, der dir Objekte des gewollten Typs erstellt. Damit könnte man sich einiges Linkergefummel wahrscheinlich sparen.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 01.04.2011 um 14:02 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
04.04.2011, 11:42 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


also ich habs nun so gemacht,

das ich in den cpp-dateien derjeweiligen bibliotheken die initialisiert habe:


C++:
#include "bar.h"

namespace // anonymous
{
    struct initializer
    {
        initializer()
        {
            std::cerr << "init bar" << std::endl;
            base::register_type<bar>(TYPE_BAR);
        }
        ~initializer()
        {
            //base::unregister_type(TYPE_BAR);
        }
    };
    static initializer i;
};



obwohl ich da wahrscheinlich auch wieder u.u ein problem mit der initialisierungsreihenfolge habe oder?

das beispiel das ich produziert habe funktioniert einwandfrei unter linux:

https://svn.ra-doersch.de/svn/cppfactory/

aber kann natürlich sein das das zufall ist.
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
04.04.2011, 15:53 Uhr
0xdeadbeef
Gott
(Operator)


Ja, du hast ein potenzielles Problem mit der Initialisierungsreihenfolge. Das lässt sich aber leicht beheben - in Base statt

C++:
        template<typename T>
        static void register_type(types type)
        {
            types_.register_type<T>(type);
        }

        static util::factory<types, base, util::smart_ptr_instantiator<base> > types_;


halt

C++:
  template<typename T>
  static void register_type(types type)
  {
    types().register_type<T>(type);
  }

  typedef util::factory<types, base, util::smart_ptr_instantiator<base> > factory_t;
  static factory_t &types() {
    static factory_t self;
    return self;
  }


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
07.04.2011, 14:57 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


natürlich ... *kopfauftisch* manchmal sind die einfachsten lösungen halt immer die die man nicht sieht ;-)
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
15.04.2011, 09:26 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


nochmal zu deiner factory:


C++:
void register_type(key_type key)
            {
                boost::mutex::scoped_lock l(lock_);
                instantiators_.insert(key, new instantiator_template<T>());
            }




hat der instantiators_ dann nicht ein speicherleck am ende?
schließlich werden die typen nirgends freigegeben?

oder räumt die boost::ptr_map das am ende auf?
--
class God : public ChuckNorris { };

Dieser Post wurde am 15.04.2011 um 09:27 Uhr von FloSoft editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
15.04.2011, 15:29 Uhr
0xdeadbeef
Gott
(Operator)


Das räumt die ptr_map auf, dafür ist sie ja da. Alternativ kann man das natürlich auch von Hand machen - der Aufwand ist nicht besonders groß - aber wo Boost die Funktionalität schon hatte, hab ich mich darum nicht mehr kümmern müssen.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: