Saya ingin tahu apakah mungkin untuk memastikan pada waktu kompilasi bahwa suatu metode dipanggil tepat di satu tempat.
Perhatikan bahwa tidak apa-apa jika fungsi dipanggil lebih dari satu kali (misalnya dalam satu lingkaran) - tetapi tidak boleh dipanggil dalam dua loop terpisah.
Ini dapat dipecah menjadi dua bagian, saya juga tertarik pada solusi yang mencakup bagian mana pun:
(a) memastikan suatu metode dipanggil di setidaknya satu tempat
(b) memastikan suatu metode dipanggil di paling banyak satu tempat
Saya memiliki kontrol penuh atas struktur kode, dan berbagai idiom yang mencapai ide yang sama dipersilakan.
// class.h
class MyClass {
public:
void my_method();
}
Yang berikut tidak boleh dikompilasi (tidak pernah dipanggil)
#include "class.h"
int main() {
MyClass my_class;
}
Yang berikut tidak boleh dikompilasi (dipanggil di lebih dari satu tempat)
#include "class.h"
int main() {
MyClass my_class;
my_class.my_method();
while(true) {
my_class.my_method();
}
}
Yang berikut harus dikompilasi (dipanggil tepat di satu tempat):
#include "class.h"
int main() {
MyClass my_class;
while(true) {
my_class.my_method();
}
}
__COUNTER__
makro non-standar untuk melakukan ini. Sesuatu sepertistatic_assert(__COUNTER__ == 0); my_class.my_method();
. Namun, penghitung diatur ulang di setiap unit terjemahan sehingga Anda hanya dapat memeriksa bahwa fungsi tersebut dipanggil satu kali per unit terjemahan.Jawaban:
Pendekatan Teknologi Rendah:
Karena Anda memiliki kendali atas struktur kode (yang mencakup sistem build, saya asumsikan), berikut adalah solusi berteknologi rendah:
Kalau tidak:
Jika Anda benar-benar ingin menyelesaikannya dengan C ++, maka Anda bisa mencobanya
Namun, kompilasi penghitung waktu adalah ilmu hitam (kata saya, dan saya sangat suka TMP), dan memaksa pelanggaran ODR untuk tujuan ini tampak seperti voodoo yang sama (setidaknya Anda akan memerlukan uji kasus yang gagal menghubungkan).
Tapi serius:
Jangan lakukan ini. Apa pun yang Anda lakukan, itu dapat diputarbalikkan dengan hampir tanpa usaha oleh fungsi pembungkus:
MyClass::my_method()
disebut hanya di bungkusnya. Semua orang hanya memanggil pembungkus yang mungkin bahkan diuraikan oleh kompiler.Seperti yang disarankan orang lain: Mungkin akan jauh lebih bermanfaat jika Anda menjelaskan apa yang ingin Anda lakukan.
sumber
Inilah ide kasar yang mungkin berhasil (terlalu lama untuk komentar - tetapi tidak lengkap untuk jawaban SO yang baik).
Anda mungkin dapat mencapai ini dengan menghitung / memeriksa Instansi template.
Template hanya dipakai saat digunakan .
Demikian pula, metode templat / fungsi fungsi tidak diuraikan atau dikompilasi atau dihubungkan (di luar memastikan sintaks yang valid) jika mereka tidak pernah dipanggil. Ini berarti bahwa setiap instantiasi dalam tubuh mereka tidak dibuat).
Anda mungkin dapat membuat templat yang mempertahankan beberapa jumlah instantiasi global dan menyatakan statis tentang itu (atau mekanisme TMP lain untuk memeriksa instantiasi sebelumnya).
sumber
Ada solusi parsial untuk pertanyaan ini menggunakan C preprocessor dan GNU inline assembly:
File tajuk
a.h
:File implementasi
a.cc
:Solusi ini sebagian dalam arti bahwa itu tidak mencegah program untuk memanggil metode yang dimulai dengan garis bawah secara langsung tanpa menggunakan pembungkus makro.
sumber
Gunakan penghitung constexpr. Ada implementasi dalam pertanyaan lain
sumber