Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用宏选择函数参数_C++_Gcc_Macros_Arduino - Fatal编程技术网

C++ 使用宏选择函数参数

C++ 使用宏选择函数参数,c++,gcc,macros,arduino,C++,Gcc,Macros,Arduino,现在,如果我调用一个包含3个参数的函数,所有类型都是intfoo(int,int,int)像这样foo(PINS1)然后函数按照预期编译和工作(所有参数都被传递,就好像#define被替换为“5,6,7”) 但是如果我使用宏来选择引脚集,比如foo(pins(STRIP1))然后参数选择就乱了套。在这种特定情况下,错误参数列表变为“7,12,13”,对于foo(PINS(STRIP0))它变成了“4,12,13”。我看到了一种模式,但我没有专业知识来告诉和纠正编译时发生的事情。我认为,使用宏来实

现在,如果我调用一个包含3个参数的函数,所有类型都是int
foo(int,int,int)像这样
foo(PINS1)
然后函数按照预期编译和工作(所有参数都被传递,就好像#define被替换为“5,6,7”)


但是如果我使用宏来选择引脚集,比如
foo(pins(STRIP1))然后参数选择就乱了套。在这种特定情况下,错误参数列表变为“7,12,13”,对于
foo(PINS(STRIP0))它变成了“4,12,13”。我看到了一种模式,但我没有专业知识来告诉和纠正编译时发生的事情。

我认为,使用宏来实现这一点会严重损害可读性。但我会这样做:

#define STRIP0 0
#define STRIP1 1
#define STRIP2 2
#define STRIP3 3
#define  PINS0 2,3,4
#define  PINS1 5,6,7
#define  PINS2 8,9,10
#define  PINS3 11,12,13

#define PINS(STRIP) { (STRIP) == (STRIP0) ? PINS0 :\
                      (STRIP) == (STRIP1) ? PINS1 :\
                      (STRIP) == (STRIP2) ? PINS2 :PINS3}
现在,你可以这样称呼它:

#define STRIP0 0
#define STRIP1 1
#define STRIP2 2
#define STRIP3 3
#define  PINS0 2,3,4
#define  PINS1 5,6,7
#define  PINS2 8,9,10
#define  PINS3 11,12,13

#define CONCAT_HELP(A, B) A ## B

#define CONCAT(A, B) CONCAT_HELP(A, B)

#define PINS(FUNC,STRIP) FUNC(CONCAT(PINS, STRIP))

由于宏替换的工作方式,您需要两个级别的间接寻址(这是一个深入的解释)。只要
#定义CONCAT(A,B)A##B
CONCAT(PINS,STRIP0)
就会创建
PINSSTRIP0
,这在这里没有意义


为了完整性起见,如果您希望将其用于运行时值(您在问题中没有给出该值的指示),则可以使用一个助手函数模板来切换strip值:

PINS(foo, STRIP0);
模板
空心管脚(函数f,int-strip)
{
开关(带){
案例0:f(PINS0);断裂;
案例1:f(销1);断裂;
案例2:f(销2);断裂;
案例3:f(销3);断裂;
}
}

并且,如果您有C++17可用:

template<typename Func>
void pins(Func f, int strip)
{
    switch(strip){
    case 0: f(PINS0); break;
    case 1: f(PINS1); break;
    case 2: f(PINS2); break;
    case 3: f(PINS3); break;
    }
}
constexpr元组参数[]={
制作元组(PINS0),
制作元组(PINS1),
制作元组(PINS2),
制作元组(PINS3)
};
模板
空心管脚(函数f,int-strip)
{
应用(f,参数[strip]);
}


尽管在这一点上,helper函数不再是必需的。

如果使用类似于宏的
PINS
函数,您会遇到两个问题:第一个是整个表达式周围的大括号,第二个是,不是传递多个参数,而是传递一个参数,因为这样逗号就不是参数分隔符,而是逗号表达式。您应该重新考虑宏的使用,是否可以使用
inline
函数包装器?或者至少修改宏,或者将函数作为参数,并将调用放在宏“body”中?为什么不编写一个
if/else
@Someprogrammerdude?我将删除大括号并编辑问题,但它对输出没有影响。当我这样做
foo(PINS1)(如问题中所述)函数本身将3个数字作为参数,这使我相信逗号作为表达式并没有发生,而编译器认识到有3个参数,这就是为什么它继续进行。这就是我认为选择
PINS0
PINS1
的宏可以工作的原因,但事实并非如此。你建议将函数作为宏中的参数,这可能是krzaq建议的,我确实需要我的咖啡。很好的回答,但解释为什么需要中间扩展可能是相关的。OP似乎不太精通。@StoryTeller补充道。我试图实现的目标是,每个PINS0集对应于一组不同的物理pin连接,这些物理pin连接在运行时不会更改,需要作为参数传递给各个函数,因此通过这样做,我将省去更改这些连接的麻烦定义无处不在,仅此而已!我会试试你的答案,看起来应该有用@StoryTeller我不太精通,谢谢大家的帮助;-)
constexpr tuple<int,int,int> params[] = {
    make_tuple(PINS0),
    make_tuple(PINS1),
    make_tuple(PINS2),
    make_tuple(PINS3)
};

template<typename Func>
void pins(Func f, int strip)
{
    apply(f, params[strip]);
}