Nochmal Danke für die Hilfe! Das eigentliche Problem hatte ich ja ein paar Beiträge weiter oben beschrieben: es geht um eine Class Factory, die auch die Möglichkeit anbieten muss, ein Objekt zu kopieren. Dazu wird über einen Mechanismus, der hier nicht zum Thema gehört, der Type des Vorlageobjekts bestimmt, damit die dazugehörige Ableitung des ObjektErzeugeHelfers bestimmt und der erstellt dann mittels Kopierkonstruktor eine eine Instanz diesen Typs.
Und nun ist das Problem, dass manche Klassen nicht kopierbar sind. Hier konkret das Problem, dass boost::signal nicht kopierbar ist und damit auch alle Klassen, die Signale haben. Also sollte die Klassenfabrik selbsttätig herausbekommen, ob die Basisklasse kopierbar ist, und die Kopier-Funktion danach anbieten oder auch nicht. An der Stelle nochmal Danke an CodingCat und seine geduldigen Erklärungen. Der Compiler kann natürlich nicht wissen, ob eine Ableitung der Basisklasse irgendwo ein Signal enthält. Daher ist es immernoch meine Pflicht, in dem Fall die Basisklasse als "nicht kopierbar" zu markieren. Und da ich das eh immer mit boost::noncopyable mache, kann ich auch einfach prüfen, ob die Klasse davon ableitet. CodingCats Vorschlag folgend sieht die Gesamtkonstruktion jetzt so aus:
Code: Alles auswählen
namespace FabrikHelfer {
/// FabrikHelfer-Klasse
template <typename Basisklasse> class BasisHelfer {
virtual Basisklasse* ErzeugeObjekt() const = 0;
virtual Basisklasse* KopiereObjekt( const Basisklasse* pObjekt) const { return nullptr; };
};
/// Template-Helfer zur Unterscheidung zwischen kopierbaren und nicht kopierbaren Klassen
template <typename Basisklasse, typename Klasse, bool IstKopierbar> class HelferDef
: public BasisHelfer<Basisklasse>
{ };
template <typename Basisklasse, typename Klasse> class HelferDef<Basisklasse, Klasse, true>
: public HelferDef<Basisklasse, Klasse, false>
{
Basisklasse* KopiereObjekt( const Basisklasse* pObjekt) const override { return new Klasse( *(static_cast<const Klasse *> (pObjekt))); };
};
/// Helferobjekt für Klassenregistrierung bei einer Objektfabrik
template <class Basisklasse, class Klasse> class Helfer
: public HelferDef<Basisklasse, Klasse, !std::is_base_of<boost::noncopyable, Basisklasse>::value>
{
Basisklasse* ErzeugeObjekt() const override { return new Klasse(); }
};
}
/// die eigentliche Class Factory
template <class Basisklasse> class Fabrik
{
protected:
// Sammlung aller Erzeuger-Helferobjekte anhand des Namens der erzeugten Klasse
std::map< std::string, Traum_FabrikHelfer::BasisHelfer<Basisklasse> *> mErzeuger;
public:
/// Registriert eine neue Klasse mit Name und Erzeuger.
void AddKlasse( const std::string& pName, Traum_FabrikHelfer::BasisHelfer<Basisklasse> *pKlassenhelfer)
{
mErzeuger[pName] = pKlassenhelfer;
}
/// Erzeugt ein Objekt der gegebenen Klasse.
Basisklasse* ErzeugeObjekt( const std::string &pKlassenname) const
{
return mErzeuger[pKlassenname]->ErzeugeObjekt();
}
/// Erzeugt eine Kopie des übergebenen Objekts.
Basisklasse* KopiereObjekt( const Basisklasse* pObjekt) const
{
auto derRichtigeFabrikHelfer = IrrelevanteFunktion( pObjekt);
return derRichtigeFabrikHelfer->KopiereObjekt( pObjekt);
}
};
Wie man sieht, ist aktuell ein Runtime-Fehler draus geworden: wenn die Basisklasse nicht kopierbar ist, wird die KopiereObjekt()-Funktion nicht überschrieben und die Basis-Implementation gibt halt einfach nullptr zurück. Das werde ich jetzt noch korrigieren, indem ich den Ableitung-Mit-TemplateBool-Trick auch auf die Fabrik selbst anwende. Dann müsste es ein Compiler-Fehler sein, wenn ich die KopiereObjekt()-Funktion einer Fabrik aufrufe, deren Klasse nicht kopierbar ist.
Danke!