|
CbmRoot
|
Let the following class be a composite of some sub-classes, which have a common interfaces:
class A { public: void Foo() const; void Bar(); // ... Some data };
class B { public: void Foo() const; void Bar(); // ... Some data };
class C { public: void Foo() const; void Bar(); // ... Some data };
// A composite class struct Composite { std::optional fA; std::optional fB; std::optional<C> fC; }
The class StructLooper allows to apply a callable to each registered variable/value: // The composite class, updated with a static constexpr looper struct Composite { std::optional fA; std::optional fB; std::optional<C> fC;
// A for-each method, which is applied to each VARIABLE. // If the variable is std::optional<T>, the argument of the visitor is treated as std::optional<T>. template<class Visitor> void ForEach(Visitor&& visitor) { kLooper.ForEachVariable(this, std::forward<Visitor>(visitor)); }
// A for-each method, which is applied to each VARIABLE. // If the variable is std::optional<T>, the argument of the visitor is treated as std::optional<T>. template<class Visitor> void ForEach(Visitor&& visitor) const { kLooper.ForEachVariable(this, std::forward<Visitor>(visitor)); }
// A for-each method, which is applied to each VALUE. // If the variable is std::optional<T>, the argument of the visitor is treated as T. The visitor is not // applied to variables, which are std::nullopt. template<class Visitor> void ForEachValue(Visitor&& visitor) { kLooper.ForEachValue(this, std::forward<Visitor>(visitor)); }
// A for-each method, which is applied to each VALUE. // If the variable is std::optional<T>, the argument of the visitor is treated as T. The visitor is not // applied to variables, which are std::nullopt. template<class Visitor> void ForEachValue(Visitor&& visitor) const { kLooper.ForEachValue(this, std::forward<Visitor>(visitor)); }
private: static constexpr auto kLooper = cbm::util::StructLooper(&Composite::fA, &Composite::fB, &Composite::fC); };
Following are examples of using the methods ForEach and ForEachValue
void CallBar(Composite& c) { // Applies a callable to components of mutable object reference c.ForEachValue([](auto&& val) { val.Bar(); }); }
void CallFoo(const Composite& c) { // Applies a callable to components of constant object reference c.ForEachValue([](const auto& val) { val.Foo(); }); }
int CountNonNullopt(const Composite& c) { // Count objects, which are not nullopt int counter{0}; c.ForEach([&counter](const auto& var) { if (var.has_value()) ++counter; }); return counter; }