Je suis curieux de savoir s'il est possible de garantir au moment de la compilation qu'une méthode est appelée exactement à un endroit.
Notez que c'est OK si la fonction est appelée plus d'une fois (par exemple dans une boucle) - mais elle ne doit pas être appelée dans deux boucles distinctes.
Cela peut être divisé en deux parties, je suis également intéressé par les solutions qui couvrent l'une ou l'autre partie:
(a) s'assurer qu'une méthode est appelée à au moins un endroit
(b) s'assurer qu'une méthode est appelée à au plus un endroit
J'ai un contrôle total sur la structure du code et les différents idiomes qui atteignent la même idée sont les bienvenus.
// class.h
class MyClass {
public:
void my_method();
}
Les éléments suivants ne doivent pas être compilés (jamais appelés)
#include "class.h"
int main() {
MyClass my_class;
}
Les éléments suivants ne doivent pas être compilés (appelés à plusieurs endroits)
#include "class.h"
int main() {
MyClass my_class;
my_class.my_method();
while(true) {
my_class.my_method();
}
}
Les éléments suivants doivent être compilés (appelés exactement à un endroit):
#include "class.h"
int main() {
MyClass my_class;
while(true) {
my_class.my_method();
}
}
__COUNTER__
macro non standard pour ce faire. Quelque chose commestatic_assert(__COUNTER__ == 0); my_class.my_method();
. Cependant, le compteur est réinitialisé dans chaque unité de traduction, vous ne pouvez donc vérifier que la fonction est appelée une fois par unité de traduction.Réponses:
Approche Low Tech:
Puisque vous contrôlez la structure du code (qui inclut le système de construction, je suppose), voici une solution à faible technologie:
Alternativement:
Si vous voulez vraiment, vraiment, vraiment le résoudre avec C ++, alors vous pouvez essayer
Cependant, les compteurs de temps de compilation sont de la magie noire (dit moi et j'aime vraiment TMP), et forcer les violations ODR à cet effet semble être un vaudou similaire (au moins, vous auriez besoin d'un cas de test qui ne parvient pas à se lier).
Mais sérieusement:
Ne fais pas ça. Quoi que vous fassiez, il peut être perverti sans effort par une fonction wrapper:
MyClass::my_method()
est appelé uniquement dans le wrapper. Tout le monde appelle simplement le wrapper qui est probablement même inséré par le compilateur.Comme d'autres l'ont suggéré: il pourrait être beaucoup plus utile d'expliquer ce que vous essayez de faire.
la source
Voici une idée approximative qui peut fonctionner (trop longue pour un commentaire - mais incomplète pour une bonne réponse SO).
Vous pourrez peut-être y parvenir en comptant / vérifiant les instanciations du modèle.
Les modèles sont instanciés uniquement lors de leur utilisation .
De même, les corps de méthode / fonction de modèle ne sont pas analysés ni compilés ou liés (au-delà de la garantie d'une syntaxe valide) s'ils ne sont jamais appelés. Cela signifie qu'aucune instanciation au sein de leur corps n'est effectuée).
Vous pourrez peut-être créer un modèle qui conserve un certain nombre d'instanciations globales et une assertion statique sur celui-ci (ou un autre mécanisme TMP pour vérifier les instanciations passées).
la source
Il existe une solution partielle à cette question en utilisant le préprocesseur C et l'assemblage en ligne GNU:
Fichier d'en-tête
a.h
:Fichier d'implémentation
a.cc
:Cette solution est partielle dans le sens où elle n'empêche pas le programme d'appeler directement la méthode commençant par le trait de soulignement sans utiliser la macro wrapper.
la source
Utilisez un compteur constexpr. Il y a une implémentation dans une autre question
la source