Usage

Basic Usage

  • Declaring an observed object Foo with two properties named bar and baz of type double.

  • Registering a validator, executed prior to assignment, which can potentially coerce the proposed value.

  • Registering a notifier, executed after the assignement.

#include <iostream>
#include <stdexcept>
#include <string>

#include "xproperty/xobserved.hpp"

struct Foo : public xp::xobserved<Foo>
{
    XPROPERTY(double, Foo, bar);
    XPROPERTY(std::string, Foo, baz);
};

Registering an observer and a validator

Foo foo;

XOBSERVE(foo, bar, [](const Foo& f) {
    std::cout << "Observer: New value of bar: " << f.bar << std::endl;
});

XVALIDATE(foo, bar, [](Foo&, double proposal) {
    std::cout << "Validator: Proposal: " << proposal << std::endl;
    if (proposal < 0)
    {
        throw std::runtime_error("Only non-negative values are valid.");
    }
    return proposal;
});

Testing the validated and observed properties

foo.bar = 1.0;                          // Assigning a valid value
                                        // The notifier prints "Observer: New value of bar: 1"
std::cout << foo.bar << std::endl;      // Outputs 1.0

try
{
    foo.bar = -1.0;                     // Assigning an invalid value
}
catch (...)
{
    std::cout << foo.bar << std::endl;  // Still outputs 1.0
}

Shortcuts to link properties of observed objects

// Create two observed objects
Foo source, target;
source.bar = 1.0;

// Link `source.bar` and `target.bar`
XDLINK(source, bar, target, bar);

source.bar = 2.0;
std::cout << target.bar << std::endl;    // Outputs 2.0

Out-of-order initialization of properties

auto foo = Foo()
    .baz("hello, world");

std::cout << foo.baz << std::endl;       // Outputs hello, world