У меня есть простой класс property<T>
с value_changed<T>
, который вы можете connect
/disconnect
, и принимать или запрещать события при вызове value_changed<T>::emit(T)
. Подумайте о сигнале/слотах Qt на стероидах С++ 11.
Моя следующая задача - предоставить объект, подобный объекту, который состоит из под-свойств. Подумайте, например, о позиции или размере, которые состоят из нескольких значений. Я хотел бы иметь возможность обрабатывать подобъекты как property
и дополнительно получать составной сигнал, излучаемый при одновременном изменении нескольких значений. Например. делать
struct
{
property<int> x;
property<int> y;
}
position2d pos{0,0};
// ...
pos = {1,1}; // this should fire x.value_changed, y.value_changed, and pos.value_changed (once!)
Это последнее маленькое слово является ядром проблемы. Я изо всех сил пытаюсь закодировать повторно используемый composite_property
, который можно настроить с помощью имен субобъектов (позиция будет получать x
, y
, но размер получит width
/height
).
Примечание a property<struct { int x; int y; }>
не хватает: изменение x
не будет выдавать композитный сигнал value_changed
.
Лучшее, что я могу придумать, - это что-то с кучей кода шаблона для подключения/отключения подобъектов при назначении суперобъекту, который является утомительным и идет против принципа DRY.
Я открыт для волшебной магии шаблона, хотя я понимаю, что свободное присвоение переменных (x
/y
и width
/height
) сделает хотя бы некоторый код шаблона.
EDIT Для полноты, это шаблон property
, который у меня есть сейчас:
template<typename T>
class property
{
public:
using value_type = T;
using reference = std::add_lvalue_reference_t<T>;
using const_reference = std::add_lvalue_reference_t<std::add_const_t<T>>;
using rvalue_reference = std::add_rvalue_reference_t<T>;
property(const_reference value_ = {}) : value(value_) {}
operator const_reference() const { return value; }
property& operator=(const_reference& other)
{
const bool changed = value != other;
value = other;
if(changed)
value_changed.emit(value);
return *this;
}
bool operator==(const_reference other) const { return value == other; }
bool operator!=(const_reference other) const { return value != other; }
bool operator< (const_reference other) const { return value < other; }
bool operator<=(const_reference other) const { return value <= other; }
bool operator> (const_reference other) const { return value > other; }
bool operator>=(const_reference other) const { return value >= other; }
signal<value_type> value_changed;
private:
value_type value;
};
signal
немного больше задействован и доступен здесь. В принципе, connect
как Qt, за исключением того, что он возвращает объект connection_type
, такой как Boost.Signal, который можно использовать для disconnect
этого соединения.
Примечание. Я открыт для функции "изменять свойство без изменений", которая обходит сигнал, но только реализует половину того, что мне нужно.