2011-07-19 36 views
10

Estoy haciendo una clase de plantilla con una clase de utilidad interna. Todas las especializaciones de la plantilla quieren la misma clase interna:¿Puede una clase interna de una clase de plantilla ser una clase sin plantilla?

template<...> class Outer { 
    class Inner { }; 
}; 

Eso me da Outer<...>::Inner pero quiero todo Inner a ser del mismo tipo, como si acabara escrito:

class Inner { }; 
template <...> class Outer { }; 

o si Outer no eran simplemente una clase de plantilla:

class Outer { 
    class Inner { }; 
}; 

me Outer::Inner dar. Me gustaría que Outer::Inner funcione para todos Outer<> si eso es posible (solo por motivos de espacio de nombres/claridad). De lo contrario, por supuesto, puedo mover Inner.

+1

Estoy bastante seguro de que la respuesta es no, pero estoy esperando que alguien demuestra que estoy equivocado, porque yo sucede que está en una situación similar :) –

+1

Solo estoy * bastante * seguro de que la respuesta es no, pero también espero soluciones inteligentes ... –

Respuesta

15

La clase anidada puede no ser una plantilla, pero cada creación de instancias de la plantilla tendrá su propia clase anidada porque son (de lo contrario) tipos no relacionados. Puede hacer

namespace detail { 

class Inner {}; 

} // detail 

template<...> 
class Outer { 
    typedef detail::Inner Inner; 
}; 
+0

Solución limpia y sexy –

+0

Me olvido de los detalles de mi espacio de nombres - puedo ' clase Inner' estar oculto, ahora, como si estuviera en una clase interna "verdadera"? ¿O algún código incluido podrá tenerlo? – Nate

+0

@Nate Lo anterior se comporta como con cualquier 'typedef'. 'Inner' puede quedar incompleto con solo una declaración que no sea también una definición (es decir,' class Inner; '), con todas las advertencias que implica. Pero debe declararse (el nombre 'detail :: Inner' debe referirse a algo), o de lo contrario no puede ser' typedef''d. –

0

Será único para cada instanciación de Outer. Es decir,

Outer<int>::Inner will be a different type from Outer<double>::Inner 
+1

Este hecho es bien conocido por el OP, ya que lo ha expresado claramente en su problema –

13

La forma en que he hecho esto en el pasado se utilizaba la herencia:

class DummyBase{ 
protected: 
    class Inner{ 
     //etc... 
    }; 
}; 

template<...> class Outer : public DummyBase{ 
    //etc... 
}; 
+0

+1 Esto es inteligente, pero me gusta más la respuesta de Luc. –

+1

+1, porque esto convierte 'Outer <> :: Inner' en un nombre de clase real. Así 'clase Outer <> :: Inner x;' o 'friend class Outer <> :: Inner;' seguiría funcionando, mientras que la solución 'typedef' fallará allí. –

Cuestiones relacionadas