2012-07-01 7 views
8

Possible Duplicate:
GCC problem : using a member of a base class that depends on a template argumentconstantes definidas en clases de plantilla

pensé que estaba familiarizado con C++, pero al parecer no lo suficientemente familiar.
El problema es que cuando define una constante en una clase de plantilla, puede usar la constante en las nuevas clases que derivan de esa clase, pero no las nuevas plantillas que derivan de ella.

Por ejemplo, gcc dice

test.h:18: error: ‘theconstant’ was not declared in this scope

cuando intento compilar este (simplificado) archivo de cabecera:

#pragma once 

template <typename T> class base 
{ 
    public: 
    static const int theconstant = 42; 
}; 

class derive1 : public base<size_t> 
{ 
    public: 
    derive1(int arg = theconstant) {} 
}; 

template<typename T> class derive2 : public base<T> 
{ 
    public: 
    derive2(int arg = theconstant) {} // this is line 18 
}; 

Así que el problema es que una clase, derive1, compila bien, pero el otra clase, derive2, que es una especialización de plantilla, no lo hace.
Ahora tal vez el error de gcc no es lo suficientemente claro, pero no entiendo por qué el constructor en derive2 tendría un alcance diferente al de derive1.
En caso de que importe, esto ocurre durante la compilación del archivo de encabezado, no al crear un objeto de tipo derive2<type>.

También sé qué cambiar para hacer esta compilación, así que realmente no estoy buscando códigos de una línea como respuestas. Quiero entender por qué esto sucede! Intenté buscar en la web, pero aparentemente no estoy usando los argumentos de búsqueda correctos.

+0

FWIW, este mismo código compila bien en VC++ 2010. Esto podría ser un error en GCC ... – dsharlet

+0

'derive2 (int arg = base :: theconstant) {}' compila bien. – jrok

+0

@dsharlet - no es un error en la parte de GCC, como se describe en la especificación. – Flexo

Respuesta

2

Estoy bastante seguro de que esto le ayudará a entender:

Su código que no se compila:

template<typename T> class derive2 : public base<T> 
{ 
    public: 
    derive2(int arg = theconstant) {} // this is line 18 
}; 

Y la razón por la cual:

template <> class base<size_t> 
{ 
    public: 
    static const int ha_idonthave_theconstant = 42; 
}; 
derive2<size_t> impossible_isnt_it; 

La especialización !!! El compilador en su línea 18 no puede estar seguro de que no va a especializar la base <> en la forma en que esta constante no estará presente en absoluto.

+0

Eso tiene tanto sentido que me pregunto por qué no se me ocurrió ... Lo intenté con una plantilla especializada, que solo contenía el mismo miembro con un valor diferente, y no pude hacer que no funcionara. Oh bien. ¡Gracias! –

2

Trate

template<typename T> class derive2 : public base<T> 
{ 
    public: 
    derive2(int arg = base<T>::theconstant) {} // this is line 18 
}; 

Básicamente se ha especificado el alcance incompleto para el "theconstant".

+0

Sí, eso fue mencionado en los comentarios. Pero lo que quiero entender es por qué esto se considera necesario en 'derived2' y no en' derived1', incluso si la herencia no es ambigua. ¿De qué manera el alcance es incompleto? –

+1

Supongo que tiene que hacer algo con la instanciación de plantilla "vago". No hay _no_ clase 'base' conocida por el compilador en el momento en que analiza 'elconstante' en derive2. Una vez que use la base , fuerza al compilador a "familiarizarse" con la base <> –

+0

. Tendré que pensar en esto. –

Cuestiones relacionadas