You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为存储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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 04:26:01