Zastanawiam się, czy w czasie kompilacji można upewnić się, że metoda jest wywoływana dokładnie w jednym miejscu.
Zauważ, że jest OK, jeśli funkcja jest wywoływana więcej niż raz (np. W pętli) - ale nie powinna być wywoływana w dwóch oddzielnych pętlach.
Można to podzielić na dwie części, interesują mnie również rozwiązania obejmujące każdą część:
(a) upewnij się, że metoda jest wywoływana w co najmniej jednym miejscu
(b) upewnij się, że metoda jest wywoływana w co najwyżej jednym miejscu
Mam pełną kontrolę nad strukturą kodu i mile widziane są różne idiomy, które osiągają ten sam pomysł.
// class.h
class MyClass {
public:
void my_method();
}
Poniższe nie powinny się kompilować (nigdy nie są wywoływane)
#include "class.h"
int main() {
MyClass my_class;
}
Poniższe nie powinny się kompilować (wywoływane w więcej niż jednym miejscu)
#include "class.h"
int main() {
MyClass my_class;
my_class.my_method();
while(true) {
my_class.my_method();
}
}
Powinny się kompilować (wywoływane dokładnie w jednym miejscu):
#include "class.h"
int main() {
MyClass my_class;
while(true) {
my_class.my_method();
}
}
__COUNTER__
makra. Coś jakstatic_assert(__COUNTER__ == 0); my_class.my_method();
. Jednak licznik resetuje się w każdej jednostce tłumaczeniowej, dzięki czemu można sprawdzić, czy funkcja jest wywoływana tylko raz na jednostkę tłumaczeniową.Odpowiedzi:
Podejście Low Tech:
Ponieważ masz kontrolę nad strukturą kodu (która obejmuje system kompilacji, jak zakładam), oto rozwiązanie mało zaawansowane:
Alternatywnie:
Jeśli naprawdę, naprawdę, naprawdę chcesz to rozwiązać za pomocą C ++, możesz spróbować
Jednak liczniki czasu kompilacji to czarna magia (mówi ja i ja naprawdę lubię TMP), a wymuszanie naruszeń ODR w tym celu wydaje się podobne do voodoo (przynajmniej wymagałbyś testowego przypadku, który nie łączy się).
Ale poważnie:
Nie rób tego Cokolwiek zrobisz, funkcja owijania może zostać wypaczona prawie bez wysiłku:
MyClass::my_method()
jest wywoływany tylko w opakowaniu. Wszyscy inni nazywają otoki, które prawdopodobnie są nawet kompilowane przez kompilator.Jak sugerowali inni: może być o wiele bardziej pomocne, jeśli wyjaśnisz, co próbujesz zrobić.
źródło
Oto szorstki pomysł, który może zadziałać (za długi na komentarz - ale niekompletny na dobrą odpowiedź SO).
Możesz to osiągnąć, licząc / sprawdzając instancje szablonów.
Szablony tworzone są tylko po użyciu .
Podobnie ciała metod / funkcji szablonów nie są analizowane, kompilowane ani łączone (poza zapewnieniem poprawnej składni), jeśli nigdy nie zostaną wywołane. Oznacza to, że wszelkie instancje w ich ciałach nie są dokonywane).
Możesz być w stanie utworzyć szablon, który będzie utrzymywał pewną globalną liczbę instancji i statyczne potwierdzanie tego (lub inny mechanizm TMP do sprawdzania poprzednich instancji).
źródło
Istnieje częściowe rozwiązanie tego problemu przy użyciu preprocesora C i wbudowanego zestawu GNU:
Plik nagłówka
a.h
:Plik implementacyjny
a.cc
:To rozwiązanie jest częściowe w tym sensie, że nie uniemożliwia programowi wywołania metody rozpoczynającej się bezpośrednio od znaku podkreślenia bez użycia makra opakowania.
źródło
Użyj licznika constexpr. Istnieje implementacja w innym pytaniu
źródło