I have multiple child classes derived of a parent class. I would like to resolve one of the static fields of one of the child classes, based on a parameter that is unique across the children through a static method of the parent.
Since C++ does not provide static initialization, in order to do this, I have to register all the children upon application startup. I do this via registerClass
.
My problem:
I am getting compile-time error:
error: no matching function for call to 'std::reference_wrapper<std::vector<vk::DescriptorSet> >::reference_wrapper()'
I cannot assign to a reference_wrapper inside a map, on the other hand, I can assign to a reference_wrapper outside of a map via std::ref()
.
What am I doing wrong here?
Code:
class Parent {
virtual ~Parent() = default;
static auto& getRegistry()
{
static std::unordered_map<unsigned int, std::reference_wrapper<std::vector<vk::DescriptorSet>>> registry;
return registry;
}
static std::reference_wrapper<std::vector<vk::DescriptorSet>> resolve_sampler_descriptor_sets_by_id(unsigned int id)
{
auto& registry = getRegistry();
auto it = registry.find(id);
if (it != registry.end())
{
return it->second;
}
throw std::runtime_error("Object ID not found in registry.");
}
static void registerClass(unsigned int id, std::vector<vk::DescriptorSet>& ds)
{
getRegistry()[id] = std::ref(ds);
}
}
class Child : public Parent
{
inline static const unsigned int TYPE = 1;
inline static std::vector<vk::DescriptorSet> sampler_descriptor_sets;
}
Registering classes:
Child::registerClass(Child::TYPE, Child::sampler_descriptor_sets);
AnotherChild::registerClass(AnotherChild::TYPE, AnotherChild::sampler_descriptor_sets);
In registerClass
, you can't use operator[]
because in case the provided key doesn't exist in the map, a default constructed reference_wrapper
should be instantiated. However, this is not possible since it makes no sense to create an object supposed to encapsulate a reference without any reference.
On the other hand, you could first test the existence of the key with find
and then insert
the new entry if needed:
if (getRegistry().find(id) == getRegistry().end())
{
getRegistry().insert ({id,std::ref(ds)});
}
or you can simply as @AhmedAEK suggested use emplace
.