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

如何创建满足自定义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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 01:27:17