В настоящее время я генерирую код, предназначенный для компилятора C ++.Я создаю класс, который будет принимать объект посетителя, вызывать метод accept для него с несколькими объектами.Тем не менее, я хочу, чтобы у посетителя была возможность «прервать», то есть у посетителя должен быть способ указать, что он хочет прекратить остальные вызовы на прием, потому что его интерес потерян.
Я вижудва способа сделать это, и при условии, что компилятор имеет полную видимость методов диспетчерского класса и методов посетителя (так что встраивание возможно), мне интересно, какой способ компилятору проще оптимизировать.Очевидно, что разные компиляторы будут давать разные результаты, но я бы хотел, чтобы мой генератор кода генерировал код , который требует наименьшего количества сложности от компилятора для быстрого кода.
Первый способзаключается в создании метода doVisiting, который ожидает метод Accept для посетителя, указывающий, должен ли он продолжать:
template<class VisitorT>
void doVisiting(VisitorT& visitor)
{
if(visitor.accept(object1)) {
if(visitor.accept(object2)) {
if(visitor.accept(object3)) {
visitor.accept(object4);
}
}
}
}
Одним из преимуществ этого способа является то, что если любой из методов accept жестко задан для возврата false или true, яожидать, что постоянное распространение компилятора сработает, обрезает проверки if и принимает вызовы.Я думаю, что это разумное предположение, потому что постоянное распространение - это то, что должен реализовать любой оптимизирующий компилятор.
Второй способ - не обращать внимание на тип возвращаемого значения и рассчитывать на посетителя, чтобы он поддерживал внутреннее логическое выражение.указывая, хочет ли он принять остальные итерации.В верхней части метода accept он проверяет bool, чтобы решить, следует ли выполнять какую-либо обработку:
struct myvisitor
{
bool stop;
void accept(object_type1& o)
{
if(stop)
return;
// do work
}
void accept(object_type2& o)
{
if(stop)
return;
// do work
if(some_break_worthy_condition)
// if we were returning bool instead of void,
// we would have a return false here.
stop = true;
}
// .. other accept methods
};
В первом методе if находятся вне вызовов accept, а во втором - внутри них if.,Второй также обязательно включает в себя сохранение состояния.Моя интуиция заключается в том, что последний требует более сложного анализа, но, возможно, я недооцениваю компиляторы.
Само собой разумеется, что меня интересуют другие предложения, которые компиляторы будут обрабатывать еще лучше;)