C++ (Qt)struct Light {..private: Light * m_master; QVector<Light *> m_slaves;..public: void Link2Master( Light * master ); void UnlinkFromMaster( void ); bool HasGrandMaster( const Light * master ) const; // пресечь циклическую зависимость};
C++ (Qt)class Printable{public: virtual ~Printable() {} virtual void print() const = 0;}; template <class P>std::enable_if_t<upl::Pointer<P, const Printable>>print(const P& pointer){#if 1 // Access to the 'pointer' by the lambda. upl::access(pointer, [](auto& value) { value.print(); }, [] { std::cout << "no value" << std::endl; });#else // Similar access to the 'pointer' by the "standard" way. const auto& pointer_accessor = upl::access(pointer); if (pointer_accessor) { auto& value = *pointer_accessor; value.print(); } else { std::cout << "no value" << std::endl; }#endif} class Engine : public Printable{public: Engine() {} Engine(const std::string& model) : m_model{model} {} ... std::string model() const { return m_model; } int currentRpm() const { return m_current_rpm; } void accelerate() { m_current_rpm++; } ...private: std::string m_model; int m_current_rpm{0};}; class Car : public Printable{public: using SingleEngine = upl::unique_single<Engine>; Car(const std::string& brand, SingleEngine engine) : m_brand{brand}, m_engine{std::move(engine)} {} SingleEngine replaceEngine(SingleEngine engine) { m_engine.swap(engine); return engine; } void drive() { (*m_engine).accelerate(); } std::string brand() const { return m_brand; } ...private: std::string m_brand; SingleEngine m_engine;}; class Monitor : public Printable{public: using WeakEngine = upl::weak<const Engine>; Monitor() {} Monitor(const std::string& model, const WeakEngine& engine) : m_model{model}, m_engine{engine} {} std::string model() const { return m_model; } void setEngine(const WeakEngine& engine) { m_engine = engine; } ...private: std::string m_model; WeakEngine m_engine;}; void driveCar(upl::weak<Car> car){ using namespace std::chrono_literals; for (int i = 0; i < 20; ++i) { std::this_thread::sleep_for(40ms); upl::access(car, [](auto& car) { car.drive(); }); }} void monitorEngine(upl::weak<const Monitor> monitor){ using namespace std::chrono_literals; for (int i = 0; i < 10; ++i) { std::this_thread::sleep_for(100ms); upl::access(monitor, [](auto& monitor) { monitor.print(); }); }}...int main(){ // With the 'upl::itself' parameter, the 'upl::unique' creates the 'Engine' // in the same way as the 'std::make_unique<Engine>'. upl::unique<Engine> vaz_i4{upl::itself, "VAZ I4"}; upl::unique<Engine> zmz_i4{upl::itself, "ZMZ I4"}; upl::shared<Monitor> monitor_1{upl::itself, "ME 1", vaz_i4}; upl::unique<Monitor> monitor_2{upl::itself, "ME 2", zmz_i4}; upl::shared<Car> lada{upl::itself, "LADA", std::move(vaz_i4)}; upl::unique<Car> uaz{upl::itself, "UAZ", std::move(zmz_i4)}; std::vector<std::thread> threads; // Drive cars in separate threads. addThread(threads, [&] { driveCar(lada); }); addThread(threads, [&] { driveCar(uaz); }); // Monitor engines in separate threads. addThread(threads, [&] { monitorEngine(monitor_1); }); addThread(threads, [&] { monitorEngine(monitor_2); }); using EngineStore = upl::shared<std::vector<Car::SingleEngine>>; EngineStore engine_store{upl::itself}; (*engine_store).emplace_back(upl::itself, "VAZ V4 Turbo"); std::queue<std::function<void()>> commands; commands.emplace([ = ] // Capture the shared 'engine_store' and the 'lada' by value. { auto& store = (*engine_store); auto engine = (*lada).replaceEngine(std::move(store.back())); store.pop_back(); store.push_back(std::move(engine)); }); commands.emplace( // Move the unique 'uaz' into the command with the 'upl::unique_carrier' helper. [uaz = upl::unique_carrier{std::move(uaz)}]() mutable { auto wall = std::move(uaz); }); commands.emplace( // Capture the unique 'monitor_2' by the upl::weak. [ =, m = upl::weak<Monitor>{monitor_2}] { upl::access(m, [&](auto& m) { m.setEngine((*engine_store)[0]); }); }); // Execute commands in a separate thread. addThread(threads, [&] { execute(std::move(commands)); }); for (auto& thread:threads) thread.join(); print(lada); print(uaz); return 0;}