【问题标题】:How to store indicies of an array in preprocessor defines?如何在预处理器定义中存储数组的索引?
【发布时间】:2021-07-09 20:53:03
【问题描述】:

我正在 cpp 中创建一个 VST(虚拟仪器)程序,并且我有一个结构数组,代表我的程序中的各种参数:

const FloatParam_Properties FloatParamProps[NUM_FLOAT_PARAMS] =
{
    //Frequency
    {"BaseFreq",    "Base Freq",    0.0,    20.0,   5.0,    0.6},   //0 
    {"FreqDelta",   "Freq Delta",   -20.0,  20.0,   0.0,    0.6},   //1
    ...

    //Wave
    {"OscSelect",   "Wave form",    0.0,    3.0,    0.0,    1.0},   //9

    //Master
    {"Volume",      "Volume",       0.0,    1.0,    0.1,    0.4},   //10
};

这个数组中的每个元素都是一个结构,当我想访问这些结构时,我只是对索引进行了硬编码(例如,执行FloatParamProps[0] 来访问基本频率)。但是,我想使用 cpp 预处理器为这些硬编码的索引命名,因为这里的所有内容在编译时都是已知的,如果我也不必对这些定义进行硬编码就好了。

我想做的是这样的:

const FloatParam_Properties FloatParamProps[NUM_FLOAT_PARAMS] =
{
    //Frequency
    DEF_FLOAT_PARAM(BaseFreq,    "Base Freq",    0.0,    20.0,   5.0,    0.6),   //0 
    DEF_FLOAT_PARAM(FreqDelta,   "Freq Delta",   -20.0,  20.0,   0.0,    0.6),   //1
    ...

    //Wave
    DEF_FLOAT_PARAM(OscSelect,   "Wave form",    0.0,    3.0,    0.0,    1.0),   //9

    //Master
    DEF_FLOAT_PARAM(Volume,      "Volume",       0.0,    1.0,    0.1,    0.4),   //10
};

其中DEF_FLOAT_PARAM 是一个宏,然后它将接受第一个参数并使用__COUNTER__ 宏将其转换为预处理器定义(或者可能是 constexpr)。然后,如果我想访问第一个,我可以做FloatParamProps[BaseFreq],例如。我遇到的问题是你不能在宏中定义,所以我不能将 BaseFreq 定义为常量。

我也试过做类似的事情

#define DEF_FLOAT_PARAM(ID, Name, minVal, maxVal, defaultVal, skewFactor) P_##ID __COUNTER__ \
            {#ID, Name, minVal, maxVal, defaultVal, skewFactor}, 

这里的计划是尝试在宏之外进行定义,然后像这样手动输入:

const FloatParam_Properties FloatParamProps[NUM_FLOAT_PARAMS] =
{
    //Frequency
    #define DEF_FLOAT_PARAM(BaseFreq,    "Base Freq",    0.0,    20.0,   5.0,    0.6),   //0
    ... 

但问题在于,当宏在定义之前,预处理器不想扩展它。要是我能告诉它扩展宏就好了。

有人知道我该怎么做吗?

谢谢。

【问题讨论】:

  • 你不能在宏中 #define 一个宏,但是你可以定义一个 enum,除了支持 @987654331 之外,它几乎可以完成宏所做的所有事情@
  • @o11c 除非您不能在数组中间定义enum。所以试图让DEF_FLOAT_PARAM() 同时定义结构元素和它的索引是行不通的。为此,您需要单独的宏。

标签: c++ preprocessor


【解决方案1】:

使用x-macros:

#define PARAMS(X) \
    X(BaseFreq,    "Base Freq",    0.0,    20.0,   5.0,    0.6) \
    X(FreqDelta,   "Freq Delta",   -20.0,  20.0,   0.0,    0.6) \
    X(OscSelect,   "Wave form",    0.0,    3.0,    0.0,    1.0)

const FloatParam_Properties FloatParamProps[NUM_FLOAT_PARAMS] =
{
    #define PARAM_STRUCT(id, ...) {#id, __VA_ARGS__},
    PARAMS(PARAM_STRUCT)
    #undef PARAM_STRUCT
};

enum Params
{
    #define PARAM_ENUM(id, ...) id,
    PARAMS(PARAM_ENUM)
    #define PARAM_ENUM
    _count,
};

这将生成您已经拥有的相同数组,以及一个与数组索引匹配的常量的枚举。

【讨论】:

  • 请注意,使用 #include "params.def" 样式的 x 宏可能更具可读性。
  • @KamilCuk 字符串名称似乎与 ID 略有不同。
  • @HolyBlackCat:是的,但他的 UDT 显然有两个字段,请参阅问题中的第一个代码块。
  • 酷,试试这个:PARAMS("French Fries")。不使用宏的另一个原因。
  • @ThomasMatthews 我喜欢DRY 多于不喜欢宏。如果您滥用模板,它们也会产生不可读的错误。
猜你喜欢
  • 1970-01-01
  • 2011-01-14
  • 2020-06-20
  • 2015-02-25
  • 1970-01-01
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多