У меня есть функция, которая принимает объект и вызывает различные функции обратного вызова в качестве его вывода.Пример:
template<typename T>
void iterateInParallel(vector<int> const& a, vector<int> const& b, T && visitor)
{
// sometimes invokes visitor.fromA(i)
// sometimes invokes visitor.fromB(i)
// sometimes invokes visitor.fromBoth(i, j)
}
(Не увлекайтесь точно тем, что делает функция, это пример и здесь не актуально.)
Теперь, когда пишем код, чтобы использовать функцию, котораяпринимает объект обратного вызова, я часто буду использовать локальную лямбду с захватом по-умолчанию по умолчанию, чтобы сохранить мой код сжатым и читабельным.
int sum = 0;
int numElems = 0;
someFunctionTakingACallback(args, [&](int x) {sum += x; numElems++; });
Это много лучше, чем старыйфункторный подход, в котором я бы определил класс для цели, которая в своих конструкторах приняла ссылки на sum
и numElems
.Как и в случае с функторным подходом, он обычно не требует затрат времени выполнения, поскольку код для обратного вызова известен при создании экземпляра функции.
Но лямбда-это только одна функция, поэтому она не работает для метода iterateInParallel
выше;Я возвращаюсь к копированию ссылок.
Итак, то, что я ищу, - это средство приблизительного уровня удобства, производительности и идиоматичности, которое у меня есть от захвата по умолчанию в lambdas.возможность вызывать несколько типов обратных вызовов.
Опции, которые я рассмотрел:
- Передача нескольких функций обратного вызова.Это не так уж плохо, и обычно это то, что я пошел.Но порядок параметров можно легко перепутать, и это действительно может привести к расширению списка аргументов.Это также менее самодокументированное, так как имена обратных вызовов нигде в пользовательском коде.
- Переписывают внутреннюю функцию так, что она вызывает один обратный вызов, с параметрами, помогающими определить, что kind обратного вызова это.Уродливый, хакерский, и не тот поступок, который мог бы сделать респектабельный программист.
- Передача структуры с целой связкой
std::function
s.У меня такое чувство, что я мог бы заставить это выглядеть хорошо , но у меня также есть ощущение, что это в конечном итоге приведет к выделению кучи и перенаправлению на вызов. - Что-то дурацкое с участием препроцессора,Небеса прощают.