Можем ли мы реализовать макрос max или min, который может принимать переменные аргументы (более двух параметров)

Я хочу реализовать новый макрос max / min, который может принимать более двух параметров, например:

#define max( ... ) ...

и тогда я могу использовать это так:

max( p0, p1, p2, p3 )
max( 2, 4, 100 )
max( 1,2,3,4,5,6,7 ) -> 7

если этот макрос может помочь нам реализовать этот макрос?

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

3

Решение

В C ++ 11 std::max работает с initializer_listтак что вы можете использовать

std::max({40, 31, 42, 13, 4, 25, 16, 27});

И если вы действительно хотите MAX(p1, p2, p3) синтаксис, вы можете сделать:

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

Другие решения

Есть алгоритм C ++ STL, чтобы сделать то же самое:

max_element.

min_element

Начинает использовать их вместо написания макроса для достижения этой цели:

 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

С помощью Boost.Preprocessor, Вы можете реализовать это так:

#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 Вы можете сделать сгиб по аргументам varidiac.

Наконец, есть некоторые ограничения на выполнение всего этого в препроцессоре. Препроцессор не полностью завершен. Таким образом, в примере повышения вы будете ограничены значениями от 0 до 256 (это полностью ограничение повышения, если вы сделаете это сами, вы можете повысить это ограничение). В зависимости от того, чего вы хотите достичь, может быть лучше написать функцию varidiac для max:

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...));
}
2
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector