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

C++如何实现向同一FIFO类构造函数传入不同自定义struct

错误原因说明
  • 第一个报错:std::array的第二个模板参数要求是编译期可确定的常量,你把运行时传入的depth作为参数,编译器无法在编译阶段确定大小,因此报错。
  • 第二个报错:struct1是类型名称,不是可传递的变量/值,普通构造函数只能接收值参数,不能直接接收类型作为入参。
解决方案

你需要用C++类模板实现FIFO,模板可以接收元素类型、队列深度作为模板参数,完全满足你不同实例用不同结构体、FIFO不感知具体结构的需求。
嵌入式场景优先用静态内存分配的实现,避免堆内存碎片化,代码如下:

#include <array>
#include <cstdint>
// C++17及以上支持std::optional,嵌入式编译器一般都兼容,返回空可选值表示队列空/满
#include <optional>

template<typename T, uint32_t DEPTH>
class FIFO {
private:
    std::array<T, DEPTH> buffer;
    uint32_t head = 0;
    uint32_t tail = 0;
    uint32_t count = 0;
public:
    FIFO() = default;

    // 入队,成功返回true,队列满返回false
    bool enqueue(const T& item) {
        if (isFull()) return false;
        buffer[tail] = item;
        tail = (tail + 1) % DEPTH;
        count++;
        return true;
    }

    // 出队,队列空返回std::nullopt,否则返回元素
    std::optional<T> dequeue() {
        if (isEmpty()) return std::nullopt;
        T item = buffer[head];
        head = (head + 1) % DEPTH;
        count--;
        return item;
    }

    bool isFull() const { return count == DEPTH; }
    bool isEmpty() const { return count == 0; }
    uint32_t size() const { return count; }
    uint32_t capacity() const { return DEPTH; }
};

// 自定义结构体
struct struct1 {
    double s1Var1;
    uint32_t s1Var2;
};

struct struct2 {
    bool s2Var1;
};

实例化方式:

// 元素为struct1,深度16的FIFO
FIFO<struct1, 16> fifo1;
// 元素为struct2,深度8的FIFO
FIFO<struct2, 8> fifo2;

如果你的嵌入式环境不支持C++17的std::optional,可以把出队接口改成返回bool,参数用引用接收出队元素:

bool dequeue(T& out_item) {
    if (isEmpty()) return false;
    out_item = buffer[head];
    head = (head + 1) % DEPTH;
    count--;
    return true;
}

调用方式:

struct1 item;
if(fifo1.dequeue(item)) {
    // 出队成功,处理item
}
嵌入式场景适配优化建议
  • 中断/DMA操作场景下,入队出队操作需要加临界区保护,比如操作前关对应外设的中断,操作完成后再开,避免队列计数、指针出现并发错误。
  • 如果需要运行时动态指定队列深度,可以把模板实现改成普通类,内部用std::vector<T>作为缓存,构造函数传入深度参数初始化vector大小即可,注意只有嵌入式环境允许用堆内存时才可以这么做。
需补充学习的知识点
  • C++类模板的基本使用,模板类型参数、非类型参数的区别
  • 嵌入式C++静态内存、动态内存的适用场景和注意事项
  • 中断安全队列的实现逻辑
设计思路评价

你当前的分层设计非常合理,UART驱动只负责队列的读写操作,不感知上层业务结构体的定义,完全符合单一职责原则,方便后续新增外设时不需要修改底层UART驱动代码,可扩展性很好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 20:36:02