如何借助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.
相关产品推荐
相关产品推荐

