如何为存储std::reference_wrapper的静态映射赋值?编译错误求解
问题描述
我有多个继承自Parent类的子类,希望通过父类的静态方法,基于子类的唯一参数解析某子类的静态成员。由于C++不支持静态初始化,需在程序启动时通过registerClass注册所有子类。当前遇到编译错误:
error: no matching function for call to 'std::reference_wrapper<std::vectorvk::DescriptorSet >::reference_wrapper()'
在map中无法为reference_wrapper赋值,但在map外可通过std::ref()赋值,请问我哪里出错了?
代码:
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; };
注册代码:
Child::registerClass(Child::TYPE, Child::sampler_descriptor_sets); AnotherChild::registerClass(AnotherChild::TYPE, AnotherChild::sampler_descriptor_sets);
问题原因与解决办法
错误根源
使用getRegistry()[id] = std::ref(ds)操作unordered_map时,operator[]的逻辑是:如果id不存在于map中,会先默认构造一个std::reference_wrapper实例作为该键的初始值,再执行赋值操作。但std::reference_wrapper没有默认构造函数——它必须绑定到一个具体对象,无法凭空创建空的引用包装,这就是编译报错的原因。
解决办法
改用emplace或insert方法直接插入键值对,跳过默认构造步骤:
static void registerClass(unsigned int id, std::vector<vk::DescriptorSet>& ds) { auto& registry = getRegistry(); // 直接构造并插入,避免默认构造 registry.emplace(id, std::ref(ds)); }
如果需要处理重复注册的场景(比如防止同一ID被多次注册),可以检查插入结果:
static void registerClass(unsigned int id, std::vector<vk::DescriptorSet>& ds) { auto& registry = getRegistry(); auto [it, inserted] = registry.emplace(id, std::ref(ds)); if (!inserted) { // 可选:抛出错误提示重复注册 throw std::runtime_error("Duplicate class ID registered."); // 或者直接覆盖原有值: // it->second = std::ref(ds); } }
另外注意原代码中类定义末尾缺少分号,这也是潜在的编译问题,需要补上。
内容的提问来源于stack exchange,提问作者Gábor DANI
相关产品推荐
相关产品推荐

