Dévoilement de la nuance dans la métaprogrammation au moment de la compilation
Dans le domaine de l'introspection, il est nécessaire de attribuez dynamiquement des identifiants uniques ou exécutez des opérations similaires sur les types au moment de la compilation. Bien que la métaprogrammation de modèles soit essentiellement un langage fonctionnel, il semble manquer des variables globales et de l'état modifiable nécessaires pour implémenter ces opérations.
Étonnamment, la réponse à ce dilemme réside à l'intersection de la recherche de fonctions et des fonctionnalités de portée d'espace de noms. . La recherche de fonctions offre un moyen d'extraire l'état numérique d'un ensemble défini de fonctions déclarées.
Dans l'exemple suivant, nous montrons comment cette technique peut être appliquée pour réaliser un comptage au moment de la compilation :
template< size_t n > // This type returns a number through function lookup. struct cn // The function returns cn<n>. { char data[ n + 1 ]; }; // The caller uses (sizeof fn() - 1). template< typename id, size_t n, size_t acc > cn< acc > seen( id, cn< n >, cn< acc > ); // Default fallback case. /* Evaluate the counter by finding the last defined overload. Each function, when defined, alters the lookup sequence for lower-order functions. */ #define counter_read( id ) \ ( sizeof seen( id(), cn< 1 >(), cn< \ ( sizeof seen( id(), cn< 2 >(), cn< \ ( sizeof seen( id(), cn< 4 >(), cn< \ ( sizeof seen( id(), cn< 8 >(), cn< \ ( sizeof seen( id(), cn< 16 >(), cn< \ ( sizeof seen( id(), cn< 32 >(), cn< 0 \ /* Add more as desired; trimmed for Stack Overflow code block. */ \ >() ).data - 1 ) \ >() ).data - 1 ) \ >() ).data - 1 ) \ >() ).data - 1 ) \ >() ).data - 1 ) \ >() ).data - 1 )
#define counter_inc( id ) \ cn< counter_read( id ) + 1 > \ seen( id, cn< ( counter_read( id ) + 1 ) & ~ counter_read( id ) >, \ cn< ( counter_read( id ) + 1 ) & counter_read( id ) > )
Cette approche permet l'attribution d'identifiants uniques et la création de structures de données avec des tailles déterminées au moment de la compilation. Il convient de noter que cette technique peut également être implémentée à l'aide du mot-clé constexpr de C 11, comme indiqué dans le code mis à jour ci-dessous :
#define COUNTER_READ_CRUMB( TAG, RANK, ACC ) counter_crumb( TAG(), constant_index< RANK >(), constant_index< ACC >() ) #define COUNTER_READ( TAG ) COUNTER_READ_CRUMB( TAG, 1, COUNTER_READ_CRUMB( TAG, 2, COUNTER_READ_CRUMB( TAG, 4, COUNTER_READ_CRUMB( TAG, 8, \ COUNTER_READ_CRUMB( TAG, 16, COUNTER_READ_CRUMB( TAG, 32, COUNTER_READ_CRUMB( TAG, 64, COUNTER_READ_CRUMB( TAG, 128, 0 ) ) ) ) ) ) ) ) #define COUNTER_INC( TAG ) \ constexpr \ constant_index< COUNTER_READ( TAG ) + 1 > \ counter_crumb( TAG, constant_index< ( COUNTER_READ( TAG ) + 1 ) & ~ COUNTER_READ( TAG ) >, \ constant_index< ( COUNTER_READ( TAG ) + 1 ) & COUNTER_READ( TAG ) > ) { return {}; }
En résumé, bien que la métaprogrammation de modèles traditionnelle manque d'effets secondaires, il est possible d'obtenir un espace de noms -Fonctionnalité de compteur de portée en tirant parti de la recherche de fonctions et des techniques susmentionnées. Ces méthodes fournissent une solution pratique pour attribuer dynamiquement des identifiants uniques et déterminer la taille des structures de données au moment de la compilation, améliorant ainsi les capacités d'introspection des applications C.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!