Skip to content

Latest commit

 

History

History
173 lines (133 loc) · 6.52 KB

fwd_delegate.md

File metadata and controls

173 lines (133 loc) · 6.52 KB

rome:: fwd_delegate

Defined in header <rome/delegate.hpp>.

template<typename Signature, typename Behavior = target_is_expected>
class fwd_delegate;  // undefined

template<typename... Args, typename Behavior>
class fwd_delegate<void(Args...), Behavior>;

template<typename Signature>
using event_delegate = fwd_delegate<Signature, target_is_optional>;

template<typename Signature>
using command_delegate = fwd_delegate<Signature, target_is_mandatory>;

Instances of class template rome::fwd_delegate can store and invoke any callable target -- functions, lambda expressions, std::function, other function objects, as well as static and non-static member functions.

The rome::fwd_delegate has identical functionality as rome::delegate, but with the restriction that data can only be forwarded. To ensure this, only function signatures with void return and arguments of immutable type are supported. E.g. the signature void(const std::string&) would work, while void(int*) or bool() would not compile.

See rome::delegate for a description of the functionality.

Template parameters

  • Args...
    The argument types of the target being called. Must be immutable.

  • Behavior
    Defines the behavior of an empty rome::fwd_delegate being called. Defaults to rome::target_is_expected.

    The behavior can be chosen by declaring the delegate with one the following types:

    • rome::target_is_expected
      A valid target is expected to be assigned before the rome::fwd_delegate is called.
      When an empty rome::fwd_delegate is being called:

    • rome::target_is_optional
      Assigning a target to the rome::fwd_delegate is optional. Calling an empty delegate returns directly without doing anything.

    • rome::target_is_mandatory
      Prevents by design that a rome::fwd_delegate can be empty. This has following consequences:

      • Default constructor is deleted. A new instance of rome::fwd_delegate can only be created by passing a target to the constructor or by using one of the factory functions create.
      • There is no possibility to drop a currently assigned target, though it can be overridden by assigning a new target.

      Note: The rome::fwd_delegate still becomes empty after a move, i.e., after auto y = std::move(x) x is empty and behaves as if Behavior was set to rome::target_is_expected.

Type aliases

  • rome::command_delegate
    This delegate was designed for event or message-driven architectures to command an action that shall happen. Because the execution of the command is mandatory, a target must be assigned during construction of the delegate and can only be overriden by another target afterwards.
    A rome::fwd_delegate with Behavior set to rome::target_is_mandatory.
  • rome::event_delegate
    This delegate was designed for event or message-driven architectures, to notify about happened events. Thus, it is optional whether someone wants to listen to the event or not.
    A rome::fwd_delegate with Behavior set to rome::target_is_optional.

Member functions

See rome::delegate

Non-member functions

See rome::delegate

Example

Model of an extremely simplified cruise control system. The four classes Engine, BrakingSystem, SpeedSensor and CruiseControl are atomic, i.e., are free from dependencies to other classes. Integration integrates all four.

See the code in examples/cruise_control.cpp.

#include <iostream>
#include <rome/delegate.hpp>

struct Engine {
    void accelerate() {
        std::cout << "engine accelerating\n";
    }
    void turnOff() {
        std::cout << "engine turned off\n";
    }
};

struct BrakingSystem {
    void turnBrakesOn() {
        std::cout << "brakes on\n";
    }
    void turnBrakesOff() {
        std::cout << "brakes off\n";
    }
};

struct SpeedSensor {
    // Assigning delegate is optional for speed sensor to work.
    rome::event_delegate<void(float)> onSpeedChanged;
};

class CruiseControl {
    float targetSpeed_ = 0.0F;

    // Assigning both delegates is required for cruise control to work.
    rome::command_delegate<void()> onAccelerateCar_;
    rome::command_delegate<void()> onSlowDownCar_;

  public:
    void updateAcceleration(const float drivingSpeed) {
        if (drivingSpeed < targetSpeed_ * 0.95F) {
            onAccelerateCar_();
        }
        else if (drivingSpeed > targetSpeed_ * 1.05F) {
            onSlowDownCar_();
        }
    }

    void setTargetSpeed(const float targetSpeed) {
        targetSpeed_ = targetSpeed;
    }

    CruiseControl(rome::command_delegate<void()>&& onAccelerateCar,
        rome::command_delegate<void()>&& onSlowDownCar)
        : onAccelerateCar_{std::move(onAccelerateCar)}, onSlowDownCar_{std::move(onSlowDownCar)} {
    }
};

struct Integration {
    SpeedSensor speedSensor;
    CruiseControl cruiseControl;
    Engine engine;
    BrakingSystem brakes;

    Integration()
        : cruiseControl{
            [this]() {
                brakes.turnBrakesOff();
                engine.accelerate();
            },
            [this]() {
                engine.turnOff();
                brakes.turnBrakesOn();
            }} {
        speedSensor.onSpeedChanged = [this](float drivingSpeed) {
            cruiseControl.updateAcceleration(drivingSpeed);
        };
    }
};

Integration integration{};

int main() {
    // Simulate IO not connected in this example
    integration.cruiseControl.setTargetSpeed(25.0F);
    integration.speedSensor.onSpeedChanged(20.0F);
    integration.speedSensor.onSpeedChanged(25.0F);
    integration.speedSensor.onSpeedChanged(30.0F);
}

Output:

brakes off
engine accelerating
engine turned off
brakes on

See also

  • rome::delegate
    The same as rome::fwd_delegate but without return and argument type restrictions.
  • std::move_only_function (C++23)
    Wraps a callable object of any type with specified function call signature.
  • std::function (C++11)
    Wraps a callable object of any copy constructible type with specified function call signature.