2010-02-17 8 views
5

Este es un fragmento de una plantilla de clase que está causando errores de compilación 'sktraits':espera anidada-nombre-especificador antes

/* Secondary index class */ 
template<class TKey, class TVal, class key_traits, class val_traits> 
template<class TSecKey, class sktraits> 
class CBtreeDb<TKey, TVal, key_traits, val_traits>::CDbSecondaryIndex: protected CBtreeDb<TKey, TVal>, public IDeallocateKey 
{ 
public: 
typedef TSecKey   skey_type; 
typedef typename sktraits       skey_traits; 
typedef CNewDbt<TSecKey, sktraits>    CDbSKey; 
typedef typename iterator_t<TSecKey, skey_traits> iterator; 
typedef typename iter_lower_bound_t<skey_type> iter_lower_bound; 
typedef typename iter_upper_bound_t<skey_type> iter_upper_bound; 

CDbSecondaryIndex(CDbEnv* pEnv, u_int32_t flags, bool bAllowDuplicates=false): 
    CBtreeDb(pEnv, flags, bAllowDuplicates) 
{ 

} 

    // Class implementation continues ... 
}; 

El mensaje de error del compilador que recibo es:

expected nested-name-specifier before 'sktraits'. 

realidad , este error ocurre en cada declaración typedef seguido por typename

He compilado este código con éxito en el pasado usando VS2005 y VS2008 en X PAG.

Estoy construyendo en Ubuntu 9.10, con gcc 4.4.1

Miré este error en Google y parece que la typename no es necesario en la línea (donde se produce el error), debido a que la la suposición estándar es que un identificador en esa posición es un tipo. g ++ parece estarse quejando porque espera que cualquier declaración typename esté calificada (es decir, A :: B).

¿Este es un diagnóstico correcto del problema? En caso afirmativo, ¿cómo califico completamente el typename?

En resumen, ¿cómo puedo resolver este problema?

+0

Me las arreglé para arreglar esto (es decir, obtener el código para compilar) - simplemente eliminando el 'typename' que sigue al typdef decl. Aunque el encabezado compila con éxito ahora, todavía no estoy satisfecho porque quiero saber el motivo subyacente (es decir, la razón técnica) por la que tuve que eliminar typename (especialmente, cuando se utiliza una notación similar en las clases de STL) –

Respuesta

0

no está permitido lo siguiente:

template<class A> 
template<class B> class F { ... }; 

Puede tener como máximo una template<> las especificaciones antes de una definición de clase/función.

+0

Explique. La gente Comeau no está de acuerdo: http: //www.comeaucomputing.com/techtalk/templates/# outsidedef - No tengo ningún estándar práctico, pero Comeau es bastante confiable. –

+0

La norma dice en 14.5.2/1: "Una plantilla de miembro de una plantilla de clase que se defina fuera de su definición de plantilla de clase se debe especificar con los parámetros de plantilla de la plantilla de clase seguidos de los parámetros de plantilla de la plantilla de miembro ", y da un ejemplo:' template template int string :: compare (const T2 & s) '. –

7

typename es necesario para especificar que un nombre dependiente es de hecho un tipo. Sus nombres no son nombres dependientes, por lo que no se requiere ni se permite typename.

actualización La norma tiene en realidad esta definición sintaxis:

nombre de tipo especí fi cador:
    nombretipo anidada nombre especí fi cador de identi fi er
    nombretipo nested- nombre-especi fi cador plantilla opt sencilla-plantilla-id

Los otros dos lugares que usted puede utilizar la palabra clave nombretipo están en la lista de parámetros de plantilla y en la declaración using (en este último caso también debe ser seguido por una especificador de nombre anidado).

Cuestiones relacionadas