Question

Quels sont les exemples les plus intéressants de métaprogrammation que vous avez vus en C ++?
Quelles sont les utilisations pratiques de la métaprogrammation que vous avez vues en C ++?

Était-ce utile?

La solution

Personnellement, je pense à Boost.Spirit est un exemple assez étonnant de méta-programmation. C’est un générateur d’analyseur complet qui vous permet d’exprimer des grammaires en utilisant la syntaxe C ++.

Autres conseils

L’utilisation la plus pratique de la méta-programmation consiste à transformer une erreur d’exécution en une erreur de compilation.

Exemple: appelons l'interface IFoo. L'un de mes programmes traitait d'un objet COM comportant plusieurs chemins d'accès à IFoo (hiérarchie d'héritage très compliquée). Malheureusement, l’implémentation de l’objet COM sous-jacent n’avait pas réalisé qu’ils avaient plusieurs chemins d’IFO. Ils ont supposé que c'était toujours le plus à gauche. Donc, dans leur code, le motif suivant était très commun

   void SomeMethod(IFoo* pFoo) {
        CFooImpl *p = (CFooImpl)pFoo;
   }

Le deuxième IFoo a cependant causé le " p " résultant; pointeur complètement invalide (l'héritage multiple est dangereux).

La solution à long terme consistait à demander au propriétaire de l'objet COM de résoudre ce problème. À court terme, je devais toutefois m'assurer que je retournais toujours le bon IFoo. Je pouvais garantir que j'avais l'IFoo approprié en utilisant un QI et en évitant tout transfert implicite à IFoo. J'ai donc créé un nouveau CComPtr & Lt; & Gt; implémentation et ajouté le remplacement suivant à la méthode equal.

template <typename T>
CComPtr<T>& operator=(const T* pT)  { 
// CComPTr Assign logic
}
template <>
CComPtr<IFoo> operator=<IFoo>(const IFoo* pT) {
  COMPILE_ERROR();
}

Cela a rapidement révélé chaque lieu que j’ai implicitement attribué à IFoo.

Pas d'utilisation pratique (sauf peut-être pour les tests du compilateur), mais metatrace est un Whitted-Style (c'est-à-dire récursif traceur et déterministe) générant des images similaires à celles du moment de la compilation:

exemple de métatrace

Certaines parties plus complexes du code sont visibles dans fixp.hh , qui possède une implémentation du sqrt à point fixe utilisant le Heron méthode ou sphere.hh qui montre l'intersection rayon / sphère calcul.

Blitz ++ fait des choses impressionnantes avec des modèles (par exemple, une seule ligne de code lisible peut être transformé en un ensemble de boucles sur un tableau multidimensionnel, automatiquement optimisé pour le meilleur ordre de traversée).

Le meilleur exemple de métaprogrammation: inciter le compilateur à calculer une liste de nombres premiers. Pas très pratique, mais impressionnante.

Les instructions d’assertion au moment de la compilation sont une utilisation pratique, c’est-à-dire qu’elles provoquent une erreur de compilation si une condition booléenne ne tient pas.

Je devrais dire Boost.Lambda, Boost.Function, et Boost.Bind et la manière dont ils fonctionnent de manière transparente. Ils fournissent une interface vraiment astucieuse et rendent la programmation fonctionnelle aussi simple que possible dans un langage qui n’a pas été construit pour elle.

luabind est un exemple pratique plutôt cool, un assez bon dsl de liaison pour lier les classes C ++ à Lua

BOOST_FOREACH

Assertion statique (améliore la version ici )

(Remarque: la prise en charge intégrée des boucles for et des assertions statiques basées sur la plage est introduite en C ++ 11)

J'ai posé une question il n'y a pas si longtemps: C ++ Connaissance d'exécution des classes et réponse que j'ai reçue d'un utilisateur StackOverflow & Quot; Denice & Quot; était une URL vers un site Web Meatspace: runtime C ++ inscription de classe .

Je pense que c’est une méthode très pratique pour utiliser des modèles et instancier des objets qui sont tous dérivés d’une classe de base. Ainsi, lorsque j’ai 10 fichiers C ++, ils peuvent tous simplement ajouter AUTO_REGISTER_BASE () en bas, et quand tout est fait et lié, seules les classes / fichiers qui l'ont créé seraient enregistrés. Ainsi, au moment de l'exécution, vous pouvez basculer entre les différentes classes disponibles. Les classes non disponibles ne sont pas enregistrées et ne peuvent donc pas être appelées par inadvertance. .

Il existe de nombreuses façons dépendantes du système d’exploitation de notifier un événement (select (), kqueue (), / dev / epoll, Solaris a sa propre fonction, poll ()) et j’avais besoin d’un moyen d’avoir toute la classe. des fichiers existent dans le répertoire, mais selon le système d’exploitation utilisé par Makefile, il ne compilerait que certains fichiers. Il me fallait un moyen de savoir au moment de l’exécution lesquelles étaient disponibles et de permettre au programmeur utilisant la bibliothèque de choisir leurs préférences. Toutefois, s’il n’était pas possible d’utiliser celle qui était la plus logique pour la plate-forme (elles ont des poids qui leur sont assignés).

Le code ci-dessus m'a aidé à atteindre cet objectif, avec quelques modifications lourdes, mais il m'a tout de même aidé!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top