首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我们能否实现一个max或min宏,它可以使用变量参数(两个以上的参数)

我们能否实现一个max或min宏,它可以使用变量参数(两个以上的参数)
EN

Stack Overflow用户
提问于 2014-04-01 01:42:05
回答 4查看 2.4K关注 0票数 5

我想实现一个新的max/min宏,它可以接受两个以上的参数,例如:

代码语言:javascript
复制
#define max( ... ) ...

然后,我可以这样用它:

代码语言:javascript
复制
max( p0, p1, p2, p3 )
max( 2, 4, 100 )
max( 1,2,3,4,5,6,7 ) -> 7

如果这个宏能帮助我们实现那个宏呢?

代码语言:javascript
复制
#define PP_EXPAND(X) X
#define PP_ARG_COUNT(...) PP_EXPAND(PP_ARG_POPER(__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
#define PP_ARG_POPER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N

#define PP_ARG_AT(Index, ...) PP_ARG_AT_##Index(__VA_ARGS__)
#define PP_ARG_AT_0(...)  PP_EXPAND(PP_ARG_POPER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, __VA_ARGS__))
#define PP_ARG_AT_1(...)  PP_EXPAND(PP_ARG_POPER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, __VA_ARGS__))
#define PP_ARG_AT_2(...)  PP_EXPAND(PP_ARG_POPER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, __VA_ARGS__))
#define PP_ARG_AT_3(...)  PP_EXPAND(PP_ARG_POPER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, __VA_ARGS__))
#define PP_ARG_AT_4(...)  PP_EXPAND(PP_ARG_POPER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, __VA_ARGS__))
#define PP_ARG_AT_5(...)  PP_EXPAND(PP_ARG_POPER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, __VA_ARGS__))
#define PP_ARG_AT_6(...)  PP_EXPAND(PP_ARG_POPER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, __VA_ARGS__))
#define PP_ARG_AT_7(...)  PP_EXPAND(PP_ARG_POPER(_1, _2, _3, _4, _5, _6, _7, _8, _9, __VA_ARGS__))
#define PP_ARG_AT_8(...)  PP_EXPAND(PP_ARG_POPER(_1, _2, _3, _4, _5, _6, _7, _8, __VA_ARGS__))
#define PP_ARG_AT_9(...)  PP_EXPAND(PP_ARG_POPER(_1, _2, _3, _4, _5, _6, _7, __VA_ARGS__))
#define PP_ARG_AT_10(...) PP_EXPAND(PP_ARG_POPER(_1, _2, _3, _4, _5, _6, __VA_ARGS__))
#define PP_ARG_AT_11(...) PP_EXPAND(PP_ARG_POPER(_1, _2, _3, _4, _5, __VA_ARGS__))
#define PP_ARG_AT_12(...) PP_EXPAND(PP_ARG_POPER(_1, _2, _3, _4, __VA_ARGS__))
#define PP_ARG_AT_13(...) PP_EXPAND(PP_ARG_POPER(_1, _2, _3, __VA_ARGS__))
#define PP_ARG_AT_14(...) PP_EXPAND(PP_ARG_POPER(_1, _2, __VA_ARGS__))
#define PP_ARG_AT_15(...) PP_EXPAND(PP_ARG_POPER(_1, __VA_ARGS__))
#define PP_ARG_AT_16(...) PP_EXPAND(PP_ARG_POPER( __VA_ARGS__))
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-07-10 16:43:37

在C++11中,std::maxinitializer_list一起工作,因此您可以使用

代码语言:javascript
复制
std::max({40, 31, 42, 13, 4, 25, 16, 27});

如果您真的想要MAX(p1, p2, p3)语法,您可以这样做:

代码语言:javascript
复制
#define MAX(...) std::max({__VA_ARGS__})
票数 6
EN

Stack Overflow用户

发布于 2019-07-23 15:07:24

您的问题包含了一半的答案-您可以使用min宏中显示的技术构建带有变量参数号的PP_ARG_COUNT /max宏(与原始代码一样,参数的数量将有限制,但您可以选择)。

下面是示例代码(最多4个参数):

代码语言:javascript
复制
#include <stdio.h>

#define __START(op, A, B, C, D, N, ...) __ARGS_##N(op, A, B, C, D)
#define __ARGS_1(op, A, B, C, D) A
#define __ARGS_2(op, A, B, C, D) __##op(A, B)
#define __ARGS_3(op, A, B, C, D) __##op(A, __##op(B, C))
#define __ARGS_4(op, A, B, C, D) __##op(__##op(A, B), __##op(C, D))


#define __MIN(A, B) ((A) < (B) ? (A) : (B))
#define __MAX(A, B) ((A) > (B) ? (A) : (B))

#define min(...) __START(MIN, __VA_ARGS__, 4, 3, 2, 1)
#define max(...) __START(MAX, __VA_ARGS__, 4, 3, 2, 1)

int main(void)
{
   printf("min(1) -> %d\n\n", min(1));
   printf("min(1.5, 2) -> %lf\n", min(1.5,2));
   printf("min(3, 2, 1.5) -> %lf\n", min(3,2,1.5));
   printf("min(1, 2, 3, 4) -> %d\n", min(1,2,3,4));
   printf("min(2, 3, 4, 1) -> %d\n\n", min(2,3,4,1));

   printf("max(2.5, 2.0) -> %lf\n", max(2.5, 2.0));
   printf("max(3, 2, 3.5) -> %lf\n", max(3, 2, 3.5));
   printf("max(1, 2, 3, 4) -> %d\n", max(1, 2, 3, 4));
   printf("max(2, 3, 4, 1) -> %d\n", max(2, 3, 4, 1));

   return 0;
}

如果您编译并运行该程序,您将得到以下输出:

代码语言:javascript
复制
min(1) -> 1

min(1.5, 2) -> 1.500000
min(3, 2, 1.5) -> 1.500000
min(1, 2, 3, 4) -> 1
min(2, 3, 4, 1) -> 1

max(2.5, 2.0) -> 2.500000
max(3, 2, 3.5) -> 3.500000
max(1, 2, 3, 4) -> 4
max(2, 3, 4, 1) -> 4

它是如何工作的。__START宏接受以下参数:

  • op -宏名(前面没有双下划线),它只使用两个参数执行必要的操作
  • ABCD -这些参数将接收min/max的参数,如果min/max参数的数量小于最大值(在本示例代码中为4个),则可能会收到一些虚拟参数。
  • N - min/max参数的数量。
  • ... -其他一些愚蠢的论点。

__START将根据参数号展开为__ARGS_1..__ARGS_4之一。通过添加调用4, 3, 2, 1宏的__START参数获得参数号:

代码语言:javascript
复制
#define min(...) __START(MIN, __VA_ARGS__, 4, 3, 2, 1)

因此,如果您调用例如min(1.5, 2.5, 3.5),它将扩展到(我在注释中添加了参数名称):

代码语言:javascript
复制
__START(/*op=*/ MIN, /*A=*/ 1.5, /*B=*/ 2.5, /*C=*/ 3.5, /*D=*/ 4, /*N=*/ 3, 2, 1)

然后,__START将扩展到__ARGS_3,下面的扩展非常简单。现在我们可以清楚地看到,参数数是如何“计算”的,以及它是如何工作的。您可以使用其他功能轻松地实现相同的宏,并增加参数的最大数量,例如sum

代码语言:javascript
复制
#define __SUM(A, B) ((A)+(B))
#define sum(...) __START(SUM, __VA_ARGS__, 4, 3, 2, 1)

认为它不像min/max那样有用。

如果使用VisualC++,则需要添加一些变通方法(如第一篇文章中的PP_EXPAND ),以克服VC++预处理器错误详情见。我用GCC,它不需要一个。

票数 3
EN

Stack Overflow用户

发布于 2014-04-01 01:45:57

有C++ STL算法来做同样的事情:

元素元素

开始使用这些,而不是编写宏来实现这一点:

代码语言:javascript
复制
 int arr[] = {1,2,3,4,5};
 int* min = std::min_element(arr, arr+5);
 int* max = std::max_element(arr,arr+5);
 std::cout<<"min:"<<*min<<"max:"<<*max<<std::endl;
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22775312

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档