2010-11-12 20 views
5

En C# 4.0, puede utilizar la palabra clave "dinámica" como marcador de posición para un tipo que no se conoce hasta el tiempo de ejecución. Hay ciertos casos de esquina donde este es un comportamiento extremadamente útil. ¿Es posible emular algo como esto en C++, posiblemente usando las características de C++ 0x o RTTI?C++ equivalente de la palabra clave "dinámica" de C# 4.0?

+1

Tratando de construir una DSL tipo pato que se compila en C++, básicamente. –

+1

Casualmente [He escrito] (http://blackninjagames.com/?p=47) sobre pato-tipado en C++. En resumen, no es así. Las plantillas le dan tipado de pato en tiempo de compilación, pero C++ tiene tipado estático. Las plantillas y el polimorfismo son cercanos, pero a menudo un poco feo. Parece que quieres [Boost.Proto] (http://www.boost.org/doc/libs/1_44_0/doc/html/proto.html). – GManNickG

+0

¿Su DSL admitirá tipos definidos por el usuario? –

Respuesta

4

Realmente no. Lo más cerca que puede obtener es un void *, pero igual debe convertirlo a un tipo apropiado antes de poder usarlo.

Actualización:

tratando de construir una conexión DSL de pato con tipo que se compila en C++, básicamente.

Puede ir sobre esto en por lo menos dos maneras:

a base de Unión variante

struct MyType { 
    enum { NUMBER, STRING /* etc */ } type; 
    union { 
    double number; 
    string str; 
    }; 
}; 

jerarquía de clase polimórfica

class MyType { 
public: 
    /* define pure virtual operations common to all types */ 
}; 

class MyNumber : public MyType { 
private: 
    double number; 
public: 
    /* implement operations for this type */ 
}; 
+1

Boost.Variant o Boost.Any puede ayudar MUCHO con este tipo de cosas – KitsuneYMG

3

característica de C# 's dynamic es altamente dependiente de. Capacidades de reflexión integradas de NET. Como estándar, C++ ofrece soporte casi sin reflejo, no hay manera de que pueda obtener un comportamiento similar. RTTI le permitirá bajar indicadores de forma segura, pero eso es más o menos. Todavía está bastante lejos para poder enumerar campos y métodos e invocarlos dinámicamente.

-1

No puedo pensar en una posible ruta de código donde el tipo de valor es realmente desconocido hasta el momento de la ejecución. Incluso si está uniendo dos módulos (dinámicamente, en tiempo de ejecución), ambos ya están compilados, y los tipos que pueden devolver también están totalmente determinados, y de hecho codificados en los nombres destrozados de los símbolos que expone la biblioteca.

Sin embargo, puede diferir el conocimiento de los tipos hasta que el código se compile realmente. En C++ 0x, hay la palabra clave auto, que proporciona la inferencia de tipos de la expresión que se utiliza para inicializar la variable y en la corriente C++, puede utilizar las plantillas, así:

template<typename T> 
T square(const T& someArg){ 
    return T*T; 
} 

Editar: Basado en su comentario en su pregunta, probablemente no tenga una situación en la que el tipo sea desconocido. Lo más probable es que el tipo esté limitado a uno de algunos tipos (predefinidos). para eso, puede usar un tipo union, preferiblemente usando boost::variant

0

No es posible. Los tamaños de los objetos deben conocerse en tiempo de compilación, por lo que el puntero de la pila puede moverse en la cantidad adecuada de bytes. Si no declaras el tipo, entonces el compilador no sabrá el tamaño. C# soluciona este problema haciendo punteros a todos los objetos.

1

Como ya han dicho otros, esto no es posible en el caso general, pero creo que sería informativo ver por qué no.

Existen dos niveles para el problema, el nivel sintáctico y el nivel semántico.

En el nivel sintáctico tiene el siguiente código:

dynamic d = /* something */; 
d.Foo(bar); // Foo is unknown at compile time 

En .NET dynamic es una característica del compilador, lo que hace es en lugar de generar una llamada función crea un sitio llamado que contiene el nombre de la función y los tipos de parámetros (para la sobrecarga). Esto significa que si desea admitir dinámicas, tiene para modificar el compilador. Es cierto que la programación de metadatos de plantillas permite hacer cosas similares, pero TMP se realiza por su propia naturaleza en tiempo de compilación y, por lo tanto, no estará a la altura de admitir la invocación en tiempo de ejecución.

Si no estás anal sobre la sintaxis entonces usted puede ser capaz de soportar algo como esto:

dynamic d = /* something */; 
d.invoke("Foo", bar); 

En el nivel semántico Como @Trillian (nombre de usuario fresca por cierto) dicho, dinámica se basa en la reflexión, esto no es estrictamente cierto, puede especificar cómo dynamic is implemented, y el valor predeterminado para tipos CLR es reflejo, por lo que el tipo vinculado a una variable dynamic debe admitir algún tipo de inspección en tiempo de ejecución (por ejemplo, COM IDispatch). Esto no es cierto para el caso general en C++, pero si puede limitar su compatibilidad solo a tipos que admitan (un conocido) tipo de inspección, puede implementar dynamic en C++ (sin la sintaxis mencionada anteriormente).

Cuestiones relacionadas