Mi pregunta es similar a estos, pero no parece que se correlaciona exactamente:Cómo forzar la inclusión de definiciones de objetos "no utilizados" en una biblioteca
How to force inclusion of an object file in a static library when linking into executable?
Forcing symbol export with MSVC
Lo que tengo es algo así:
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);
Ahora, en un archivo concrete_thingy.cpp
tengo:
struct my_concrete_thingy : registered_thingy<my_concrete_thingy>
{
my_concrete_thingy() {} // registered_thingy's constructor not called otherwise
};
Por supuesto, lo anterior es totalmente inútil, pero aquí se abstrae el comportamiento real.
Esto funciona maravillosamente cuando se utiliza en una aplicación que se compila en su conjunto. El problema ahora es que no puedo, hasta ahora, usar esta técnica mientras embotello el comportamiento detrás de collection
en una biblioteca. En otras palabras, tengo un archivo thingys.lib
que contiene concrete_thingy.cpp
pero el registro no se produce cuando está vinculado a un ejecutable. El collection
termina existiendo y funciona bien, pero está vacío.
Ahora, esta es una biblioteca STATIC, no una DLL. Eso puede cambiar un poco el problema y las técnicas habladas en los enlaces de arriba no parecen aplicarse. Por supuesto, se trata de funciones y no veo cómo podría aplicarlo a estas estructuras de C++.
He tratado de utilizar el método #pragma comment
con las tres líneas siguientes (de forma individual por supuesto) en concrete_thingy.cpp
, ninguno de los cuales trabajó:
#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")
Si concrete_thingy.cpp
es ejecutable en el lugar de las obras de la biblioteca de muebles multa.
Así pues, aquí está mi pregunta:
1) ¿Es posible hacer lo que estoy tratando de hacer? Supongo que sí, pero no sé cómo.
2) Si es posible, ¿cómo podría obtener MSVC++ 2010 para hacerlo?
3) Si es posible, ¿cómo podría hacerlo de forma portátil?
En resumen, lo que estoy tratando de hacer sería similar a crear una fábrica abstracta que crea implementaciones de una abstracción. No sabe nada acerca de estas implementaciones, que se registran utilizando trucos de inicialización global. Todo esto debería estar en una biblioteca estática a la que pueda conectarse una aplicación y estas implementaciones deberían estar disponibles a través de esa fábrica. Nadie sabe nada sobre estas implementaciones, excepto ellos mismos y, por lo tanto, los enlaces normales los están haciendo desaparecer, y sus globales de registro.
No es exactamente lo que estoy haciendo, pero está lo suficientemente cerca.
Editar: ============================================ ========
Parece que este comportamiento es "por diseño".EM reconoce que la construcción del objeto que causan efectos secundarios deben ocurrir si su usado, que utilizan un vacío en la norma que les permite no incluyen unidades de traducción en los que se utiliza nada: \
https://connect.microsoft.com/feedback/viewfeedback.aspx?FeedbackID=244410&wa=wsignin1.0&siteid=210
La/OPT: la opción NOREF está diseñada para no hacer nada en este caso aparentemente.
"el constructor de registered_thingy no se llama de otra manera" -> hay otra manera de resolver el problema. Necesita una 'plantilla struct refit;' y luego puede decir, en lugar de definir un constructor, 'typedef refit user;' después de la declaración estática int. Esto forzará la creación de instancias de la estática también. Ver [esta respuesta] (http://stackoverflow.com/questions/401621/best-way-to-build-a-list-of-per-type-data/401801#401801) para una mayor elaboración. –
Al parecer, una vez más se ha demostrado que la diferencia entre un error y una característica es que la función está documentada. Por cierto ... ¿es realmente el truco de la plantilla necesaria? ¿No funcionaría mejor lo siguiente? 'struct concrete: abstract {concrete (...) {}} concrete_instance (...);' – 6502