#pragma once #include #include #include namespace erebos { using std::nullopt; using std::optional; using std::vector; template struct Mergeable { }; template<> struct Mergeable>> { using Component = Object; static vector> components(const vector> & x) { return x; } static vector> merge(const vector> & x) { return x; } }; vector> findPropertyObjects(const vector> & leaves, const string & prop); template optional::Component>> findPropertyComponent(const vector::Component>> & components, const string & prop) { vector> leaves; leaves.reserve(components.size()); for (const auto & c : components) leaves.push_back(Stored::load(c.ref())); auto candidates = findPropertyObjects(leaves, prop); if (!candidates.empty()) return Stored::Component>::load(candidates[0].ref()); return nullopt; } template optional::Component>> findPropertyComponent(const T & x, const string & prop) { return findPropertyComponent(x.components(), prop); } template vector::Component>> findPropertyComponents(const vector::Component>> & components, const string & prop) { vector> leaves; leaves.reserve(components.size()); for (const auto & c : components) leaves.push_back(Stored::load(c.ref())); auto candidates = findPropertyObjects(leaves, prop); vector::Component>> result; result.reserve(candidates.size()); for (const auto & obj : candidates) result.push_back(Stored::Component>::load(obj.ref())); return result; } template vector::Component>> findPropertyComponents(const T & x, const string & prop) { return findPropertyComponents(x.components(), prop); } }