Maison >développement back-end >C++ >Comment implémenter des compteurs de temps de compilation en C sans utiliser de variables globales ou d'état modifiable ?

Comment implémenter des compteurs de temps de compilation en C sans utiliser de variables globales ou d'état modifiable ?

Susan Sarandon
Susan Sarandonoriginal
2024-12-25 16:52:10941parcourir

How Can Compile-Time Counters Be Implemented in C   Without Using Global Variables or Modifiable State?

Compteurs de temps de compilation en C

Malgré la nature fonctionnelle de la métaprogrammation de modèles, les variables globales ou l'état modifiable ne sont pas facilement disponibles pour implémenter des compteurs de compilation. Cependant, comme démontré ci-dessous, la fonctionnalité de portée d'espace de noms peut être obtenue avec une utilisation minimale de modèles.

La recherche de fonctions peut être utilisée pour suivre l'état numérique à travers l'ensemble des fonctions déclarées, comme le montre le code suivant :

template // Return a number through function lookup.
struct cn // The function returns cn<n>.
{ char data[ n + 1 ]; }; // The caller uses (sizeof fn() - 1).

template
cn seen( id, cn, cn ); // Default fallback case.

#define counter_read( id ) \
( sizeof seen( id(), cn, cn, cn, cn, cn, cn, cn() ).data - 1 ) \
                      >() ).data - 1 ) \
                      >() ).data - 1 ) \
                      >() ).data - 1 ) \
                      >() ).data - 1 ) \
                      >() ).data - 1 )

#define counter_inc( id ) \
cn \
seen( id, cn, \
          cn )</n>

Démo rapide :

struct my_cnt {};

int const a = counter_read( my_cnt );
counter_inc( my_cnt );
counter_inc( my_cnt );
counter_inc( my_cnt );
counter_inc( my_cnt );
counter_inc( my_cnt );

int const b = counter_read( my_cnt );

counter_inc( my_cnt );

#include <iostream>

int main() {
    std::cout <p><strong>C 11 Mise à jour :</strong></p>
<p>En utilisant constexpr de C 11, une version mise à jour élimine l'utilisation de sizeof:</p>
<pre class="brush:php;toolbar:false">#define COUNTER_READ_CRUMB( TAG, RANK, ACC ) counter_crumb( TAG(), constant_index(), constant_index() )
#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_crumb( TAG, constant_index, \
                                                constant_index ) { return {}; }

#define COUNTER_LINK_NAMESPACE( NS ) using NS::counter_crumb;

template
struct constant_index : std::integral_constant {};

template
constexpr constant_index counter_crumb( id, constant_index, constant_index ) { return {}; } // found by ADL via constant_index

Cela élimine le besoin d'un espace de noms distinct pour chaque compteur, ce qui le rend plus pratique à utiliser dans plusieurs espaces de noms.

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn