Heim > Backend-Entwicklung > C++ > Wie können Kompilierzeitzähler in C implementiert werden, ohne globale Variablen oder veränderbare Zustände zu verwenden?

Wie können Kompilierzeitzähler in C implementiert werden, ohne globale Variablen oder veränderbare Zustände zu verwenden?

Susan Sarandon
Freigeben: 2024-12-25 16:52:10
Original
848 Leute haben es durchsucht

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

Kompilierungszeitzähler in C

Trotz der funktionalen Natur der Template-Metaprogrammierung stehen globale Variablen oder veränderbare Zustände nicht ohne weiteres zur Implementierung von Kompilierungszeitzählern zur Verfügung. Wie unten gezeigt, kann jedoch die Funktionalität des Namespace-Bereichs mit minimalem Einsatz von Vorlagen erreicht werden.

Funktionssuche kann verwendet werden, um den numerischen Status über den Satz deklarierter Funktionen zu verfolgen, wie im folgenden Code dargestellt:

template< size_t n > // Return 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.

#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 ) &amp; ~ counter_read( id ) >, \
          cn< ( counter_read( id ) + 1 ) &amp; counter_read( id ) > )
Nach dem Login kopieren

Schnelle Demo:

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 << a << ' ' << b << '\n';

    std::cout << counter_read( my_cnt ) << '\n';
}
Nach dem Login kopieren

C 11 Update:

Mit constexpr von C 11 entfällt in einer aktualisierten Version die Verwendung von sizeof:

#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 ) &amp; ~ COUNTER_READ( TAG ) >, \
                                                constant_index< ( COUNTER_READ( TAG ) + 1 ) &amp; COUNTER_READ( TAG ) > ) { return {}; }

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

template< std::size_t n >
struct constant_index : std::integral_constant< std::size_t, n > {};

template< typename id, std::size_t rank, std::size_t acc >
constexpr constant_index< acc > counter_crumb( id, constant_index< rank >, constant_index< acc > ) { return {}; } // found by ADL via constant_index
Nach dem Login kopieren

Dadurch entfällt die Notwendigkeit eines separaten Namespace für jeden Zähler, was die Bedienung komfortabler macht Zur Verwendung in mehreren Namespaces.

Das obige ist der detaillierte Inhalt vonWie können Kompilierzeitzähler in C implementiert werden, ohne globale Variablen oder veränderbare Zustände zu verwenden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage