2010-11-12 12 views
5

In C# 4.0, è possibile utilizzare la parola chiave "dinamica" come segnaposto per un tipo sconosciuto fino al runtime. Ci sono alcuni casi d'angolo in cui questo è un comportamento estremamente utile. È possibile emulare qualcosa di simile in C++, possibilmente utilizzando funzionalità C++ 0x o RTTI?C++ equivalente della parola chiave "dinamica" di C# 4.0?

+1

Provare a creare un DSL con dattilo che si compila in C++, in pratica. –

+1

Per coincidenza [ho scritto] (http://blackninjagames.com/?p=47) sulla digitazione anatra in C++. Per farla breve, non lo fai. I template ti danno la digitazione in fase di compilazione, ma il C++ è tipizzato staticamente. I modelli e il polimorfismo sono vicini, ma spesso un po 'brutti. Sembra che tu voglia [Boost.Proto] (http://www.boost.org/doc/libs/1_44_0/doc/html/proto.html). – GManNickG

+0

il tuo DSL supporterà i tipi definiti dall'utente? –

risposta

4

Non proprio. Il più vicino che si può ottenere è un void *, ma è ancora necessario convertirlo in un tipo appropriato prima di poterlo utilizzare.

Aggiornamento:

cercando di costruire una DSL anatra tipizzato che compila in C++, in fondo.

Si può andare su questo in almeno due modi:

a base dell'Unione variante

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

classe polimorfica gerarchia

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 può aiutare molto con questo tipo di cose – KitsuneYMG

3

dynamic funzione C# s 'è altamente dipendente da Funzionalità di riflessione integrate di NET. Come standard C++ offre un supporto per la riflessione prossimo a zero, non c'è modo di ottenere un comportamento simile. RTTI ti permetterà di puntare con sicurezza verso il basso, ma questo è praticamente tutto. Sei ancora abbastanza lontano per essere in grado di enumerare campi e metodi e invocarli dinamicamente.

-1

Non riesco a pensare a un possibile percorso di codice in cui il tipo di un valore è in realtà sconosciuto fino in fase di esecuzione. Anche se si collegano insieme due moduli (dinamicamente, in fase di esecuzione), entrambi sono già compilati e anche i tipi che possono essere restituiti sono completamente determinati e, di fatto, codificati nei nomi storti dei simboli esposti dalla libreria.

È possibile, tuttavia, rimandare la conoscenza dei tipi fino a quando il codice deve essere effettivamente compilato. In C++ 0x, c'è la parola chiave auto, che fornisce l'inferenza di tipo dall'espressione usata per inizializzare la variabile, ed in corrente C++, è possibile utilizzare i modelli, in questo modo:

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

Edit: In base alle vostre commento sulla tua domanda, probabilmente non hai una situazione in cui il tipo è sconosciuto. Quel che è più probabile è che il tipo sia limitato a uno dei pochi tipi (predefiniti). per questo, è possibile utilizzare un tipo union, preferibilmente utilizzando boost::variant

0

Non è possibile. Le dimensioni degli oggetti devono essere note al momento della compilazione, quindi il puntatore dello stack può spostarsi del numero appropriato di byte. Se non si dichiara il tipo, il compilatore non conoscerà la dimensione. C# risolve questo problema rendendo tutti gli oggetti puntatori.

1

Come già detto, questo non è possibile nel caso generale, ma penso che sarebbe utile vedere perché no.

Ci sono due livelli per il problema, il livello sintattico e il livello semantico.

A livello sintattico avete il seguente codice:

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

In .NET dynamic è una caratteristica del compilatore, ciò che fa è invece di generare un funzione di chiamata si crea un sito chiamata che contiene il nome della funzione e i tipi di parametri (per sovraccarico). Ciò significa che se vuoi supportare dinamicamente lo hai per modificare il compilatore. È vero che la meta-programmazione dei template permette di fare cose simili ma TMP è per sua natura fatto in fase di compilazione e quindi non sarà all'altezza del compito di supportare l'invocazione del runtime.

Se non sei anale sulla sintassi, allora potreste essere in grado di sostenere qualcosa di simile:

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

Sul piano semantico Come @Trillian (nome utente freddo BTW) ha detto, dinamica si basa a riflessione, questo non è strettamente vero, è possibile specificare come dynamic is implemented e il valore predefinito per i tipi di CLR è il riflesso, quindi il tipo associato a una variabile dynamic deve supportare una sorta di ispezione di runtime (ad esempio, COM IDispatch). Questo non è vero per il caso generale in C++, ma se si può restringere il supporto solo ai tipi che supportano un tipo di ispezione (noto) è possibile implementare dynamic in C++ (senza la sintassi come menzionato sopra).

Problemi correlati