Поскольку я не знаю, как задать вопрос напрямую, я хотел бы представить проблему шаг за шагом:
Представьте себе вектор (обтекание) объектов, и вам нужно отсортировать и отфильтровать. Обычно я делал бы что-то вроде этого:
class Foo
{
Bar* bar
int CalcDistance(); // operates on bar;
std::vector<int> GetObjects(); // operates on bar;
};
std::vector<Foo*> process()
{
std::vector<Foo*> foos = GetFoosFromSomewhere();
std::vector<Foo*> potentialFoos;
auto the_filter = [&](auto foo){
return foo->CalcDistance() < MAGIC_NUMBER && !foo->GetObjects().empty();
};
std::copy_if(foos.begin(), foos.end(), potentialFoos.begin(), the_filter);
auto the_sorter = [&](auto lhs, auto rhs){ return lhs->CalcDistance() > rhs->CalcDistance(); };
std::sort(potentialFoos.begin(), potentialFoos.end(), the_sorter);
return potentialFoos;
}
К сожалению, мне не нужно фильтровать вектор Foos. Вместо этого отдельные запросы работают с графиком и возвращают несколько результатов при задании цели (вершины на графике).
Если есть три возможности добраться до цели, вы получите три расстояния и три вектора объектов соответственно.
class Foo
{
Bar* bar
std::vector<int> CalcDistance(Vertex target); // operates on bar, based on a graph;
std::vector<std::vector<int>> GetObjects(Vertex target); // operates on bar, based on a graph;
};
Мне бы хотелось иметь простой (выразительный) способ сортировки и фильтрации альтернативных путей, ведущих к одной и той же цели. То, что я могу себе представить, выглядит примерно так:
// pseudo-code
Foo foo = GetFooFromSomewhere();
std::vector<Vertex> targets = GetTargetsFromSomewhere();
auto the_filter = [](Distance d, Objects o){ return d < MAGIC_NUMBER && !o.empty() };
auto the_sorter = [](Distances d){ return d.lhs < d.rhs; }
auto alternatives = SortAndFilter(foo, targets,
filter<Distance, Objects>(the_filter),
sorter<Distance>(the_sorter));
Я уже добился определенного прогресса, используя шаблоны c variadi и выражения сгиба для разложения отдельных объектов Query (здесь Distance и Objects) лямбд ( см. http://coliru.stacked-crooked.com/a/3a095f1adcf61de4), но это (а) не завершено, (б) не так выразительно, как хотелось бы, и (c), безусловно, «переосмысление года».
Конечная цель состоит в том, чтобы скрыть сложность вызовов базовых методов для объекта обернутой панели от конечного пользователя с возможностью расширять запросы, например, по специализации шаблона.
Проблема заключается в моих чувствах о изобретении колеса, и я почти уверен, что есть несколько лучших способов сделать это (например, некоторые полезные вещи в верхней части графика наддува).
Есть идеи (улучшения)?