2009-08-19 11 views
5

Escribir una función de plantilla, declaré:g ++ "no es un tipo de" error

template <typename T> 
T invertible(T const& container, T::size_type startIndex, T::size_type endIndex); 

Compilar con g ++ 4.0.1 Tengo el error:

error: 'T::size_type' is not a type 

Respuesta

7

Como descubriste, T :: size_type necesita ser prefijado con typename. ¿Por qué?

De "C++ Templates: The Complete Guide"

The language definition resolves this problem by specifying that in general a dependent qualified name does not denote a type unless that name is prefixed with the keyword typename.

... The typename prefix to a name is required when the name

  1. Appears in a template
  2. Is qualified
  3. Is not used as a list of base class specifications or in a list of member initializations introducing a constructor definition
  4. Is dependent on a template parameter

Furthermore the typename prefix is not allowed unless at least the first three previous conditions hold.

+0

He leído ese pasaje, gracias (los que leen en casa pueden ver la explicación detallada en la página 130). Todavía no veo por qué se requiere "typename" en una declaración de argumento, ya que tiene que ser un tipo, pero tal vez sea solo por coherencia con los enunciados en general. –

+1

@wnissen: Por lo general, tales requisitos existen para mantener felices a los constructores de analizadores. Parte del problema es que aparentemente ya sabes que es una declaración de argumento. Debido al problema de "analizar más molesto", el analizador generalmente tiene que deducirlo de los tokens entre(). Ahora, si dices que la interpretación de los tokens entre() debería depender de saber que es una declaración de argumento, entonces has introducido un problema de análisis cíclico. – MSalters

29

Es necesario añadir nombretipo.

I.e.

template <typename T> 
T invertible(T const& container, typename T::size_type startIndex, typename T::size_type endIndex); 

Sin tener ninguna información sobre el tipo T, el compilador necesita saber que T :: size_type designa un tipo.

de la norma, la sección 14.6.2:

A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename .

0

Resultó que necesitaba para especificar que T :: size_type era un nombre de tipo. ¿Porqué es eso?

template <typename T> 
T invertible(T const& container, typename T::size_type startIndex, typename T::size_type endIndex); 
+0

para eliminar la ambigüedad entre un posible nombre de instancia y un posible nombre del tipo. Para obtener más información, lea el libro C++ Templates; La Guía completa - información en http://www.josuttis.com/tmplbook/tmplbook.html –

+1

que debería ser una pregunta separada. (Aunque se ha preguntado antes. Buscar un poco) – jalf

3

Porque durante el análisis de la declaración de la plantilla, T no se conoce. Entonces el compilador no sabe si T :: size_type existe en absoluto. Puede referirse a una variable estática, por ejemplo. Cuando más tarde usas la plantilla, T es por supuesto conocida, pero el error ocurre antes. Y utilice algo menos antiguo que gcc 4.0.1 ;-)

Editar: Si compila con -permisivo, el compilador probablemente mastica su código, pero le dará una advertencia.

+0

gcc 4.0.1 es el más reciente - en el mac :) – Tobias

+1

Si es cierto, una razón más para no usar un mac. La última calidad de producción g ++ es 4.4.0 –

+0

Actualmente gcc 4.4.1. – hirschhornsalz

Cuestiones relacionadas