#pragma once #include "error.hh" namespace nix { template std::vector topoSort(std::set items, std::function(const T &)> getChildren, std::function makeCycleError) { std::vector sorted; std::set visited, parents; std::function dfsVisit; dfsVisit = [&](const T & path, const T * parent) { if (parents.count(path)) throw makeCycleError(path, *parent); if (!visited.insert(path).second) return; parents.insert(path); std::set references = getChildren(path); for (auto & i : references) /* Don't traverse into items that don't exist in our starting set. */ if (i != path && items.count(i)) dfsVisit(i, &path); sorted.push_back(path); parents.erase(path); }; for (auto & i : items) dfsVisit(i, nullptr); std::reverse(sorted.begin(), sorted.end()); return sorted; } }