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

如何借助Boost::MP11循环实例化类的模板方法?

批量显式实例化MessageEndpoint模板方法(基于Boost::MP11)

问题场景

现有包含模板方法的类,需为SupportedMessages列表内所有类型预实例化subscribe及两个send_message重载:

#include <functional>
#include <boost/mp11/mp_list.hpp>

namespace messaging {
    struct MessageType1 {};
    struct MessageType2 {};
    struct MessageTypeN {};
}

using UID = int; // 示例UID定义

class MessageEndpoint
{
public:
    using SupportedMessages = boost::mp11::mp_list<messaging::MessageType1, messaging::MessageType2, messaging::MessageTypeN>;

public:
    virtual ~MessageEndpoint() = default;

public:
    template <typename MessageType>
    UID subscribe(const UID &publisher_uid, std::function<void(const MessageType &)> callback);

    template <typename MessageType>
    void send_message(const MessageType &message);
    template <typename MessageType>
    void send_message(MessageType &&message);
};

传统逐个显式实例化的方式冗长且维护成本高,需要批量处理方案。

实现方案

借助Boost::MP11的元编程工具,可遍历SupportedMessages中的每个类型,自动生成对应模板方法的显式实例化声明/定义。

方法1:头文件中声明批量显式实例化

在类声明的头文件末尾添加以下代码,用于声明所有类型的显式实例化:

#include <boost/mp11/mp_transform.hpp>

// 辅助模板:为单个类型生成所有所需的显式实例化声明
template <typename T>
struct InstantiateMessageEndpointMethods {
    // 显式实例化subscribe模板方法
    template UID MessageEndpoint::subscribe<T>(const UID&, std::function<void(const T&)>);
    // 显式实例化两个send_message重载
    template void MessageEndpoint::send_message<T>(const T&);
    template void MessageEndpoint::send_message<T>(T&&);
};

// 遍历SupportedMessages,为每个类型触发辅助模板实例化
using InstantiateAllMessageEndpoint = boost::mp11::mp_transform<
    InstantiateMessageEndpointMethods,
    MessageEndpoint::SupportedMessages
>;

方法2:在.cpp文件中实现显式实例化定义

若模板方法的实现位于.cpp文件,可添加以下代码完成批量实例化:

#include "MessageEndpoint.h"
#include <boost/mp11/mp_for_each.hpp>

// 模板方法的实际实现
template <typename MessageType>
UID MessageEndpoint::subscribe(const UID &publisher_uid, std::function<void(const MessageType &)> callback) {
    // 业务逻辑实现
    return 0;
}

template <typename MessageType>
void MessageEndpoint::send_message(const MessageType &message) {
    // 业务逻辑实现
}

template <typename MessageType>
void MessageEndpoint::send_message(MessageType &&message) {
    // 业务逻辑实现
}

// 辅助函数:触发单个类型的所有模板方法实例化
template <typename T>
void instantiate_single_type() {
    // 显式实例化定义
    template UID MessageEndpoint::subscribe<T>(const UID&, std::function<void(const T&)>);
    template void MessageEndpoint::send_message<T>(const T&);
    template void MessageEndpoint::send_message<T>(T&&);
}

// 遍历所有支持的消息类型,触发实例化
void instantiate_all_message_endpoint_methods() {
    boost::mp11::mp_for_each<MessageEndpoint::SupportedMessages>(
        [](auto /* dummy */) {
            using T = decltype(dummy);
            instantiate_single_type<T>();
        }
    );
}

// 全局初始化时触发所有实例化
static const auto trigger_instantiation = []{
    instantiate_all_message_endpoint_methods();
    return 0;
}();

说明

  • mp_transform会将SupportedMessages中的每个类型传入InstantiateMessageEndpointMethods模板,自动为每个类型生成对应显式实例化声明。
  • mp_for_each用于遍历类型列表,在全局初始化阶段触发每个类型的实例化逻辑(实际实例化发生在编译期)。
  • 此方式仅需维护SupportedMessages列表,新增类型时无需手动编写重复的显式实例化代码。

内容的提问来源于stack exchange,提问作者A.N.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 20:47:33