문제

나는 약간의 이론적 문제가 발생합니다. 코드 한 장에서 나는 유지하고있는 매크로 세트가 있습니다.

#define MAX_OF_2(a, b)       (a) > (b) ? (a) : (b)
#define MAX_OF_3(a, b, c)    MAX_OF_2(MAX_OF_2(a, b), c)
#define MAX_OF_4(a, b, c, d) MAX_OF_2(MAX_OF_3(a, b, c), d)
...etc up to MAX_OF_8

내가하고 싶은 것은 다음과 같은 것으로 바꾸는 것입니다.

/* Base case #1, single input */
#define MAX_OF_N(x)      (x)

/* Base case #2, two inputs */
#define MAX_OF_N(x, y)   (x) > (y) ? (x) : (y)

/* Recursive definition, arbitrary number of inputs */
#define MAX_OF_N(x, ...) MAX_OF_N(x, MAX_OF_N(__VA_ARGS__))

... 물론 유효한 사전 처리기 코드가 아닙니다.

이 특정 사례를 무시하면 아마도 사전 처리기 매크로가 아닌 함수를 사용하여 해결해야 할 것입니다., variadic max_of_n () 매크로를 정의 할 수 있습니까?

명확성을 위해 최종 결과는 임의의 수의 매개 변수를 취하고 가장 큰 매개 변수를 평가하는 단일 매크로 여야합니다. 나는 이것이 가능해야한다는 이상한 느낌을 받았지만 어떻게 보지 못했습니다.

도움이 되었습니까?

해결책

아니요, 전처리 서가 파일에서 "스 와이프"만 가져 가기 때문에. 매크로를 재귀 적으로 정의 할 방법이 없습니다.

내가 본 유일한 코드는 ~ 아니다 Variadic이지만 사용 된 기본값을 사용하여 사용자가 통과해야했습니다.

x = MAX_OF_8 (a, b, -1, -1, -1, -1, -1, -1)

모든 값이 음성이 없다고 가정합니다.

인라인 함수는 적어도 C ++에 대해 동일하게 제공해야합니다. 당신이 말하듯이, 아마도와 유사한 변수 인수가있는 함수에 남은 것이 더 나을 것입니다. printf().

다른 팁

호출되는 인수의 수를 평가하는 매크로를 작성할 수 있습니다. (처음 본 곳에 대한 링크를 찾을 수 없었습니다.) 따라서 원하는대로 작동하는 max_of_n ()을 쓸 수 있지만, 일부 제한까지 번호가 매겨진 매크로가 모두 필요합니다.

#define MAX_OF_1(a)         (a)         
#define MAX_OF_2(a,b)       max(a, b)

#define MAX_OF_3(a,...)    MAX_OF_2(a,MAX_OF_2(__VA_ARGS__))
#define MAX_OF_4(a,...)    MAX_OF_2(a,MAX_OF_3(__VA_ARGS__))
#define MAX_OF_5(a,...)    MAX_OF_2(a,MAX_OF_4(__VA_ARGS__))
...
#define MAX_OF_64(a,...)   MAX_OF_2(a,MAX_OF_63(__VA_ARGS__))

// NUM_ARGS(...) evaluates to the literal number of the passed-in arguments.
#define _NUM_ARGS2(X,X64,X63,X62,X61,X60,X59,X58,X57,X56,X55,X54,X53,X52,X51,X50,X49,X48,X47,X46,X45,X44,X43,X42,X41,X40,X39,X38,X37,X36,X35,X34,X33,X32,X31,X30,X29,X28,X27,X26,X25,X24,X23,X22,X21,X20,X19,X18,X17,X16,X15,X14,X13,X12,X11,X10,X9,X8,X7,X6,X5,X4,X3,X2,X1,N,...) N
#define NUM_ARGS(...) _NUM_ARGS2(0, __VA_ARGS__ ,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)

#define _MAX_OF_N3(N, ...) MAX_OF_ ## N(__VA_ARGS__)
#define _MAX_OF_N2(N, ...) _MAX_OF_N3(N, __VA_ARGS__)
#define MAX_OF_N(...)      _MAX_OF_N2(NUM_ARGS(__VA_ARGS__), __VA_ARGS__)

지금 MAX_OF_N(a,b,c,d,e) 평가할 것입니다 max(a, max(b, max(c, max(d, e)))). (GCC 4.2.1에서 테스트했습니다.)

기본 케이스가 중요합니다 (MAX_OF_2) 확장에서 그 주장을 두 번 이상 반복하지 않습니다 (이것이 내가 넣는 이유입니다. max 이 예에서). 그렇지 않으면, 당신은 모든 레벨에 대한 확장 길이를 두 배로 늘릴 것이므로, 당신은 64 인수로 어떤 일이 일어날 지 상상할 수 있습니다 :)

이 부정 행위는 재귀가 아니며 사전 처리기에서 작업을 수행하지 않기 때문에이 부정 행위를 고려할 수 있습니다. 그리고 그것은 GCC 확장을 사용합니다. 그리고 그것은 하나의 유형에 대해서만 작동합니다. 그러나 Variadic max_of_n 매크로입니다.

#include <iostream>
#include <algorithm>

#define MAX_OF_N(...) ({\
        int ra[] = { __VA_ARGS__ }; \
        *std::max_element(&ra[0], &ra[sizeof(ra)/sizeof(int)]); \
    })

int main() {
    int i = 12;
    std::cout << MAX_OF_N(1,3,i,6);
}

아, 예, 이니셜 라이저 목록의 잠재적 변수 표현식으로 인해 C89에서 (std :: max_element를 피하기 위해 자체 기능을 사용)와 동등한 것으로 생각하지 않습니다. 그러나 Variadic 매크로가 C89에도 확실하지 않습니다.

다음은 "하나의 유형"제한을 둘러싼 것으로 생각하는 것이 있습니다. 그래도 약간 털이 발생합니다.

#include <iostream>
#include <algorithm>

#define MAX_OF_N(x, ...) ({\
        typeof(x) ra[] = { (x), __VA_ARGS__ }; \
        *std::max_element(&ra[0], &ra[sizeof(ra)/sizeof(ra[0])]); \
    })

int main() {
    int i = 12;
    std::cout << MAX_OF_N(i+1,1,3,6,i);
}

매크로를 재귀 적으로 확장 할 수 있다고해도 효율성 측면에서 접근 방식에 약간의 문제가있을 것이라고 생각합니다. MAX_OF_[N-1] 더 크면 처음부터 다시 평가해야합니다.

여기 아무도 XD를 좋아하지 않을 어리 석고 어리석은 대답이 있습니다.

"source.c"파일

#include "my_macros.h"
...

"makefile"파일

myprogram: source.c my_macros.h
 gcc source.c -o myprogram

my_macros.h: make_macros.py
 python make_macros.py > my_macros.h

"make_macros.py"파일

def split(l):
    n = len(l)
    return l[:n/2], l[n/2:]

def gen_param_seq(n):
    return [chr(i + ord("A")) for i in range(n)]

def make_max(a, b):
    if len(a) == 1:
        parta = "("+a[0]+")"
    else:
        parta = make_max(*split(a))

    if len(b) == 1:
        partb = "("+b[0]+")"
    else:
        partb = make_max(*split(b))

    return "("+parta +">"+partb+"?"+parta+":"+partb+")"

for i in range(2, 9):
    p = gen_param_seq(i)
    print "#define MAX_"+str(i)+"("+", ".join(p)+") "+make_max(*split(p))

그런 다음 예쁜 매크로를 정의 할 수 있습니다.

#define MAX_2(A, B) ((A)>(B)?(A):(B))
#define MAX_3(A, B, C) ((A)>((B)>(C)?(B):(C))?(A):((B)>(C)?(B):(C)))
#define MAX_4(A, B, C, D) (((A)>(B)?(A):(B))>((C)>(D)?(C):(D))?((A)>(B)?(A):(B)):((C)>(D)?(C):(D)))
#define MAX_5(A, B, C, D, E) (((A)>(B)?(A):(B))>((C)>((D)>(E)?(D):(E))?(C):((D)>(E)?(D):(E)))?((A)>(B)?(A):(B)):((C)>((D)>(E)?(D):(E))?(C):((D)>(E)?(D):(E))))
#define MAX_6(A, B, C, D, E, F) (((A)>((B)>(C)?(B):(C))?(A):((B)>(C)?(B):(C)))>((D)>((E)>(F)?(E):(F))?(D):((E)>(F)?(E):(F)))?((A)>((B)>(C)?(B):(C))?(A):((B)>(C)?(B):(C))):((D)>((E)>(F)?(E):(F))?(D):((E)>(F)?(E):(F))))
#define MAX_7(A, B, C, D, E, F, G) (((A)>((B)>(C)?(B):(C))?(A):((B)>(C)?(B):(C)))>(((D)>(E)?(D):(E))>((F)>(G)?(F):(G))?((D)>(E)?(D):(E)):((F)>(G)?(F):(G)))?((A)>((B)>(C)?(B):(C))?(A):((B)>(C)?(B):(C))):(((D)>(E)?(D):(E))>((F)>(G)?(F):(G))?((D)>(E)?(D):(E)):((F)>(G)?(F):(G))))
#define MAX_8(A, B, C, D, E, F, G, H) ((((A)>(B)?(A):(B))>((C)>(D)?(C):(D))?((A)>(B)?(A):(B)):((C)>(D)?(C):(D)))>(((E)>(F)?(E):(F))>((G)>(H)?(G):(H))?((E)>(F)?(E):(F)):((G)>(H)?(G):(H)))?(((A)>(B)?(A):(B))>((C)>(D)?(C):(D))?((A)>(B)?(A):(B)):((C)>(D)?(C):(D))):(((E)>(F)?(E):(F))>((G)>(H)?(G):(H))?((E)>(F)?(E):(F)):((G)>(H)?(G):(H))))

그리고 그것에 대한 가장 좋은 점은 ... 작동하는 것입니다 ^_ ^

C ++ 로이 길을 가고 있다면 템플릿 메타 프로 그램. 예쁘지 않으며 정확한 문제를 해결하지 못할 수도 있지만 재귀를 처리합니다.

첫째, 매크로는 회복 적으로 확장되지 않습니다. 그러나 매크로는 각 재귀 수준에 대한 매크로를 생성 한 다음 재귀 수준을 추론함으로써 재창조를 가질 수 있습니다. 그러나이 모든 반복과 재귀 추론은 부스트 .proprocessor 도서관. 따라서 고차 폴드 매크로를 사용하여 최대를 계산할 수 있습니다.

#define MAX_EACH(s, x, y) BOOST_PP_IF(BOOST_PP_GREATER_EQUAL(x, y), x, y)
#define MAX(...) BOOST_PP_SEQ_FOLD_LEFT(MAX_EACH, 0, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) 

MAX(3, 6, 8) //Outputs 8
MAX(4, 5, 9, 2) //Outputs 9

이제 이것은 0-256 사이의 문자 번호를 이해할 것입니다. C 프리 프로세서가 C ++를 이해하지 못하기 때문에 C ++ 변수 또는 표현식에서 작동하지 않습니다. 순수한 텍스트 교체. 그러나 C ++는 C ++ 표현식에서 작동하는 "기능"이라는 기능을 제공하며이를 최대 값을 계산할 수 있습니다.

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

template<class X, class... T>
auto max(X x, T ... args) -> decltype(max(x, max(args...)))
{
    return max(x, max(args...));
}

이제 위의 코드에는 C ++ 11 컴파일러가 필요합니다. C ++ 03을 사용하는 경우 변수 매개 변수를 시뮬레이션하기 위해 기능의 여러 과부하를 만들 수 있습니다. 또한, 우리는 사전 처리기를 사용 하여이 반복적 인 코드를 생성 할 수 있습니다 (그게 바로 그랬습니다). 따라서 C ++ 03에서는 다음을 작성할 수 있습니다.

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

#define MAX_FUNCTION(z, n, data) \
template<class T> \
T max(T x, BOOST_PP_ENUM_PARAMS(n, T x)) \
{ \
    return max(x, max(BOOST_PP_ENUM_PARAMS(n, x)));\
}

BOOST_PP_REPEAT_FROM_TO(2, 64, MAX_FUNCTION, ~) 
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top