Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/22.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++ 我们可以实现一个max或min宏,它可以接受变量参数(两个以上的参数)_C++_Variadic Macros_Boost Preprocessor - Fatal编程技术网

C++ 我们可以实现一个max或min宏,它可以接受变量参数(两个以上的参数)

C++ 我们可以实现一个max或min宏,它可以接受变量参数(两个以上的参数),c++,variadic-macros,boost-preprocessor,C++,Variadic Macros,Boost Preprocessor,我想实现一个新的max/min宏,它可以接受两个以上的参数,例如: #define max( ... ) ... 然后,我可以这样使用它: max( p0, p1, p2, p3 ) max( 2, 4, 100 ) max( 1,2,3,4,5,6,7 ) -> 7 #define MAX_FOLD(s, state, elem) BOOST_PP_MAX(state, elem) #define MAX(...) BOOST_PP_SEQ_FOLD_LEFT(MAX_FOLD,

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

#define max( ... ) ...
然后,我可以这样使用它:

max( p0, p1, p2, p3 )
max( 2, 4, 100 )
max( 1,2,3,4,5,6,7 ) -> 7
#define MAX_FOLD(s, state, elem) BOOST_PP_MAX(state, elem) 
#define MAX(...) BOOST_PP_SEQ_FOLD_LEFT(MAX_FOLD, 0, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) 
该宏是否可以帮助我们实现该宏

#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__))

有C++ STL算法做同样的操作:

开始使用这些而不是编写宏来实现此目的:

 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;
intarr[]={1,2,3,4,5};
int*min=std::min_元素(arr,arr+5);
int*max=std::max_元素(arr,arr+5);
std::cout使用,您可以这样实现它:

max( p0, p1, p2, p3 )
max( 2, 4, 100 )
max( 1,2,3,4,5,6,7 ) -> 7
#define MAX_FOLD(s, state, elem) BOOST_PP_MAX(state, elem) 
#define MAX(...) BOOST_PP_SEQ_FOLD_LEFT(MAX_FOLD, 0, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) 
因为预处理器在扩展期间不直接支持比较,所以从头开始实现这一切需要大量的工作。使用这些技术,您可以实现计数器和while循环构造。有了它,您可以实现减法,这将允许您实现小于(或大于),这是
MAX
所需要的。然后使用另一个
while
可以折叠变量参数

最后,在预处理器中执行所有这些操作有一些限制。预处理器不是完全图灵完成的。因此,在boost示例中,您将被限制为0到256之间的值(这完全是一个boost限制,如果您自己这样做,您可以提高该限制)。根据您想要实现的目标,最好为max编写varidiac函数:

template<class T, class U>
T max(T x, T y)
{
    return x > y ? x : y;
}

template<class... Ts>
T max(T x, Ts... xs)
{
    return max(x, max(xs...)); 
}
模板
T最大值(T x,T y)
{
返回x>y?x:y;
}
模板
最大温度(tx,Ts…xs)
{
返回max(x,max(xs…);
}

在C++11中,
std::max
初始值设定项\u list
一起工作,因此您可以使用

std::max({40, 31, 42, 13, 4, 25, 16, 27});
如果您确实想要
MAX(p1,p2,p3)
语法,您可以执行以下操作:

#define MAX(...) std::max({__VA_ARGS__})

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

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

它是如何工作的。
\u START
宏采用以下参数:

#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;
}
  • op
    -宏名称(前面没有双下划线),它只使用两个参数执行必要的操作
  • A
    B
    C
    D
    -这些参数将接收
    min
    /
    max
    的参数,如果
    min
    /
    max
    参数的数量小于最大值(本示例代码中为4个),则可能会接收一些伪参数
  • N
    -参数
    min
    /
    max
    的数量
  • -一些其他伪参数
\uuuu START
将扩展到其中一个
\uuuu ARGS\u 1
\uuuu ARGS\u 4
取决于参数编号。参数编号是通过添加调用
\u START
宏的
4,3,2,1
参数获得的:

#define min(...) __START(MIN, __VA_ARGS__, 4, 3, 2, 1)
因此,如果您调用例如
min(1.5,2.5,3.5)
,它将扩展到(我在注释中添加了参数名称):

\uuu START
随后将扩展到
\uu ARGS\u 3
,下面的扩展非常简单。 现在可以清楚地看到参数数是如何“计数”的以及它是如何工作的。您可以轻松地使用其他功能实现相同的宏,并增加最大参数数,例如
sum

#define __SUM(A, B) ((A)+(B))
#define sum(...) __START(SUM, __VA_ARGS__, 4, 3, 2, 1)
虽然它不如
min
/
max
那么有用


如果你使用VisualC++,你需要添加一些解决方法(比如在第一篇文章中使用代码> PPYPosisiux/Cuff>)来克服VC++预处理器错误。我使用GCC,它不需要一个。< / P>嗨,我不会使用这个代码,我问这个问题,因为我想研究这种预处理器技术,非常感谢……Hikari:几乎没有必要在纯C++中编写宏。这些STL算法将和宏一样高效(几乎)。您还可以使用内联概念来实现宏类型行为。所以你应该学习这些概念,而不是宏观。选择权在你:)@tmp这仍然是一个有趣的学习练习。我们不能读Hikari的想法。嗨,我不会用这个代码,我问这个问题,因为我想学习这个预处理器技术这个标题,谢谢LoTISS这C或C++?挑一个。在C++中,可以使用更健壮的技术来代替宏。