2011-06-03 6 views
15

This snippet (tomado de this question) compila bien con g ++ (como se ve), siempre que el template antes de que el tipo de devolución esté allí. Por el contrario, VC10 no compila el código con el siguiente error:¿Qué compilador tiene razón? 'plantilla' antes del tipo de retorno de plantilla necesario?

error C2244: 'A::getAttr' : unable to match function definition to an existing declaration

Si quito el template, VC10 es feliz, pero g ++ grita este error:

error: non-template 'AttributeType' used as template
note: use 'A::template AttributeType' to indicate that it is a template

¿También se debe de VC está roto búsqueda de dos fases o ¿cuál es la causa? ¿Qué compilador está aquí? Sospecho que g ++ es correcto, ya que tengo un vago recuerdo de template que se necesita aquí, como con la plantilla rebind dentro de los asignadores.


Editar: Tenemos un ganador: g ++/GCC (sorpresa, sorpresa ...).


template <typename T, typename K> 
class A { 
public: 
    T t; 
    K k; 

    template <int i, int unused = 0> 
    struct AttributeType{ 
    }; 

    template <int i> 
    AttributeType<i> getAttr(); 

}; 

template <typename T, typename K> 
template <int i> 
typename A<T, K>::template AttributeType<i> A<T, K>::getAttr() { 
//    ^^^^^^^^ -- needed or not? 
    return t; 
} 


int main(){ 
    A<int,int> a; 
} 
+3

el código postal en la pregunta. Apoye los soportes de desbordamiento y lo alienta firmemente. –

+1

En general, el "compilador de referencia" informal para el cumplimiento estándar es Comeau, puede intentar enviar su fragmento [aquí] (http://www.comeaucomputing.com/tryitout/) para ver su veredicto. - EDITAR: intentado ahora, el fragmento compila bien como está en Ideone. –

+0

@Merlyn: Quería mantener esta pregunta corta, sin embargo. – Xeo

Respuesta

10

GCC es correcto. AttributeType es un nombre de plantilla dependiente seguido del corchete angular <, por lo que se requiere la palabra clave template para eliminar la ambigüedad , dejando en claro para el compilador que lo que se sigue es un nombre de plantilla. La regla se menciona en §14.2/4:

When the name of a member template specialization appears after . or -> in a postfix-expression, or after nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a template-parameter (14.6.2), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.

@Johannes ha escrito una muy buena explicación aquí:

Where and why do I have to put the "template" and "typename" keywords?

+2

Gracias, esa fue la cotización estándar que estaba buscando. – Xeo

Cuestiones relacionadas