template<typename M,
aui::invocable< M & > Getter,
aui::invocable< M &, std::invoke_result_t< Getter, M & > > Setter, typename SignalArg>
class APropertyDef< M, Getter, Setter, SignalArg >
- Warning
- This API is experimental. Experimental APIs are likely to contain bugs, might be changed or removed in the future.
- You can use this way if you are required to define custom behaviour on getter/setter. As a downside, you have to write extra boilerplate code: define property, data field, signal, getter and setter checking equality. Also, APropertyDef requires the class to derive
AObject
. Most of AView's properties are defined this way.
See property system for usage examples.
Performance considerations#
APropertyDef does not involve extra runtime overhead between assignment and getter/setter.
Declaration#
To declare a property with custom getter/setter, use APropertyDef template. APropertyDef-based property is defined by const member function as follows:
class User : public AObject {
public:
auto name() const {
return APropertyDef {
this,
&User::getName,
&User::setName,
mNameChanged,
};
}
private:
AString mName;
void setName(AString name) {
if (mName == name) {
return;
}
mName = std::move(name);
emit mNameChanged(mName);
}
const AString& getName() const { return mName; }
};
ASignal< Args... > emits
A signal declaration.
Definition ASignal.h:577
#define emit
emits the specified signal in context of this object.
Definition AObject.h:340
APropertyDef behaves like a class/struct function member:
User u;
u.name() = "Hello";
EXPECT_EQ(u.name(), "Hello");
- Note
- Properties defined with APropertyDef instead of AProperty impersonate themselves by trailing braces
()
. We can't get rid of them, as APropertyDef is defined thanks to member function. In comparison to user->name
, think of user->name()
as the same kind of property except defining custom behaviour via function, hence the braces ()
.
For the rest, APropertyDef is identical to AProperty including seamless interaction:
User u;
u.name() = "Hello";
u.name() += " world!";
EXPECT_EQ(u.name(), "Hello world!");
EXPECT_EQ(u.name()->length(),
AString(
"Hello world!").length());
Represents a Unicode character string.
Definition AString.h:38
- Note
- In order to honor getters/setters,
APropertyDef
calls getter/setter instead of using +=
on your property directly. Equivalent code will be: u.setName(u.getName() + " world!")
The implicit conversions work the same way as with AProperty:
auto doSomethingWithName = [](
const AString& name) { EXPECT_EQ(name,
"Hello"); };
User u;
u.name() = "Hello";
doSomethingWithName(u.name());
If it doesn't, simply put an asterisk:
doSomethingWithName(*u.name());
Observing changes#
All property types offer .changed
field which is a signal reporting value changes. Let's make little observer object for demonstration:
class LogObserver : public AObject {
public:
ALogger::info("LogObserver") << "Received value: " << msg;
}
};
The usage is close to AProperty
:
auto observer = _new<LogObserver>();
auto u = _new<User>();
u->name() = "Chloe";
#define AUI_SLOT(v)
Passes some variable and type of the variable separated by comma. It's convenient to use with the con...
Definition kAUI.h:88
static decltype(auto) connect(const Signal &signal, Object *object, Function &&function)
Connects signal to the slot of the specified object.
Definition AObject.h:82
Code produces the following output:
[07:58:59][][LogObserver][INFO]: Received value: Marinette
Making connection to property directly instead of .changed
:
auto observer = _new<LogObserver>();
auto u = _new<User>();
u->name() = "Chloe";
Code above produces the following output:
[07:58:59][][LogObserver][INFO]: Received value: Chloe
Subsequent changes to field would send updates as well:
Assignment operation above makes an additional line to output:
[07:58:59][][LogObserver][INFO]: Received value: Marinette
Whole program output when connecting to property directly:
[07:58:59][][LogObserver][INFO]: Received value: Chloe
[07:58:59][][LogObserver][INFO]: Received value: Marinette
- Examples
- /home/runner/work/aui/aui/aui.views/src/AUI/View/AView.h.