Мне любопытно, можно ли гарантировать, что во время компиляции метод вызывается ровно в одном месте.
Обратите внимание, что все в порядке, если функция вызывается более одного раза (например, в цикле), но ее не следует вызывать в двух отдельных циклах.
Это может быть разбито на две части, меня также интересуют решения, которые охватывают любую часть:
(а) убедиться, что метод вызывается хотя бы в одном месте
(б) убедиться, что метод вызывается не более чем в одном месте
У меня есть полный контроль над структурой кода, и приветствуются различные идиомы, которые достигают той же идеи.
// class.h
class MyClass {
public:
void my_method();
}
Следующее не должно компилироваться (никогда не вызывается)
#include "class.h"
int main() {
MyClass my_class;
}
Следующее не должно компилироваться (вызывается более чем в одном месте)
#include "class.h"
int main() {
MyClass my_class;
my_class.my_method();
while(true) {
my_class.my_method();
}
}
Следующее должно скомпилироваться (вызывается ровно в одном месте):
#include "class.h"
int main() {
MyClass my_class;
while(true) {
my_class.my_method();
}
}
__COUNTER__
макрос для этого. Нечто подобноеstatic_assert(__COUNTER__ == 0); my_class.my_method();
. Однако счетчик сбрасывается в каждой единице перевода, поэтому вы можете проверить, что функция вызывается только один раз для каждой единицы перевода.Ответы:
Низкий технический подход:
Так как у вас есть контроль над структурой кода (которая включает в себя систему сборки, я полагаю), вот низкотехнологичное решение:
В качестве альтернативы:
Если вы действительно очень хотите решить эту проблему с помощью C ++, тогда вы можете попробовать
Однако счетчики времени компиляции - чёрная магия (говорит я, и мне действительно нравится TMP), и принудительное использование ODR-нарушений для этой цели кажется похожим на voodoo (по крайней мере, вам потребуется тестовый пример, который не может соединиться).
Но серьезно:
Не делай этого. Что бы вы ни делали, это может быть практически без усилий извращено функцией-оберткой:
MyClass::my_method()
вызывается только в обёртке. Все остальные просто вызывают обертку, которая, вероятно, даже встроена компилятором.Как и предполагали другие: было бы гораздо полезнее, если бы вы объяснили, что вы пытаетесь сделать.
источник
Вот грубая идея, которая может сработать (слишком долго для комментария - но неполно для хорошего ответа SO).
Вы можете достичь этого, посчитав / проверив экземпляры шаблона.
Шаблоны создаются только при использовании .
Точно так же тела метода / функции шаблона не анализируются, не компилируются и не связываются (за исключением обеспечения допустимого синтаксиса), если они никогда не вызываются. Это означает, что никаких инстанциаций внутри их тел не производится).
Возможно, вам удастся создать шаблон, который будет поддерживать некоторое глобальное количество экземпляров и статическое утверждение для этого (или какой-то другой механизм TMP для проверки прошлых экземпляров).
источник
Существует частичное решение этого вопроса с использованием препроцессора C и встроенной сборки GNU:
Заголовочный файл
a.h
:Файл реализации
a.cc
:Это решение является частичным в том смысле, что оно не мешает программе вызывать метод, начинающийся непосредственно с подчеркивания, без использования макроса-оболочки.
источник
Используйте счетчик constexpr. Есть реализация в другом вопросе
источник