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

如何用C++变参模板替换模板参数列表并创建对应智能指针?

变参模板类Foo的改造实现

1. 声明存储TB类型智能指针的容器

由于每个TB类型各不相同,无法用单一类型的std::vector存储,最适配的容器是std::tuple——它天然支持容纳不同类型的元素。直接将std::unique_ptr<TB>作为tuple的元素类型,声明如下:

template <typename TA, typename... TB>
class Foo {
private:
    std::tuple<std::unique_ptr<TB>...> m_tb_ptrs;
    std::unique_ptr<TA> m_ta_ptr; // 原有的TA类型成员
};

如果需要限制TB的数量最多为6个,可在类内添加静态断言做校验:

static_assert(sizeof...(TB) <= 6, "最多支持6个TB类型参数");

2. 在initialise方法中实例化智能指针

已知所有TB的构造函数签名一致,假设构造函数接受的参数类型为Args...,我们可以借助C++17的折叠表达式,逐个初始化tuple中的每个unique_ptr:

template <typename... Args>
void initialise(Args&&... args) {
    // 先初始化TA的智能指针(假设TA构造函数也支持相同参数)
    m_ta_ptr = std::make_unique<TA>(std::forward<Args>(args)...);
    
    // 遍历tuple元素,逐个构造TB对象并赋值给unique_ptr
    std::apply([&](auto&&... ptrs) {
        ((ptrs = std::make_unique<std::remove_pointer_t<decltype(ptrs)>>(std::forward<Args>(args)...)), ...);
    }, m_tb_ptrs);
}

这里用std::apply解包tuple的所有元素,再通过折叠表达式依次完成每个unique_ptr的赋值。std::remove_pointer_t<decltype(ptrs)>用于获取unique_ptr指向的原始TB类型。

3. 在execute方法中调用每个智能指针的execute方法

同样利用std::apply和折叠表达式,遍历tuple中的每个智能指针并调用其execute方法:

void execute() {
    // 先调用TA对象的execute(如果业务需要)
    m_ta_ptr->execute();
    
    // 依次调用所有TB对象的execute
    std::apply([](auto&&... ptrs) {
        (ptrs->execute(), ...);
    }, m_tb_ptrs);
}

折叠表达式中的逗号运算符会按顺序执行每个ptrs->execute()调用,确保所有TB对象的方法都被触发。

完整示例代码

#include <tuple>
#include <memory>

template <typename TA, typename... TB>
class Foo {
private:
    std::tuple<std::unique_ptr<TB>...> m_tb_ptrs;
    std::unique_ptr<TA> m_ta_ptr;
    static_assert(sizeof...(TB) <= 6, "最多支持6个TB类型参数");

public:
    template <typename... Args>
    void initialise(Args&&... args) {
        m_ta_ptr = std::make_unique<TA>(std::forward<Args>(args)...);
        std::apply([&](auto&&... ptrs) {
            ((ptrs = std::make_unique<std::remove_pointer_t<decltype(ptrs)>>(std::forward<Args>(args)...)), ...);
        }, m_tb_ptrs);
    }

    void execute() {
        m_ta_ptr->execute();
        std::apply([](auto&&... ptrs) {
            (ptrs->execute(), ...);
        }, m_tb_ptrs);
    }
};

// 测试用例类
class A {
public:
    A(int x) : m_val(x) {}
    void execute() { /* 自定义逻辑 */ }
private:
    int m_val;
};

class B1 {
public:
    B1(int x) : m_val(x) {}
    void execute() { /* 自定义逻辑 */ }
private:
    int m_val;
};

// 使用示例
int main() {
    Foo<A, B1> foo;
    foo.initialise(42);
    foo.execute();
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 06:35:19