如何创建满足自定义ModelConcept的boost::any_collection?
如何用boost::any_collection存储符合自定义ModelConcept的实体
问题根源
你之前的写法均不成立,原因如下:
boost::any_collection<ModelConcept>:概念并非可实例化的具体类型,any_collection要求传入能直接创建对象的类型。boost::any_collection<ModelConceptWrapper>/boost::any_collection<ModelConceptWrapper<>>:未实例化的模板不是合法的类型参数,空模板参数也无法满足Wrapper的模板约束。
boost::any_collection的核心是存储类型擦除后的统一类型,因此必须先构建一个能封装ModelConcept行为的类型擦除包装。
解决方案1:用Boost.TypeErasure自动生成类型擦除包装
Boost.TypeErasure提供工具可快速生成适配自定义概念的类型擦除类型,完美适配any_collection:
#include <boost/any_collection.hpp> #include <boost/type_erasure/any.hpp> #include <boost/type_erasure/member.hpp> #include <boost/type_erasure/builtin.hpp> // 假设Command已定义 struct Command {}; // 自定义概念 template<typename T> concept ModelConcept = requires(T model) { { model.setCommand(Command{}) } -> std::same_as<void>; }; // 声明成员函数的类型擦除接口 BOOST_TYPE_ERASURE_MEMBER((has_setCommand), setCommand, 1) // 构建可擦除的统一类型,包含核心操作、可复制、可析构属性 using AnyModel = boost::type_erasure::any< boost::mpl::vector< has_setCommand<void(Command)>, // 匹配setCommand(Command)的函数签名 boost::type_erasure::copy_constructible<>, boost::type_erasure::destructible<> > >; // 创建any_collection实例 boost::any_collection<AnyModel> entities;
解决方案2:手动实现类型擦除包装
若不想依赖Boost.TypeErasure的宏,可手动编写类型擦除包装类:
#include <boost/any_collection.hpp> #include <memory> struct Command {}; // 自定义概念 template<typename T> concept ModelConcept = requires(T model) { { model.setCommand(Command{}) } -> std::same_as<void>; }; // 手动实现类型擦除包装 class AnyModel { public: // 接受任何符合ModelConcept的类型 template<ModelConcept T> AnyModel(T obj) : impl_(std::make_unique<ModelImpl<T>>(std::move(obj))) {} // 支持复制(any_collection要求元素可复制) AnyModel(const AnyModel& other) : impl_(other.impl_->clone()) {} AnyModel& operator=(const AnyModel& other) { if (this != &other) impl_ = other.impl_->clone(); return *this; } // 支持移动语义 AnyModel(AnyModel&&) = default; AnyModel& operator=(AnyModel&&) = default; // 暴露ModelConcept要求的操作 void setCommand(Command cmd) { impl_->setCommand(std::move(cmd)); } private: // 抽象基类:定义类型擦除后的统一接口 struct ConceptImpl { virtual ~ConceptImpl() = default; virtual std::unique_ptr<ConceptImpl> clone() const = 0; virtual void setCommand(Command cmd) = 0; }; // 模板子类:封装具体类型的实现 template<ModelConcept T> struct ModelImpl : ConceptImpl { explicit ModelImpl(T obj) : obj_(std::move(obj)) {} std::unique_ptr<ConceptImpl> clone() const override { return std::make_unique<ModelImpl>(obj_); } void setCommand(Command cmd) override { obj_.setCommand(std::move(cmd)); } T obj_; }; std::unique_ptr<ConceptImpl> impl_; }; // 创建any_collection实例 boost::any_collection<AnyModel> entities;
使用示例
无论采用哪种方案,都可按如下方式向集合中添加符合ModelConcept的对象:
// 定义一个符合ModelConcept的示例类 struct MyModel { void setCommand(Command) { /* 业务逻辑实现 */ } }; // 添加对象到集合 entities.insert(MyModel{}); entities.insert(AnotherModel{}); // 只要AnotherModel符合ModelConcept即可 // 遍历集合并调用统一接口 for (auto& model : entities) { model.setCommand(Command{}); }
内容的提问来源于stack exchange,提问作者Jepessen
相关产品推荐
相关产品推荐

