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

如何编写适配std::shared_ptr与std::unique_ptr的模板化工厂函数

复用智能指针工厂函数的模板化实现

问题场景

我经常编写一对功能高度重复的工厂函数,分别返回std::unique_ptr和std::shared_ptr:

std::unique_ptr<AbstractType> createUnique(IDType id);
std::shared_ptr<AbstractType> createShared(IDType id);

两者的核心逻辑完全一致,仅在创建实例的函数(std::make_unique/std::make_shared)和返回的智能指针类型上有区别:
createUnique实现示例:

switch (id)
{
case kID1:
    return std::make_unique<Type1>();
// 其他类型分支...
}

createShared实现示例:

switch (id)
{
case kID1:
    return std::make_shared<Type1>();
// 其他类型分支...
}

这种重复不仅增加维护成本,也不符合DRY原则。我希望实现一个通用模板函数,能同时适配两种智能指针类型,避免代码重复,同时保留直接调用对应创建函数的效率(不通过智能指针间的转换实现)。

解决方案

方案1:类型特征绑定指针与创建逻辑

通过定义类型特征模板,将智能指针类型与其对应的创建函数绑定,用户只需指定指针类型即可调用通用工厂:

首先定义类型特征:

#include <memory>

template <typename PTR>
struct creator_trait;

// 为std::unique_ptr特化特征
template <typename T>
struct creator_trait<std::unique_ptr<T>> {
    template <typename Derived>
    static std::unique_ptr<T> make() {
        return std::make_unique<Derived>();
    }
};

// 为std::shared_ptr特化特征
template <typename T>
struct creator_trait<std::shared_ptr<T>> {
    template <typename Derived>
    static std::shared_ptr<T> make() {
        return std::make_shared<Derived>();
    }
};

然后实现通用模板工厂函数:

template <typename PTR>
PTR create(IDType id) {
    using trait = creator_trait<PTR>;
    switch (id) {
        case kID1:
            return trait::template make<Type1>();
        case kID2:
            return trait::template make<Type2>();
        // 扩展更多类型分支...
        default:
            return nullptr; // 或抛出异常处理非法ID
    }
}

使用方式:

auto unique_inst = create<std::unique_ptr<AbstractType>>(kID1);
auto shared_inst = create<std::shared_ptr<AbstractType>>(kID2);

方案2:传递创建器对象(灵活适配自定义逻辑)

如果需要支持自定义创建逻辑(比如带参数的构造、自定义内存分配),可以将创建逻辑封装为函数对象,作为参数传入通用工厂:

首先定义创建器:

struct MakeUniqueCreator {
    template <typename Derived>
    std::unique_ptr<AbstractType> operator()() {
        return std::make_unique<Derived>();
    }
};

struct MakeSharedCreator {
    template <typename Derived>
    std::shared_ptr<AbstractType> operator()() {
        return std::make_shared<Derived>();
    }
};

然后实现通用工厂:

template <typename PTR, typename Creator>
PTR create(IDType id, Creator creator) {
    switch (id) {
        case kID1:
            return creator.template operator()<Type1>();
        case kID2:
            return creator.template operator()<Type2>();
        // 扩展更多分支...
        default:
            return nullptr;
    }
}

使用方式:

auto unique_inst = create<std::unique_ptr<AbstractType>>(kID1, MakeUniqueCreator{});
auto shared_inst = create<std::shared_ptr<AbstractType>>(kID2, MakeSharedCreator{});

方案3:C++20 概念+编译期分支简化实现

如果使用C++20及以上版本,可以利用std::smart_pointer概念约束输入类型,并通过if constexpr在编译期选择对应的创建函数,无需额外类型特征:

#include <memory>
#include <concepts>

template <std::smart_pointer PTR>
PTR create(IDType id) {
    using ElementType = typename PTR::element_type;
    switch (id) {
        case kID1:
            if constexpr (std::same_as<PTR, std::unique_ptr<ElementType>>) {
                return std::make_unique<Type1>();
            } else if constexpr (std::same_as<PTR, std::shared_ptr<ElementType>>) {
                return std::make_shared<Type1>();
            }
        case kID2:
            if constexpr (std::same_as<PTR, std::unique_ptr<ElementType>>) {
                return std::make_unique<Type2>();
            } else if constexpr (std::same_as<PTR, std::shared_ptr<ElementType>>) {
                return std::make_shared<Type2>();
            }
        // 扩展更多分支...
        default:
            return nullptr;
    }
}

使用方式与方案1一致,直接指定智能指针类型即可。

内容的提问来源于stack exchange,提问作者Patrick Wright

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:02:51