2010-07-18 12 views
10

Considérese la clase siguiente:Parámetros no dependientes del tipo de plantilla

class Foo 
{ 
    enum Flags {Bar, Baz, Bax}; 

    template<Flags, class = void> struct Internal; 

    template<class unused> struct Internal<Bar, unused> {/* ... */}; 
    template<class unused> struct Internal<Baz, unused> {/* ... */}; 
    template<class unused> struct Internal<Bax, unused> {/* ... */}; 
}; 

El esquema de la clase anterior compila y funciona como se esperaba cuando se prueba en VC++ 2010 y Comeau C++. Sin embargo, cuando Foo se hace en una plantilla en sí, las roturas anteriormente fragmento de bajo VC++ 2010.

Por ejemplo, el siguiente fragmento:

template<class> class Foo 
{ 
    // Same contents as the original non-templated Foo. 
}; 

produce el siguiente error class:

C2754: 'Foo<<unnamed-symbol>>::Internal<Bar,unused>' : a partial specialization cannot have a dependent non-type template parameter 
C2754: 'Foo<<unnamed-symbol>>::Internal<Baz,unused>' : a partial specialization cannot have a dependent non-type template parameter 
C2754: 'Foo<<unnamed-symbol>>::Internal<Bax,unused>' : a partial specialization cannot have a dependent non-type template parameter 

  1. ¿Puede alguien explicar lo que está pasando aquí en inglés?
  2. ¿Cómo puedo solucionar esto (es decir, mantener las especializaciones pseudoexplícitas internas en una plantilla de Foo) en VC++ 2010?
+1

Yo diría que los mensajes de error son falsos. FWIW, Comeau acepta el código incluso si 'Foo' es una plantilla. Sugiero que intentes en uno de los grupos de noticias de MS. La gente del compilador de MS solía pasar el rato allí. – sbi

Respuesta

4

¿Cómo se puede arreglar que este (es decir, mantener especializaciones seudo-explícita internos en una plantilla de Foo) en VC++ 2010?

Puede hacer que el tipo de enumeración no dependiente declarando en una clase base no molde (C++ 03 hizo clases anidadas dependientes en #108 pero que no incluye la enumeración, pero incluso si, como código todavía sería legal).

struct FooBase { 
    enum Flags {Bar, Baz, Bax}; 
}; 

template<class> class Foo : public FooBase { 
    template< ::FooBase::Flags, class = void > struct Internal; 
    // same other stuff ... 
}; 

El enlace "clase de error" ya proporciona una descripción de los casos previstos en los que se debe aumentar el error. El error cree que todos los tipos dependientes están prohibidos, pero de hecho esto es lo que dice el Estándar:

El tipo de un parámetro de plantilla correspondiente a un argumento especial sin tipo no dependerá de un parámetro de la especialización .

Así que incluso si el nombre Flags sería de alguna manera dependiente, que no lo hacen mal formada, con tal de que no depende de un parámetro de la especialización como en el ejemplo de la "clase de error" enlazar.

+3

Bastante molesto que Microsoft no puede producir un compilador conforme teniendo en cuenta toda su mano de obra. Especialmente cuando se tiene en cuenta el precio de venta de las ediciones no gratuitas. – rybz

+0

@litb: No estoy seguro de seguir: ¿cómo 'Flags' depende de un parámetro de la especialización? – HighCommander4

Cuestiones relacionadas