so I'm trying to design a class Observed<T>
, which stores a T
and bool
, with the boolean value indicating whether the T
member variable has been updated since it was last set. To demonstrate, my initial implementation was something like
template <std::copyable T>
class Observed
{
public:
Observed()
: m_data{}, m_updated{false} {};
Observed(const T &data)
: m_data{data}, m_updated{true} {};
// .. move, copy, assignment ctors
// setting the data leaves it 'updated'
template <typename U>
requires(std::same_as<T, U>)
auto write(U &&value) -> void
{
m_data = std::forward<U>(value);
m_updated = true;
}
// to test if it has since been modified (i.e. written without reading)
auto modified() -> bool
{
return m_updated;
}
// reading the value means it has no longer been updated
auto value() -> T &
{
m_updated = false;
return m_data;
}
private:
T m_data;
bool m_updated;
};
However, the problem became that for an example Observed<std::vector<int>> v
, if I needed to add an element to the vector i'd call v.value().push_back(...)
, which would surpass the write()
function, and subsequently m_updated
would not be set correctly.
My slightly janky approach was to therefore introduce a call()
function as follows:
template <std::copyable T>
class Observed
{
public:
// ctors
Observed()
: m_data{}, m_updated{false} {};
Observed(const T &data)
: m_data{data}, m_updated{true} {};
// the new 'call' function
template<typename Func, typename... Ts>
auto call(Func&& func, Ts... args) -> std::invoke_result_t<Func, Ts...>
{
m_updated = true;
return std::invoke(func, m_data, args...);
}
// .. rest of class
private:
T m_data;
bool m_updated;
};
so that you'd be able to write v.call(&std::vector<int>::push_back, 1)
.
However, doing so doesn't exactly work, and debugging it is a bit of a nightmare. I just wondered whether anyone could give it a look over and help me get the correct functionality. I hope my code above has shown enough of my intent with the class.
I'm also a little unclear on how you would form the function pointer to std::vector<T>::push_back
given it takes an allocator as a second template argument.
Thanks.