2011-10-25 3 views
15

Esta pequeña pieza de código provoca la ira del enlazador cuando se incluye en al menos dos unidades de traducción (cpp):¿Por qué el enlazador se queja de múltiples definiciones en esta plantilla?

# ifndef MAXIMUM_HPP 
# define MAXIMUM_HPP 

template<typename T> 
T maximum(const T & a, const T & b) 
{ 
    return a > b ? a : b ; 
} 

/* dumb specialization */ 
template<> 
int maximum(const int & a, const int & b) 
{ 
    return a > b ? a : b ; 
} 

# endif // MAXIMUM_HPP 

Pero compila y enlaza bien con una unidad de traducción. Si elimino la especialización, funciona bien en todas las situaciones. Aquí está el mensaje del enlazador:

g++ -o test.exe Sources\test.o Sources\other_test.o 
Sources\other_test.o:other_test.cpp:(.text+0x0): multiple definition of `int maximum<int>(int const&, int const&)' 
Sources\test.o:test.cpp:(.text+0x14): first defined here 

¿No se pueden crear instancias de las plantillas varias veces? ¿Cómo explicar este error y cómo solucionarlo?

¡Gracias por cualquier consejo!

+0

Probablemente debería devolver una referencia de sus funciones. – Dani

+0

Fue solo un ejemplo resultante de rastrear los errores que encontré en un código más complejo. Creo que el ejemplo puede ser más claro sin ninguna referencia :) – overcoder

Respuesta

30

Es porque las especializaciones de plantillas explícitas completas deben definirse solo una vez: aunque el enlazador permite que las especializaciones implícitas se definan más de una vez, no permitirá especializaciones explícitas, solo las tratará como una función normal.
Para solucionar este error, coloque todas las especialidades en el archivo de origen como:

// header 

// must be in header file because the compiler needs to specialize it in 
// different translation units 
template<typename T> 
T maximum(const T & a, const T & b) 
{ 
    return a > b ? a : b ; 
} 

// must be in header file to make sure the compiler doesn't make an implicit 
// specialization 
template<> int maximum(const int & a, const int & b); 

// source 

// must be in source file so the linker won't see it twice 
template<> 
int maximum(const int & a, const int & b) 
{ 
    return a > b ? a : b ; 
} 
+0

¡Estoy más que agradecido! ¡Estaba a punto de preguntarte cómo reescribir el archivo de encabezado! – overcoder

11

Declarar las funciones en línea

// must be in header file because the compiler needs to specialize it in 
// different translation units 
template<typename T> 
inline T maximum(const T & a, const T & b) 
{ 
    return a > b ? a : b ; 
} 

/* dumb specialization */ 
template<> 
inline int maximum(const int & a, const int & b) 
{ 
    return a > b ? a : b ; 
} 
+1

¡Muchas gracias! Creo que podemos obtener una respuesta completa y precisa si fusionamos la tuya con la respuesta de Dani. – overcoder

Cuestiones relacionadas