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

非C++17环境下,如何实现模板类B仅需单个模板参数引用模板类A?

在C++17之前实现仅用A的引用作为模板参数的模板类B

针对你的问题——在不支持C17的编译器(比如你的arm-none-eabi-gcc)上,定义一个只需要接收A的引用/指针作为单一模板参数的模板类B,我来分享几个可行的C11/C++14兼容方案:

首先明确你的场景:
你有一个依赖整数模板参数的类A:

template <int n> class A{ /* 自定义代码 */ };

目前你能用的写法需要同时传入n和A的引用,比较繁琐:

template <int n, A<n> &a> class B{ /* 自定义代码 */ };

而C17的auto非类型模板参数虽然能简化成template <auto &a> class B,但你的编译器不支持。那我们可以用以下几种方法绕开C17的限制:


方案1:用工厂函数自动推导模板参数

这是最简洁的用法,不需要用户手动指定任何模板参数,完全由编译器推导:

首先定义模板类B,保留两个模板参数(类型T和T的引用a):

template <typename T, T& a>
class B {
public:
    // 利用内部模板提取A的n值
    static constexpr int n = [](){
        struct extract_n {
            template <int k>
            static constexpr int get(A<k>) { return k; }
        };
        return extract_n::get(a);
    }();

    // 这里写你的B类逻辑,比如使用a和n
    void do_something() {
        // 示例操作,可根据需求修改
        // std::cout << "A's template parameter n = " << n << std::endl;
    }
};

然后写一个工厂函数make_B,用于自动推导模板参数:

template <int n>
B<A<n>, A<n>&> make_B(A<n>& a) {
    return B<A<n>, a>();
}

使用方式

// 定义A的实例
A<5> my_a;
// 自动推导生成B的实例,无需手动写模板参数
auto my_b = make_B(my_a);
my_b.do_something(); // 正常调用B的成员函数

这种方法的好处是用户完全不用关心模板参数的细节,用法和普通函数一样直观。


方案2:用宏简化模板参数输入

如果不想用工厂函数,也可以用宏来自动生成decltype(a)作为模板参数,避免手动输入A:

首先定义B类:

template <typename T, T& a>
class B {
    // 提取A的n值的辅助函数
    template <int k>
    static constexpr int get_n(A<k>) { return k; }
public:
    static constexpr int n = get_n(a);
    // 你的类逻辑
};

然后定义一个宏:

#define CREATE_B(a) B<decltype(a), a>

使用方式

A<7> another_a;
CREATE_B(another_a) my_b; // 等价于B<A<7>, another_a> my_b;

宏会自动推导a的类型,你只需要传入实例名即可,省去了手动写A<7>的麻烦。


方案3:用辅助模板封装类型提取

如果你希望更“模板化”的解决方案,可以写一个辅助模板来提取A的模板参数n,然后在B类中直接使用:

// 辅助模板:从A<n>类型中提取n
template <typename T>
struct A_template_parameter;

template <int n>
struct A_template_parameter<A<n>> {
    static constexpr int value = n;
};

// 定义B类
template <typename T, T& a>
class B {
public:
    static constexpr int n = A_template_parameter<T>::value;
    // 你的类逻辑
};

使用时可以结合方案1的工厂函数或者方案2的宏来简化输入,让B类内部能直接用n获取A的模板参数值。


需要注意的是,C17之前的非类型模板参数确实要求明确指定类型,所以无法完全像C17那样只写template <auto& a>,但上面的几种方法都能达到“用户只需传入A的实例,无需手动指定n”的效果,完美适配你的arm-none-eabi-gcc环境。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:25:20