Menyingkap Nuansa dalam Pengaturcaraan Meta Kompilasi-Masa
Dalam bidang introspeksi, timbul keperluan untuk secara dinamik menetapkan pengecam unik atau melaksanakan operasi serupa pada jenis pada masa penyusunan. Walaupun pemrograman meta templat pada asasnya adalah bahasa berfungsi, ia nampaknya tidak mempunyai pembolehubah global yang diperlukan dan keadaan boleh diubah suai untuk melaksanakan operasi ini.
Anehnya, jawapan kepada dilema ini terletak pada persimpangan carian fungsi dan fungsi skop ruang nama . Carian fungsi menawarkan cara untuk mengekstrak keadaan berangka daripada set fungsi yang diisytiharkan.
Dalam contoh berikut, kami menunjukkan cara teknik ini boleh digunakan untuk mencapai pengiraan masa kompilasi:
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 ) > )
Pendekatan ini membolehkan penetapan pengecam unik dan penciptaan struktur data dengan saiz yang ditentukan oleh masa kompilasi. Perlu diingat bahawa teknik ini juga boleh dilaksanakan menggunakan kata kunci constexpr C 11, seperti yang ditunjukkan dalam kod yang dikemas kini di bawah:
#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 {}; }
Ringkasnya, sementara pengaturcaraan meta templat tradisional tidak mempunyai kesan sampingan, adalah mungkin untuk mencapai ruang nama -fungsi kaunter skop dengan memanfaatkan carian fungsi dan teknik yang dinyatakan di atas. Kaedah ini menyediakan penyelesaian praktikal untuk menetapkan pengecam unik secara dinamik dan menentukan saiz struktur data pada masa penyusunan, meningkatkan keupayaan introspeksi aplikasi C.
Atas ialah kandungan terperinci Bagaimanakah Pembilang Masa Kompilasi Boleh Dilaksanakan dalam C Menggunakan Carian Fungsi dan Fungsi Skop Ruang Nama?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!