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

如何在C++中实现带参数传递的编译时游戏引擎插件系统?

编译时插件系统支持多参数构造的实现方案

现有游戏引擎编译时插件系统仅支持向插件传递EngineT&类型参数,需扩展为支持每个插件携带自定义额外参数,通过tuple转发参数至对应插件的构造函数。

核心思路

通过辅助函数转发参数+C++17 std::apply简化元组展开,实现将engine引用与插件自定义参数一起传递给插件构造函数,同时保留原有无额外参数的兼容逻辑。

修改后的完整代码

#include <tuple>
#include <string>
#include <utility> // 用于std::apply、std::forward

namespace engine
{
    struct base_plugin
    {
        template<typename EngineT>
        base_plugin(EngineT& engine) {}
        
        ~base_plugin() = default;
    };

    // 辅助函数:将engine引用与元组参数转发给插件构造函数
    template<typename PluginT, typename EngineT, typename Tuple>
    PluginT construct_plugin(EngineT& engine, Tuple&& args_tuple)
    {
        return std::apply(
            [&engine](auto&&... args) {
                return PluginT(engine, std::forward<decltype(args)>(args)...);
            },
            std::forward<Tuple>(args_tuple)
        );
    }

    // 重载:无额外参数时直接用engine引用构造插件
    template<typename PluginT, typename EngineT>
    PluginT construct_plugin(EngineT& engine)
    {
        return PluginT(engine);
    }

    template<typename... PluginTs>
    struct engine
    {
        std::tuple<PluginTs...> plugins;

        // 默认构造:兼容原有逻辑,所有插件仅接收engine引用
        engine() : plugins(construct_plugin<PluginTs>(*this)...) {}

        // 模板构造:接受每个插件对应的额外参数元组
        template<typename... ArgsTuples>
        explicit engine(ArgsTuples&&... args_tuples)
            : plugins(construct_plugin<PluginTs>(*this, std::forward<ArgsTuples>(args_tuples))...)
        {}
    };
}

// 示例:带额外参数的插件
struct plugin_with_int
{
    template<typename EngineT>
    plugin_with_int(EngineT& engine, int config_value) {}
};

struct plugin_with_string
{
    template<typename EngineT>
    plugin_with_string(EngineT& engine, const std::string& plugin_name) {}
};

int main()
{
    // 原有用法:无需额外参数
    engine::engine<engine::base_plugin> basic_engine;

    // 新用法:为不同插件传递自定义参数
    engine::engine<engine::base_plugin, plugin_with_int, plugin_with_string> extended_engine(
        std::tuple<>(),          // base_plugin无额外参数,传空元组
        std::make_tuple(42),     // plugin_with_int接收int参数
        std::make_tuple("Audio") // plugin_with_string接收字符串参数
    );

    return 0;
}

关键细节说明

  • 辅助函数construct_plugin:利用std::apply将元组中的参数逐个展开,配合lambda捕获engine引用,将两者一起传递给插件的构造函数,完美转发参数的左值/右值属性。
  • 双构造函数设计:默认构造函数兼容原有代码,模板构造函数支持自定义参数,确保向后兼容。
  • 参数对应关系:构造函数的参数元组数量必须与模板参数中插件的数量完全匹配,无额外参数的插件传递std::tuple<>即可。

C++20+简化版

如果使用C++20及以上,可以直接用std::make_from_tuple结合折叠表达式进一步简化,去掉辅助函数:

template<typename... PluginTs>
struct engine
{
    std::tuple<PluginTs...> plugins;

    engine() : plugins(PluginTs(*this)...) {}

    template<typename... ArgsTuples>
    explicit engine(ArgsTuples&&... args_tuples)
        : plugins(
            std::make_from_tuple<PluginTs>(
                std::tuple_cat(std::forward_as_tuple(*this), std::forward<ArgsTuples>(args_tuples))
            )...
        )
    {}
};

这里通过std::tuple_cat将engine引用的tuple与插件参数tuple合并,再用std::make_from_tuple直接构造插件实例,代码更紧凑。

内容的提问来源于stack exchange,提问作者Alexandre Deus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 07:07:14