Wie zu zwingen, die Aufnahme der "unbenutzt" - Objekt-Definitionen in einer Bibliothek
Meine Frage ist ähnlich wie diese, aber scheint nicht zu korrelieren genau:
Zwingen symbol exportieren mit MSVC
Was ich habe, ist so etwas wie 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 einem concrete_thingy.cpp
- Datei habe ich:
struct my_concrete_thingy : registered_thingy<my_concrete_thingy>
{
my_concrete_thingy() {} //registered_thingy's constructor not called otherwise
};
Natürlich ist völlig nutzlos, aber es gibt Reale Verhalten abstrahiert hier.
Dies funktioniert wunderbar, wenn verwendet, in einer Anwendung, die zusammengestellt als ganzes. Das Problem ist jetzt, dass ich bin nicht in der Lage, so weit, um diese Technik zu nutzen, während Abfüllen bis das Verhalten hinter collection
in einer Bibliothek. In anderen Worten, ich habe eine thingys.lib
- Datei, die enthält concrete_thingy.cpp
aber die Registrierung wird nicht ausgeführt, wenn das verbunden ist, um eine ausführbare Datei. Die collection
endet bestehenden und arbeiten gut, aber es ist leer.
Nun, dies ist eine STATISCHE Bibliothek, keine DLL. Das ändert sich möglicherweise die Ausgabe ein wenig und die Techniken gesprochen, die in den oben genannten links scheinen nicht zu gelten. Die eine ist natürlich über die Funktionen und ich sehe nicht, wie ich es anwenden konnte, um diesen C++ - Strukturen.
Habe ich versucht, den #pragma comment
Methode mit den folgenden drei Zeilen (einzeln natürlich) in concrete_thingy.cpp
, keiner von denen 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
ist in der ausführbaren Datei, anstatt die Bibliothek funktioniert alles einwandfrei.
Also dann, hier meine Fragen:
1) Ist es möglich, das zu tun, was ich versuche zu tun? Ich vermute ja, aber ich weiß nur nicht, wie.
2) Wenn es möglich ist, wie kann ich MSVC++ 2010 zu tun?
3) Wenn es möglich ist, wie könnte ich es in einen tragbaren Weg?
Kurz, was ich versuche zu tun, wäre ähnlich wie das erstellen einer abstrakten Fabrik, die schafft Implementierungen einer Abstraktion. Er weiß nichts über diese Implementierungen, die registriert sind, unter Verwendung der globalen Initialisierungs-Tricks. Dies sollten sich alle in eine statische Bibliothek, die verknüpft werden können, um durch eine Anwendung und diese Implementierungen verfügbar sein sollten, durch die Fabrik. Niemand weiß etwas über diese Implementierungen, mit Ausnahme von sich selbst und damit die normale Verknüpfung, ist das verursachen von Ihnen, und Ihre Registrierung globals, zu verschwinden.
Ist es nicht genau das, was ich bin, aber es ist nah genug.
Bearbeiten: ====================================================
Sieht wie das Verhalten ist "by design". MS erkennt, dass der Bau des Objekts, das Nebenwirkungen auftreten sollten, ob oder nicht, Ihr verwendet, Sie verwenden, um eine Lücke im standard, der es Ihnen ermöglicht nicht enthalten übersetzungseinheiten in dem nichts so ist, verwendet :\
https://connect.microsoft.com/feedback/viewfeedback.aspx?FeedbackID=244410&wa=wsignin1.0&siteid=210
/OPT:NOREF option soll nicht alles tun, in diesem Fall offensichtlich.
- "registered_thingy Konstruktor nicht aufgerufen wird, ansonsten" -> es ist ein weiterer Weg, um das Problem zu lösen. Sie brauchen eine
template<typename T, T&> struct refit;
und dann kann man sagen, stattdessen definieren Sie einen Konstruktor,typedef refit<int, my_static_id> user;
nach der static int Erklärung. Dies zwingt die Instanziierung des statischen zu. Siehe diese Antwort für die weitere Bearbeitung. - Scheinbar mal wieder gezeigt, dass der Unterschied zwischen einem bug und einem feature es ist, dass die Funktion dokumentiert ist. By the way ... ist wirklich die Vorlage, die Tricks nötig ? wäre nicht Folgendes besser funktionieren ?
struct concrete : abstract { concrete(...) {} } concrete_instance(...);
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gut, die anderen Antworten, wo gute versuche, aber letztlich fruchtlos. Ich bin mit dem refit-trick, aber der rest scheint ein Ablenkungsmanöver; es Art von Sinn macht, da die Vorlage in Frage, die nicht tatsächlich verwendet, anderswo, so dass die Tatsache, dass es nicht explizit instanziiert werden, sollte keinen Unterschied machen...die Deklaration der globalen passiert immer noch in Einer übersetzung Einheit, es hat Nebenwirkungen...ich glaube nicht, dass es die Norm zulässt optimiert werden entfernt.
Den unglücklichen bisschen über den standard nicht zu sagen, ob oder nicht es ist erforderlich, um eine übersetzung Einheit ist das ultimative Problem. Ich denke, dass C++0x etwas tun, aber vielleicht auch nicht... jedenfalls, Frau fühlt sich frei, damit Sie nicht die Einheit, und da es nicht das Globale ist nicht letztlich in der ausführbaren Datei enthalten und damit keiner der anderen Mist passiert.
Was ich beschlossen habe zu tun, und es gibt natürlich noch viele andere Möglichkeiten, ist eine Datei zu erstellen, die 'tag' - variable. Dieses tag wird dann zugewiesen, um in eine Funktion, die weltweit erreichbar (es HAT zuweisen oder zuweisen von oder der Verweis ist wegoptimiert). Dann diese Funktion aufgerufen werden, aus der ausführbaren Datei.
Ich beschlossen, es zu tun auf diese Weise, weil dann der rest noch funktioniert auf die gleiche wie immer. Ich glaube nicht, Ende bis schließlich ändern von Verhalten, wie ich könnte, wenn ich einfach nur schrieb eine Registrierungs-Funktion, hand-registriert-Typen. Plus ich kann andere Dinge tun, Dinge dieser Art...ich muss nur sicherstellen, dass alles, was möglicherweise fallen in diese Klassifizierung von fucktardery hat eine tag-und-tag zugegriffen wird.
Ich werde das schreiben ein paar Helfer Makros zu machen, diese meist schmerzlos.
Gibt es die linker-option /OPT:REF " und " /OPT:NOREF, auf die der Zugriff über linker->Optimierung->Referenzen.