2012-06-21 10 views
6

Tengo un código Java donde el tipo de devolución de una función tiene un tipo de comodín ilimitado (?). ¿Cómo puedo emular algo como esto en C++? p.ej.Cómo emular los genéricos de tipo 'signo de interrogación (?)' En Java a C++?

public GroupHandlerSetting<?> handleGroupProcessingFor(final EventHandler<T> eventHandler) 
    { 
     return new GroupHandlerSetting<T>(eventHandler, eventProcessors); 
    } 
+4

Y las plantillas de C++ ni siquiera son ligeramente como Java Generics. Las plantillas C++ crean nuevos tipos; Java Generics restringe los tipos existentes. Las plantillas de C++ son básicamente un preproceso con algunas reglas de tipo injertado; Java Generics se basa en la teoría de tipos. No se deje seducir por la notación para pensar que son casi equivalentes. Ellos no son – EJP

+3

Joshua Bloch afirma en varios videos que los comodines no deben usarse para los tipos de devolución. ¿Estás seguro de que son una buena idea en tu caso? ¿Puedes publicar la función o al menos su firma? – fredoverflow

+0

por favor, ¿podría agregar la función? –

Respuesta

6

En C++ todos los argumentos de tipo deben tener un nombre, ya sea que lo use o no, por lo que no hay signo de interrogación. Simplemente haga que sea un argumento de plantilla para la función y asígnele un nombre y debería estar bien.

template <typename T> 
struct templ { 
    template <typename U> 
    void assign(templ<U> & u);  // public void assign<?>(temple<U> u)  
}; 

Esa es la parte trivial, la parte más compleja es hacer cumplir las restricciones sobre el tipo, y para eso se puede utilizar SFINAE:

template <typename T> 
struct templ { 
    template <typename U, typename _ = std::enable_if< 
           typename std::is_base_of<U,T>::value 
             >::type > 
    void super(templ<U> & u);  // public void super_<? super T>(templ<?> u) 

    template <typename U, typename _ = std::enable_if< 
           typename std::is_base_of<T,U>::value 
             >::type > 
    void extends(templ<U> & u);  // public void extends_<? extends T>(templ<?> u) 
} 

que está utilizando C++ 11 para el SFINAE, en C++ 03, es un poco más intrincado (como si esta versión fuera simple) ya que no puede usar SFINAE en un argumento de plantilla de función, por lo que SFINAE debe aplicarse al tipo de retorno o a los argumentos de funciones adicionales. SFINAE es una solución mucho más poderosa, puede utilizarse no solo para proporcionar super y extends, sino también con muchas otras características de tipos o valores de tiempo de compilación. Google for SFINAE y encontrará muchos casos de uso de SFINAE, muchos de ellos serán de estilo C++ 03.

Hubo una propuesta de conceptos que habrían simplificado enormemente la sintaxis, pero no se llegó a un acuerdo y en un movimiento para llevar el estándar a su finalización se pospuso para un estándar posterior.

Ahora bien, esto no es tan común en C++ como lo es en Java, así que le recomiendo que haga una pregunta diferente sobre lo que quiere hacer, y obtendrá ideas para diseños en C++ más idiomáticos.

+2

Esto no es exactamente lo mismo. Compare estos dos en el sitio de llamadas: http://ideone.com/2LXUp y http://ideone.com/bMMJr. Si desea emular el comodín, necesita borrar el tipo. –

+0

@ R.MartinhoFernandes: Las plantillas y los genéricos no son lo mismo, pero puede implementar todo el código genérico que se puede hacer con genéricos mediante el uso de plantillas. A partir de su ejemplo, C++ no admite ese * olor en particular *, tenga en cuenta que los expertos en Java recomiendan no usar '?' En las declaraciones de retorno, la razón es que la implementación del método * sabe * el tipo, por lo que no hay razón para no publicarlo La única ventaja que '?' Proporciona en un tipo de devolución es que no necesita volver a compilar llamadas si el destinatario devuelve un tipo diferente para el marcador de posición ... –

+0

... pero eso es inútil en C++, como plantillas * debe recompilarse *, por lo que no es una característica la compatibilidad binaria (y poder usar un tipo lisiado en el sitio de llamadas, es decir, un tipo del cual conoce un par de pequeñas características que usted desconoce). En su ejemplo, en la versión de Java, siempre devuelve un 'ArrayList ', por lo que el ejemplo equivalente en C++ sería una función simple no genérica: 'std :: vector getSomeList()'. En la pregunta, el método es parte de una clase genérica (adivinar a partir de 'T'), por lo tanto, una función miembro sin plantilla de una plantilla. –

1

Su ejemplo específico es fácil de hacer, y como no uso Java, no puedo entender por qué necesita el <?> allí. En C++, que acaba de llenar en el mismo parámetro de plantilla:

template<class T> 
GroupHandlerSetting<T> handleGroupProcessingFor(EventHandler<T> const& evHandler){ 
    return GroupHandlerSetting<T>(evHandler, evProcessors); 
} 

T obtendrá deduce de lo argumento se pasa a handleGroupProcessingFor, y que utiliza de la misma manera T para el tipo de retorno, básicamente exactamente lo que haces en el cuerpo de la función.

+0

No estoy seguro de esto. Si pudiera simplemente reemplazar con , entonces creo que también es posible hacerlo en Java. No estoy seguro de por qué es necesario . Tengo poco conocimiento de Java, así que podría estar equivocado. – polapts

+1

@polapts: leyendo el comentario de la respuesta de David, parece que se necesita '' para borrar el tipo. En su ejemplo específico, puede salirse con la simple deducción de argumento. – Xeo

+0

@Xeo: '?' Es un marcador de posición de tipo, básicamente otro argumento de tipo que ni siquiera te importa nombrar. Puede establecer algunas restricciones sobre lo que es el tipo * desconocido *, es decir, puede requerir que sea una base o derivar de otro tipo (ya sea un argumento genérico o un tipo fijo). La diferencia entre su código y el código de pregunta es que en el código, el tipo 'T' debe ser el mismo tanto en el argumento como en la declaración de devolución, mientras que en el código de la pregunta no lo es (internamente puede devolver' GroupHandlerSetting 'independientemente de' T' y se compilaría. Sin embargo, es un mal diseño. –

Cuestiones relacionadas