2010-11-12 16 views
5

Dans C# 4.0, vous pouvez utiliser le mot clé "dynamic" comme espace réservé pour un type inconnu jusqu'à l'exécution. Il y a certains cas d'angle où c'est un comportement extrêmement utile. Est-il possible d'émuler quelque chose comme ça en C++, en utilisant éventuellement les fonctionnalités C++ 0x ou RTTI?L'équivalent C++ du mot-clé "dynamique" de C# 4.0?

+1

Essayant de construire un DSL typé canard qui compile en C++, fondamentalement. –

+1

Par coïncidence [j'ai écrit] (http://blackninjagames.com/?p=47) sur le canard en C++. Longue histoire courte, vous n'avez pas. Les templates vous permettent de taper du canard à la compilation, mais C++ est typé statiquement. Les modèles et le polymorphisme sont proches, mais souvent un peu moche. Ça sonne comme vous voulez [Boost.Proto] (http://www.boost.org/doc/libs/1_44_0/doc/html/proto.html). – GManNickG

+0

votre DSL supportera-t-il les types définis par l'utilisateur? –

Répondre

4

Pas vraiment. Le plus proche que vous pouvez obtenir est un void *, mais vous devez toujours le convertir en un type approprié avant de pouvoir l'utiliser.

Mise à jour:

Essayer de construire un DSL typé canard qui compile à C++, essentiellement.

Vous pouvez aller à ce sujet dans au moins deux façons:

variante Union basée

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

classe polymorphique heirarchy

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 ou Boost.Any peut aider BEAUCOUP avec ce genre de chose – KitsuneYMG

3

C# 's dynamic fonction est fortement dépendante de. Les capacités de réflexion intégrées de NET. Comme la norme C++ ne propose aucun support de réflexion, il est impossible d'obtenir un comportement similaire. RTTI vous permettra de baisser les pointeurs en toute sécurité, mais c'est à peu près tout. Vous êtes encore assez loin de pouvoir énumérer des champs et des méthodes et de les appeler dynamiquement.

-1

Je ne peux pas penser à un chemin de code possible où le type d'une valeur est réellement inconnu jusqu'à l'exécution. Même si vous liez deux modules ensemble (dynamiquement, au moment de l'exécution), les deux sont déjà compilés, et les types qu'ils peuvent renvoyer sont également entièrement déterminés, et en fait codés dans les noms mutilés des symboles exposés par la bibliothèque.

Vous pouvez cependant reporter la connaissance des types jusqu'à ce que le code soit réellement compilé. En C++ 0x, il y a le mot-clé auto, qui fournit l'inférence de type de l'expression utilisée pour initialiser la variable, et en courant C++, vous pouvez utiliser des modèles, comme ceci:

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

Edit: en fonction de votre commentaire Sur votre question, vous n'avez probablement pas de situation où le type est inconnu. Ce qui est plus probable, c'est que le type est limité à l'un des quelques types (prédéfinis). pour cela, vous pouvez utiliser un type union, de préférence en utilisant boost::variant

0

Ce n'est pas possible. Les tailles d'objet doivent être connues au moment de la compilation, de sorte que le pointeur de pile peut se déplacer d'un nombre d'octets approprié. Si vous ne déclarez pas le type, le compilateur ne connaîtra pas la taille. C# contourne ce problème en créant des pointeurs sur tous les objets.

1

Comme d'autres l'ont déjà dit ce n'est pas possible dans le cas général mais je pense qu'il serait instructif de voir pourquoi pas.

Il y a deux niveaux au problème, le niveau syntaxique et le niveau sémantique.

Sur le plan syntaxique vous avez le code suivant:

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

Dans .NET dynamic est une caractéristique du compilateur, ce qu'il fait est au lieu de générer un appel de fonction il crée un site d'appel qui contient le nom de la fonction et les types de paramètres (pour la surcharge). Cela signifie que si vous voulez prendre en charge la dynamique avez pour modifier le compilateur. Il est vrai que la méta-programmation de template permet de faire des choses similaires mais TMP est par nature fait au moment de la compilation et ne sera donc pas à la hauteur de la tâche de support de l'invocation d'exécution.

Si vous n'êtes pas anal sur la syntaxe, alors vous pourriez être en mesure de soutenir quelque chose comme ceci:

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

Sur le plan sémantique Comme @Trillian (nom d'utilisateur froid BTW) dit, dynamique repose à la réflexion, ceci n'est pas strictement vrai, vous pouvez spécifier comment dynamic is implemented, et la valeur par défaut pour les types CLR est la réflexion, donc le type lié à une variable dynamic doit supporter une sorte d'inspection d'exécution (par exemple COM IDispatch). Ce n'est pas vrai pour le cas général en C++ mais si vous pouvez limiter votre support uniquement aux types supportant un type d'inspection connu, vous pouvez implémenter dynamic en C++ (sans la syntaxe mentionnée ci-dessus).