2010-01-21 9 views
6

Estoy trabajando en un proyecto bastante significativo que abarca muchas bibliotecas compartidas. También confiamos mucho en STL, Boost y nuestras propias clases y funciones de plantillas. Muchas clases exportadas contienen miembros de plantilla y las funciones exportadas contienen parámetros de plantilla.Uso de clases y funciones con plantilla en un objeto compartido/DLL

Aquí está un ejemplo reducida de la forma en que hago exportadora de biblioteca:

#if defined(_MSC_VER) && defined(_DLL) 
    // Microsoft 
    #define EXPORT __declspec(dllexport) 
    #define IMPORT __declspec(dllimport) 
#elif defined(_GCC) 
    // GCC 
    #define EXPORT __attribute__((visibility("default"))) 
    #define IMPORT 
#else 
    // do nothing and hope for the best at link time 
    #define EXPORT 
    #define IMPORT 
#endif 

#ifdef _CORE_COMPILATION 
#define PUBLIC_CORE EXPORT 
#define EXTERNAL_CORE 
#else 
#define PUBLIC_CORE IMPORT 
#define EXTERNAL_CORE extern 
#endif 

#include <deque> 

// force exporting of templates 
EXTERNAL_CORE template class PUBLIC_CORE std::allocator<int>; 
EXTERNAL_CORE template class PUBLIC_CORE std::deque<int, std::allocator<int> >; 

class PUBLIC_CORE MyObject 
{ 
private: 
    std::deque<int> m_deque; 
}; 

SO, mi problema es que cuando compilo en Visual Studio (2008 y 2010), me sale el siguiente advertencia:

C4251 advertencia: 'std :: _ Deque_val < _Ty, _Alloc> :: _ Almap' : clase 'std :: asignador < _Ty>' debe tener DLL-inter cara para ser utilizado por clientes de clase 'std :: _ Deque_val < _Ty, _Alloc>'

que parece dar a entender que no he exportado std::allocator<int>, lo que tengo. Y no es que mi exportadora es incorrecto, ya que no incluyen

EXTERNAL_CORE template class PUBLIC_CORE std::allocator<int>; 
EXTERNAL_CORE template class PUBLIC_CORE std::deque<int, std::allocator<int> >; 

produce la advertencia:

C4251 advertencia: 'MiObjeto :: m_deque': clase 'std :: deque < _Ty>' necesita tener DLL-interfaz para ser utilizado por clientes de clase 'MiObjeto'

lo único que ocurre es que el _Ty la advertencia sobre º e std::allocator está hablando de alguna manera no es int, pero parece que no puedo encontrar ninguna indicación de que sería de otra manera, ya que un std::deque<int> lógicamente asignaría un std::allocator<int>.

Una aplicación de consumo puede usar la clase muy bien, pero tengo la corazonada de que esta advertencia no se debe ignorar. Al compilar con g ++ en Linux, no se emiten errores (aunque eso no significa que funcione correctamente). ¿G ++ está haciendo automáticamente algo que MSVC no puede hacer? He estado apuntando a GCC en Linux, LLVM en OSX y MSVC en Windows, pero podría pasar al desarrollo de MinGW para Windows, por lo que abandonar MSVC no está fuera de discusión (si esto resulta ser un inconveniente). .

+1

_muy bien por su parte, ¡intente interpretar esas advertencias! – xtofl

+0

¿Es este un duplicado de (o similar a) http://stackoverflow.com/q/5661738/417197? –

Respuesta

3

Como ya sabrá, las plantillas en su archivo de exportación son, de hecho, un "permiso para completar lo que crea necesario" para el compilador.

Eso significa que si compila su archivo de encabezado con el compilador A, puede instanciar un deque<int> completamente diferente que el compilador B. El orden de algunos miembros puede cambiar, para uno, o incluso el tipo real de algunas variables miembro.

Y eso es lo que el compilador le está advirtiendo.

EDIT: addes algunas consecuencias para la explicación

Así que sus bibliotecas compartidas sólo funcionará muy bien juntos cuando se compila por el mismo compilador.Si desea que funcionen juntos, puede asegurarse de que todos los códigos de cliente "vean" la misma declaración (mediante el uso de la misma implementación de stl) o que den un paso atrás al agregar plantillas a su API.

+1

+1: no solo el mismo compilador, sino la misma versión del mismo compilador. VS 2008 y VS 2008 SP1 podrían tener diferentes implementaciones de y de los tipos de STL, por ejemplo. –

+0

Tenía la impresión de que declaraciones como 'clase de plantilla EXTERNAL_CORE PUBLIC_CORE std :: deque >;' tenían como objetivo obligar a los compiladores a compilar a un consumidor a usar la implementación de std :: deque del compilador original, mediante __dllimport. Los contenedores son las únicas cosas con las que realmente tengo un problema (ya que la exportación de cosas que no son tan complicadas parece funcionar bien). –

+0

@Travis: ¿Cómo sabría un compilador de destino cuál es la implementación original de std :: deque, por ejemplo? –

Cuestiones relacionadas