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

如何为std::make_shared创建支持传参的别名?

问题:为std::make_shared创建支持参数的别名,实现ThreadSafePtr_make<int>(2)式调用

现有一个线程安全变量包装类ThreadSafeVar,希望为std::shared_ptr<ThreadSafeVar<T>>创建别名ThreadSafePtr<T>,同时为std::make_shared<ThreadSafeVar<T>>创建可接收参数的别名,实现类似ThreadSafePtr<int> a = ThreadSafePtr_make<int>(2)的调用,但原代码中的两种别名方式均无法支持参数传递。

原代码问题点:

  • ThreadSafePtr_make将std::make_shared<ThreadSafeVar<T>>赋值给变量,实际绑定的是无参版本的函数指针,传递参数会因签名不匹配报错。
  • ThreadSafePtr_make2尝试用模板函数指针,但调用时无法推导Args模板参数,导致编译失败。

解决方案:用模板函数包装std::make_shared

直接定义一个模板函数,内部调用std::make_shared<ThreadSafeVar<T>>并完美转发参数,这是最简洁且兼容所有参数场景的方案。

修改后的完整代码

#include <memory>
#include <mutex>

template<typename T>
class ThreadSafeVar
{
    T value;
    std::mutex mutex{};

public:
    template<typename... Args>
    ThreadSafeVar(Args&&... args) : value{ std::forward<Args>(args)... } {}
    ThreadSafeVar(ThreadSafeVar&) = delete;
    ThreadSafeVar(ThreadSafeVar&&) = delete;
    ThreadSafeVar& operator=(ThreadSafeVar&) = delete;
    ThreadSafeVar& operator=(ThreadSafeVar&&) = delete;

    class Lock
    {
        friend class ThreadSafeVar<T>;
        T& ref;
        std::unique_lock<std::mutex> lock;
        Lock(ThreadSafeVar* tsvar) : ref{ tsvar->value }, lock{ tsvar->mutex } {}
    public:
        T & get() const { return ref; }
    };

    Lock lock() { return Lock{ this }; }
};

template<typename T>
using ThreadSafePtr = std::shared_ptr<ThreadSafeVar<T>>;

// 核心:用模板函数包装std::make_shared,完美转发参数
template <typename T, typename... Args>
constexpr ThreadSafePtr<T> ThreadSafePtr_make(Args&&... args) {
    return std::make_shared<ThreadSafeVar<T>>(std::forward<Args>(args)...);
}

int main()
{
    ThreadSafePtr<int> a = std::make_shared<ThreadSafeVar<int>>(2);
    a->lock().get()++;
    
    // 现在所有调用均正常
    ThreadSafePtr<int> b = ThreadSafePtr_make<int>();
    ThreadSafePtr<int> c = ThreadSafePtr_make<int>(2);
    // 支持多参数构造(比如T是std::pair的情况)
    ThreadSafePtr<std::pair<int, std::string>> d = ThreadSafePtr_make<std::pair<int, std::string>>(10, "test");

    return 0;
}

方案说明

  1. 完美转发:通过std::forward<Args>(args)...保证参数的左值/右值属性不变,和直接调用std::make_shared的效率一致。
  2. 兼容所有参数场景:支持ThreadSafeVar<T>构造函数的任意参数组合,包括无参、单参、多参、甚至带默认值的参数。
  3. 编译期优化:constexpr修饰保证在编译期即可完成实例化(符合C++17及以上标准)。

内容的提问来源于stack exchange,提问作者H.v.M.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 20:35:02