Meine Frage an diesen ähnlich ist, aber scheint nicht genau zu korrelieren:Wie zu zwingen, Aufnahme von „nicht verwenden“ Objektdefinitionen in einer Bibliothek
How to force inclusion of an object file in a static library when linking into executable?
Forcing symbol export with MSVC
Was ich habe, so etwas wie ist so:
struct thingy;
struct container
{
static container& instance(); // singleton
int register_thingy(thingy*);
};
struct thingy
{
virtual ~thingy() {}
virtual int id() const = 0;
};
//template trick to force registration.
template < typename Derived >
struct registered_thingy : thingy
{
registered_thingy() : my_id(my_static_id) {}
int id() const { return my_id; }
private:
int my_id;
static int my_static_id;
}
template < typename Derived >
int registered_thingy<Derived>::my_static_id =
container::instance().register_thingy(new Derived);
nun in einer concrete_thingy.cpp
Datei ich habe:
struct my_concrete_thingy : registered_thingy<my_concrete_thingy>
{
my_concrete_thingy() {} // registered_thingy's constructor not called otherwise
};
Natürlich ist das Obige völlig nutzlos, aber hier wird echtes Verhalten abstrahiert.
Dies funktioniert wunderbar, wenn es in einer Anwendung verwendet wird, die als Ganzes kompiliert wird. Das Problem ist jetzt, dass ich bisher nicht in der Lage bin, diese Technik zu verwenden, während ich das Verhalten hinter collection
in einer Bibliothek abfülle. Mit anderen Worten, ich habe eine thingys.lib
Datei, die concrete_thingy.cpp
enthält, aber die Registrierung tritt nicht auf, wenn das mit einer ausführbaren Datei verknüpft ist. Die collection
endet oben vorhanden und funktioniert gut, aber es ist leer.
Jetzt ist dies eine statische Bibliothek, keine DLL. Das kann das Thema ein wenig verändern und die Techniken, die in den obigen Links erwähnt werden, scheinen nicht zu gelten. Das eine ist natürlich über Funktionen und ich sehe nicht, wie ich es auf diese C++ - Strukturen anwenden könnte.
Ich habe versucht, die #pragma comment
Verfahren mit den folgenden drei Zeilen zu verwenden (einzeln natürlich) in concrete_thingy.cpp
, von denen keines gearbeitet:
#pragma comment (linker, "/export:concrete_thingy")
#pragma comment (linker, "/export:concrete_thingy::my_static_id")
#pragma comment (linker, "/export:registered_thingy<concrete_thingy>::my_static_id")
Wenn concrete_thingy.cpp
in der ausführbaren Datei ist, anstatt die Bibliothek alles funktioniert fein.
Also dann, hier ist meine Fragen:
1) Ist es möglich, zu tun, was ich versuche zu tun, um? Ich denke ja, aber ich weiß nicht wie.
2) Wenn es möglich ist, wie würde ich MSVC++ 2010 dazu bekommen?
3) Wenn es möglich ist, wie kann ich es auf eine tragbare Weise tun?
Kurz gesagt, was ich versuche, wäre vergleichbar mit dem Erstellen einer abstrakten Fabrik, die Implementierungen einer Abstraktion erstellt. Es weiß nichts über diese Implementierungen, die unter Verwendung von globalen Initialisierungstricks registriert werden. Dies sollte alles in einer statischen Bibliothek sein, mit der eine Anwendung verknüpft werden kann, und diese Implementierungen sollten über diese Factory verfügbar sein. Niemand weiß etwas über diese Implementierungen, außer sich selbst, und daher führt eine normale Verknüpfung dazu, dass diese und ihre Registrierungs-Globals verschwinden.
Es ist nicht genau das, was ich vorhabe, aber es ist nahe genug.
Bearbeiten: ============================================= ========
Sieht aus wie dieses Verhalten "nach Entwurf" ist.MS erkennt, dass der Bau von Objekten, die Nebenwirkungen verursachen auftreten sollte, ob ihre verwendet wird, sie eine Lücke im Standard verwenden, die sie Einheiten nicht enthalten Übersetzung ermöglicht es, in der nichts verwendet wird: \
https://connect.microsoft.com/feedback/viewfeedback.aspx?FeedbackID=244410&wa=wsignin1.0&siteid=210
Die/OPT: Die NOREF-Option soll in diesem Fall scheinbar nichts tun.
"registered_thingys Konstruktor nicht anders genannt" -> es gibt eine andere Möglichkeit, das Problem zu lösen. Sie brauchen ein 'template struct refit;' und dann können Sie anstelle eines Konstruktors 'typedef refit user;' nach der statischen int-Deklaration angeben. Dies wird auch die Instanziierung der Statik erzwingen. Siehe [diese Antwort] (http://stackoverflow.com/questions/401621/best-way-to-build-a-list-of-per-type-data/401801#401801) für weitere Ausführungen. –
Anscheinend wird wieder einmal gezeigt, dass der Unterschied zwischen einem Fehler und einem Feature darin besteht, dass das Feature dokumentiert ist. Übrigens ... ist wirklich die Template-Trickerei nötig? würde das Folgende nicht besser funktionieren? 'struct concrete: abstract {konkreter (...) {}} concrete_instance (...);' – 6502