I'm trying to implement a state store, which is basically a map of key-value pairs where the value is a std::variant
.
The following class works fine. Note that it not only prints the visited value, but also the keys:
class StateStoreTest
{
typedef std::variant<float, std::string> StateValue;
private:
std::map<int, StateValue> States;
public:
void SetValue(int key, const StateValue& value) { States[key] = value; }
void VisitAllValues()
{
for (auto& it : States)
{
auto key = it.first;
std::visit([key](auto&& value) { std::cout << key << "=" << value << "\n"; }, it.second);
}
}
};
I can use it like this and the output is as expected:
StateStoreTest sst;
sst.SetValue(1, 123.4f);
sst.SetValue(2, "Test");
sst.VisitAllValues();
Now I don't want to implement a specific visitor implementation in VisitAllValues()
but I want to be able to provide a visitor callable to the VisitAllValues()
method. In that visitor callable I want to have access to both the key and also the visited value.
So basically from a caller perspective I'd like to be able to do something like this:
sst.VisitAllValues([](auto key, auto&& value){ std::cout << key << "=" << value << "\n"; });
I guess my VisitAllValues()
method would have to look something like this:
void VisitAllValues(??? visitor)
{
for (auto& it : States)
{
auto key = it.first;
std::visit([key](auto&& value) { visitor(key, value); }, it.second);
}
}
But I couldn't figure out the details (I tried writing VisitAllValues()
as a template, but then I ran into problems on the caller side).
How can I implement my VisitAllValues()
method so it accepts a visitor which has access to both the id and the value?
Here is the full working toy example to play with.
It seems to me that as follows should works
template <typename L>
void VisitAllValues (L const & visitor)
{
for (auto& it : States)
{
auto key = it.first;
std::visit([&](auto&& value) { visitor(key, value); }, it.second);
}
}
Off Topic: maybe using std::forward
is you use forwarding references
visitor(key, std::forward<decltype(value)>(value));