Estou curioso para saber se é possível garantir, em tempo de compilação, que um método seja chamado em exatamente um local.
Observe que não há problema se a função for chamada mais de uma vez (por exemplo, em um loop) - mas não deve ser chamada em dois loops separados.
Isso pode ser dividido em duas partes. Também estou interessado em soluções que abrangem qualquer parte:
(a) garantir que um método seja chamado em pelo menos um local
(b) garantir que um método seja chamado em mais de um local
Eu tenho controle total sobre a estrutura do código, e diferentes idiomas que alcançam a mesma idéia são bem-vindos.
// class.h
class MyClass {
public:
void my_method();
}
O seguinte não deve ser compilado (nunca chamado)
#include "class.h"
int main() {
MyClass my_class;
}
O seguinte não deve ser compilado (chamado em mais de um local)
#include "class.h"
int main() {
MyClass my_class;
my_class.my_method();
while(true) {
my_class.my_method();
}
}
O seguinte deve ser compilado (chamado exatamente em um local):
#include "class.h"
int main() {
MyClass my_class;
while(true) {
my_class.my_method();
}
}
__COUNTER__
macro não padrão para fazer isso. Algo comostatic_assert(__COUNTER__ == 0); my_class.my_method();
. No entanto, o contador é redefinido em cada unidade de tradução, portanto você só pode verificar se a função é chamada uma vez por unidade de tradução.Respostas:
Abordagem de baixa tecnologia:
Como você tem controle sobre a estrutura de código (que inclui o sistema de compilação, suponho), aqui está uma solução de baixa tecnologia:
Alternativamente:
Se você realmente, realmente, realmente quer resolvê-lo com C ++, pode tentar
No entanto, os contadores de tempo de compilação são magia negra (diz eu e gosto muito de TMP), e forçar violações de ODR para esse fim parece um vodu semelhante (pelo menos você exigiria um caso de teste que não vincule).
Mas seriamente:
Não faça isso. Faça o que fizer, ele pode ser pervertido sem quase nenhum esforço por uma função de wrapper:
MyClass::my_method()
é chamado apenas no wrapper. Todos os demais chamam o wrapper, que provavelmente está embutido no compilador.Como outros sugeriram: pode ser muito mais útil se você explicar o que está tentando fazer.
fonte
Aqui está uma idéia aproximada que pode funcionar (muito tempo para um comentário - mas incompleta para uma boa resposta SO).
Você pode conseguir isso contando / verificando as instâncias do modelo.
Os modelos são instanciados somente após o uso .
Da mesma forma, os corpos de método / função do modelo não são analisados, compilados ou vinculados (além de garantir a sintaxe válida) se nunca forem chamados. Isso significa que quaisquer instanciações dentro de seus corpos não são feitas).
Você pode criar um modelo que mantenha alguma contagem de instanciação global e afirmação estática sobre isso (ou algum outro mecanismo TMP para verificar instanciações passadas).
fonte
Há uma solução parcial para essa pergunta usando o pré-processador C e o assembly embutido GNU:
Arquivo de cabeçalho
a.h
:Arquivo de implementação
a.cc
:Essa solução é parcial no sentido de que não impede que o programa chame o método começando diretamente com o sublinhado sem usar a macro do wrapper.
fonte
Use um contador constexpr. Existe uma implementação em outra pergunta
fonte