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

如何存储C++中编译期已知、大小固定的小型层级静态常量数据?

C++ 编译期静态多维常量数据集最优实现方案

针对编译期已知、无需实例化、支持层级与动态查找的静态多维常量存储需求,C++11及以上版本最优实现方案如下:

方案核心思路

放弃运行时容器(如unordered_map),完全使用编译期常量语法实现,零运行时开销,完全匹配全部需求点。

完整实现代码(仅需头文件即可使用)

#pragma once
#include <array>
#include <cstdint>
#include <string_view>

// 用命名空间封装所有常量,避免全局命名污染
namespace MidiEventTypes {

// 1. 定义每个事件的通用属性结构体,可任意扩展字段
struct EventAttr {
    std::uint8_t event_value; // 事件对应的数值
    std::uint8_t required_bytes; // 需要读取的字节数
    std::string_view event_name; // 示例扩展字段:事件名
    // 可按需添加更多属性,比如事件描述、处理函数指针等
};

// 2. 定义所有事件的数值常量,仅需定义一次
inline constexpr std::uint8_t NOTE_OFF = 8;
inline constexpr std::uint8_t NOTE_ON = 9;
inline constexpr std::uint8_t KEY_AFTERTOUCH = 10;
inline constexpr std::uint8_t CONTROL_CHANGE = 11;
inline constexpr std::uint8_t PROGRAM_CHANGE = 12;
inline constexpr std::uint8_t CHANNEL_AFTERTOUCH = 13;
inline constexpr std::uint8_t PITCH_WHEEL_CHANGE = 14;

// 3. 编译期映射表,所有数据编译时确定,运行时只读,无多副本
inline constexpr std::array<EventAttr, 7> EVENT_META = {{
    {NOTE_OFF, 2, "NOTE_OFF"},
    {NOTE_ON, 2, "NOTE_ON"},
    {KEY_AFTERTOUCH, 2, "KEY_AFTERTOUCH"},
    {CONTROL_CHANGE, 2, "CONTROL_CHANGE"},
    {PROGRAM_CHANGE, 1, "PROGRAM_CHANGE"},
    {CHANNEL_AFTERTOUCH, 1, "CHANNEL_AFTERTOUCH"},
    {PITCH_WHEEL_CHANGE, 2, "PITCH_WHEEL_CHANGE"}
}};

// 4. 编译期查找函数,支持常量和变量查询
constexpr EventAttr get_event_attr(std::uint8_t event_val) {
    for (const auto& meta : EVENT_META) {
        if (meta.event_value == event_val) {
            return meta;
        }
    }
    // 异常分支可按需处理,C++23可用std::unreachable()触发编译错误
    return {0, 0, "UNKNOWN_EVENT"};
}

// 5. 快捷查询函数,直接返回需要的字节数
constexpr std::uint8_t GetRequiredBytesByEventType(std::uint8_t event_val) {
    return get_event_attr(event_val).required_bytes;
}

// 可选:实现类似MidiEventTypes::NOTE_OFF::NUM_BYTES的层级访问语法
namespace _impl {
    template<std::uint8_t Val>
    inline constexpr EventAttr cached_attr = get_event_attr(Val);
}
inline constexpr auto NOTE_OFF_META = _impl::cached_attr<NOTE_OFF>;
inline constexpr auto NOTE_ON_META = _impl::cached_attr<NOTE_ON>;
// 其他事件的元数据可按同样方式定义,也可用宏批量生成避免重复代码
}

用法示例

1. 基础常量比较

std::uint8_t test_val = 8;
if (test_val == MidiEventTypes::NOTE_OFF) {
    // 业务逻辑
}

2. 静态层级访问属性

std::cout << "NOTE_OFF事件需要读取的字节数:" << MidiEventTypes::NOTE_OFF_META.required_bytes << std::endl;

3. 按运行时变量动态查询

std::uint8_t test_val = 8;
std::uint8_t bytes_needed = MidiEventTypes::GetRequiredBytesByEventType(test_val);
// 也可以直接获取完整属性
auto event_meta = MidiEventTypes::get_event_attr(test_val);
std::cout << "事件名:" << event_meta.event_name << ",需要字节数:" << event_meta.required_bytes << std::endl;

4. 编译期求值(零运行时开销)

// 编译阶段就计算出字节数,运行时直接作为常量使用
constexpr std::uint8_t note_on_bytes = MidiEventTypes::GetRequiredBytesByEventType(MidiEventTypes::NOTE_ON);

方案优势

完全匹配全部需求:

  • 所有数据编译期确定,永不修改,无运行时初始化开销
  • 仅需引入头文件即可使用,全局只有一份数据副本,无冗余
  • 事件数值仅定义一次,所有引用都用常量名,修改只需改一处,不会出现不同步问题
  • 支持扩展任意多的属性,只需修改EventAttr结构体即可
  • 同时支持静态常量访问和运行时变量查找,性能远高于运行时哈希表
  • 类型安全,无需强制类型转换

可选C++20极简层级语法实现

如果编译环境支持C++20,想要完全匹配MidiEventTypes::NOTE_OFF::NUM_BYTES的伪代码写法,可以用嵌套常量结构体实现:

namespace MidiEventTypes {
    // 每个事件对应一个嵌套结构体,直接定义所有属性
    struct NOTE_OFF {
        static constexpr std::uint8_t VALUE = 8;
        static constexpr std::uint8_t NUM_BYTES = 2;
        static constexpr std::string_view NAME = "NOTE_OFF";
    };
    struct NOTE_ON {
        static constexpr std::uint8_t VALUE = 9;
        static constexpr std::uint8_t NUM_BYTES = 2;
        static constexpr std::string_view NAME = "NOTE_ON";
    };
    // 其他事件同理定义

    // 仍可保留动态查找功能,用编译期数组映射即可
    inline constexpr std::array<std::uint8_t, 256> BYTES_LOOKUP = [](){
        std::array<std::uint8_t, 256> arr{};
        arr[NOTE_OFF::VALUE] = NOTE_OFF::NUM_BYTES;
        arr[NOTE_ON::VALUE] = NOTE_ON::NUM_BYTES;
        // 其他事件赋值
        return arr;
    }();

    constexpr std::uint8_t GetRequiredBytesByEventType(std::uint8_t val) {
        return BYTES_LOOKUP[val];
    }
}

使用时完全符合伪代码要求:

if (test_val == MidiEventTypes::NOTE_OFF::VALUE) {
    std::cout << MidiEventTypes::NOTE_OFF::NUM_BYTES << std::endl;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 15:27:03