I'm trying to make a class that's a handler for messaging with a certain state.
When a message is prepared, I expect to create a new state_t
struct referring to the new y
data. I want to then be able to access the new object via the same state
variable.
A minimal example with pointers would be something like this:
class Handler {
int x; // something config for the handler
struct state_t {
int *y;
state_t(int *y) : y(y) {}
};
std::optional<state_t> state;
Handler(int x) : x(x), state(std::nullopt) {}
void prepare_message(int *y) {
state = state_t(y);
}
void handle_state() {
// do something with the y e.g. send it over a socket
}
};
I was wondering if there's a good way to make this work with a reference instead of a pointer to y
. Replacing it directly wouldn't compile because copy assignment is implicitly removed. Can this be overcome in an elegant way?
As @RemyLebeau commented, you can use std::reference_wrapper
.
As you can see it does exactly what you require:
std::reference_wrapper is a class template that wraps a reference in a copyable, assignable object.
This is demonstrated below.
Note that I added a public test()
method to show that state_t
is now copyable/assignable (although the fact that prepare_message
compiles also implies that).
I also made the constructor of Handler
public in order to create it from main
.
#include <optional>
#include <iostream>
#include <functional>
class Handler {
[[maybe_unused]] int x; // something config for the handler
struct state_t {
//------vvvvvvvvvvvvvvvvvvvvvv--------
std::reference_wrapper<int> y;
state_t(int & y) : y(y) {}
};
std::optional<state_t> state;
void prepare_message(int & y) {
state = state_t(y);
}
void handle_state() {
}
public:
Handler(int x) : x(x), state(std::nullopt) {}
// Demonstration that `state_t` is now copyable:
void test() {
int x1 = 1;
int x2 = 2;
state_t s1{ x1 };
state_t s2{ x2 };
std::cout << s1.y << "\n";
s1 = s2;
std::cout << s1.y << "\n";
}
};
int main() {
Handler h{ 5 };
h.test();
}
Output:
1
2