Bisakah Anda memberi contoh di mana static_assert(...)
('C ++ 11') akan menyelesaikan masalah di tangan dengan elegan?
Saya akrab dengan run-time assert(...)
. Kapan saya harus memilih static_assert(...)
daripada biasa assert(...)
?
Juga, di dalam boost
ada yang disebut BOOST_STATIC_ASSERT
, apakah sama dengan static_assert(...)
?
Jawaban:
Dari atas kepala saya...
Dengan asumsi itu
SomeLibrary::Version
dideklarasikan sebagai konstanta statis, bukan sebagai#define
d (seperti yang diharapkan dalam pustaka C ++).Berbeda dengan harus benar-benar mengkompilasi
SomeLibrary
dan kode Anda, hubungan segalanya, dan menjalankan eksekusi hanya kemudian untuk mengetahui bahwa Anda menghabiskan 30 menit kompilasi versi tidak kompatibelSomeLibrary
.@Arak, menanggapi komentar Anda: ya, Anda bisa
static_assert
duduk di mana saja, dari tampilan itu:sumber
static_assert
konteks non-eksekusi? Tampaknya contoh yang sangat bagus :)static_assert
. Jika kondisi tidak akan diketahui sampai program berjalan, gunakanassert
.Penegasan statis digunakan untuk membuat pernyataan pada waktu kompilasi. Ketika pernyataan statis gagal, program tidak dapat dikompilasi. Ini berguna dalam situasi yang berbeda, seperti, misalnya, jika Anda menerapkan beberapa fungsionalitas dengan kode yang sangat bergantung pada
unsigned int
objek yang memiliki persis 32 bit. Anda dapat menempatkan pernyataan statis seperti inidalam kode Anda. Di platform lain, dengan jenis ukuran yang berbeda
unsigned int
, kompilasi akan gagal, sehingga menarik perhatian pengembang ke bagian kode yang bermasalah dan menyarankan mereka untuk menerapkan ulang atau memeriksanya kembali.Untuk contoh lain, Anda mungkin ingin meneruskan beberapa nilai integral sebagai
void *
pointer ke suatu fungsi (hack, tetapi kadang berguna) dan Anda ingin memastikan bahwa nilai integral akan sesuai dengan pointerAnda mungkin ingin aset
char
jenis itu ditandatanganiatau pembagian integral dengan nilai negatif membulatkan ke arah nol
Dan seterusnya.
Dalam banyak kasus, pernyataan run-time dapat digunakan sebagai pengganti pernyataan statis, tetapi pernyataan run-time hanya berfungsi pada waktu proses dan hanya jika kontrol melewati pernyataan. Karena alasan ini, pernyataan run-time yang gagal mungkin tidak aktif, tidak terdeteksi untuk waktu yang lama.
Tentu saja, ekspresi dalam pernyataan statis harus berupa konstanta waktu kompilasi. Ini tidak bisa menjadi nilai run-time. Untuk nilai run-time Anda tidak punya pilihan lain selain menggunakan yang biasa
assert
.sumber
static_assert
dari C ++ 11 secara khusus. Saya distatic_assert
atas hanyalah beberapa implementasi abstrak dari pernyataan statis. (Saya pribadi menggunakan sesuatu seperti itu dalam kode C). Jawaban saya dimaksudkan tentang tujuan umum pernyataan statis dan perbedaannya dari pernyataan run-time.unsigned int
. Ini tidak dijamin oleh standar. Variabel tipeunsigned int
secara legal dapat menempati 32 bit memori, meninggalkan 16 bit di antaranya tidak digunakan (dan dengan demikian makroUINT_MAX
akan sama dengan65535
). Jadi cara Anda mendeskripsikan pernyataan statis pertama ("unsigned int
objek yang memiliki persis 32 bit") menyesatkan. Untuk mencocokkan keterangan Anda, pernyataan ini harus dimasukkan juga:static_assert(UINT_MAX >= 0xFFFFFFFFu)
.Saya menggunakannya untuk memastikan asumsi saya tentang perilaku compiler, header, libs, dan bahkan kode saya sendiri sudah benar. Misalnya di sini saya memverifikasi bahwa struct telah dikemas dengan benar ke ukuran yang diharapkan.
Dalam pembungkus kelas
stdio.h
'sfseek()
, saya telah mengambil beberapa cara pintas denganenum Origin
dan cek bahwa mereka pintas sejajar dengan konstanta yang didefinisikan olehstdio.h
Anda harus memilih
static_assert
lebihassert
saat perilaku didefinisikan pada waktu kompilasi, dan tidak pada saat runtime, seperti contoh yang saya berikan di atas. Contoh di mana hal ini tidak terjadi akan mencakup pemeriksaan parameter dan kode kembali.BOOST_STATIC_ASSERT
adalah makro pra-C ++ 0x yang menghasilkan kode ilegal jika kondisinya tidak terpenuhi. Tujuannya sama, meskipunstatic_assert
sudah terstandarisasi dan dapat memberikan diagnostik compiler yang lebih baik.sumber
BOOST_STATIC_ASSERT
adalah pembungkus lintas platform untukstatic_assert
fungsionalitas.Saat ini saya menggunakan static_assert untuk menerapkan "Konsep" di kelas.
contoh:
Ini akan menyebabkan kesalahan waktu kompilasi jika salah satu kondisi di atas tidak terpenuhi.
sumber
Salah satu kegunaannya
static_assert
mungkin untuk memastikan bahwa struktur (yang merupakan antarmuka dengan dunia luar, seperti jaringan atau file) persis dengan ukuran yang Anda harapkan. Ini akan menangkap kasus di mana seseorang menambah atau memodifikasi anggota dari struktur tanpa menyadari konsekuensinya. Itustatic_assert
akan mengambilnya dan memperingatkan pengguna.sumber
Jika tidak ada konsep yang dapat digunakan
static_assert
untuk pemeriksaan jenis waktu kompilasi yang sederhana dan dapat dibaca, misalnya, dalam template:sumber
Ini tidak secara langsung menjawab pertanyaan asli, tetapi membuat studi yang menarik tentang bagaimana menerapkan pemeriksaan waktu kompilasi ini sebelum C ++ 11.
Bab 2 (Bagian 2.1) Desain C ++ Modern oleh Andrei Alexanderscu mengimplementasikan gagasan pernyataan waktu kompilasi seperti ini
Bandingkan makro STATIC_CHECK () dan static_assert ()
sumber
The
static_assert
dapat digunakan untuk melarang penggunaandelete
kata kunci cara ini:#define delete static_assert(0, "The keyword \"delete\" is forbidden.");
Setiap pengembang C ++ modern mungkin ingin melakukannya jika dia ingin menggunakan pengumpul sampah konservatif dengan hanya menggunakan kelas dan struct yang membebani operator new untuk memanggil fungsi yang mengalokasikan memori pada tumpukan konservatif dari pengumpul sampah konservatif yang dapat diinisialisasi dan dibuat instance-nya dengan menjalankan beberapa fungsi yang melakukan ini di awal
main
fungsi.Misalnya, setiap pengembang C ++ modern yang ingin menggunakan kolektor sampah konservatif Boehm-Demers-Weiser akan
main
menulis di awal fungsi:GC_init();
Dan di setiap
class
danstruct
membebani denganoperator new
cara ini:Dan sekarang hal
operator delete
itu tidak diperlukan lagi, karena pengumpul sampah konservatif Boehm-Demers-Weiser bertanggung jawab untuk membebaskan dan membatalkan alokasi setiap blok memori saat tidak diperlukan lagi, pengembang ingin melarangdelete
kata kunci.Salah satu caranya adalah membebani dengan
delete operator
cara ini:Tetapi ini tidak disarankan, karena pengembang C ++ modern akan tahu bahwa dia salah memanggil
delete operator
waktu berjalan, tetapi ini lebih baik untuk segera mengetahuinya pada waktu kompilasi.Jadi solusi terbaik untuk skenario ini menurut saya adalah menggunakan
static_assert
seperti yang ditunjukkan di awal jawaban ini.Tentu saja ini juga bisa dilakukan
BOOST_STATIC_ASSERT
, tapi menurut saya itustatic_assert
lebih baik dan harus lebih selalu disukai.sumber