이 작업을 수행하는 것은 좋지 않지만, 은 일 수 있습니다. 여기에는 한 가지 방법이 있습니다.
적절하게 강력한 메타 프로그래밍 라이브러리 인 Order (앞서 언급 한 Boost가 또 다른 가능한 후보 임)을 사용하는 경우 실제로 전처리기에 루프가 생기고 재귀 매크로를 정의 할 수 있습니다. Order를 사용하면 Scheme 또는 ML을 아는 사람이 익숙한 기능적 스타일로 프로그래밍 할 수 있습니다.
루프하려면 for_each
구조를 사용하십시오. 단순히 뭔가 주어진 수를 만들려면 당신은 1, N+1
와 for_each_in_range
를 사용할 수 있습니다
ORDER_PP( // within this block Order code runs
8for_each_in_range(8fn(8_, 8print((*))),
1, 8)
)
은 위의 일곱 별을 인쇄합니다. 당신은 정상 전처리 규칙에 따라 기존의 매크로, 내부 metaprogram 블록을 마무리 할 수 있습니다 다음 ORDER_PP
블록 내
// print COUNT stars
#define STARS(COUNT) ORDER_PP(\
8for_each_in_range(8fn(8_, 8print((*))), 1, 8plus(COUNT, 1)) \
)
을 모두 호출 할 수 있습니다 만 인식 주문 기능을 의미 주문 코드보다는 C 전 처리기 코드로 간주됩니다 (모든 값/전처리 토큰은 raw int이거나 8(val)
구조로 "quoted"여야합니다). 이 중첩 된 표현의 한 부분으로 ORDER_PP
내에서 호출 할 수 있도록 대신 CPP 매크로의 주문 기능으로 stars
를 정의하려면, 우리는이처럼 쓸 필요가 :
#define ORDER_PP_DEF_8stars ORDER_PP_FN(\
8fn(8C, 8for_each_in_range(8fn(8_, 8print((*))), 1, 8plus(8C, 1))))
ORDER_PP(8stars(7)) // prints 7 stars
주문이 완전히 투명하게 재귀를 제공하고, 그래서 중첩 초기화 루프를 작성하는 것은 비교적 간단합니다 :
#define ORDER_PP_DEF_8ndim_init ORDER_PP_FN(\
8fn(8N, 8T, 8C, 8I, 8D, \
8do(\
8print(8N (=malloc) 8lparen 8seq_head(8D) (*sizeof) 8lparen 8T 8stars(8minus(8C, 1)) 8rparen 8rparen (;)), \
8if(8equal(8C, 1), \
8print(((void)0;)), \
8do(\
8print((for) 8lparen (int) 8I (=0;) 8I (<) 8seq_head(8D) (;) 8I (++) 8rparen ({)), \
8ndim_init(8adjoin(8N, 8([), 8I, 8(])), 8T, 8minus(8C, 1), 8cat(8I, 8(_K)), 8seq_tail(8D)), \
8print((})) \
)))))
호출 ndim_init
같은 :
// print the nested initializer from the question
ORDER_PP(
8ndim_init(8(nda), 8(int), 3, 8(i), 8seq(8(n1), 8(n2), 8(n3)))
)
ORDER_PP
블록 내에 나타날 때 C 변수 이름 (nda
, i
등)을 인용해야하므로 Order가 변수를 평가하려고하는 대신 텍스트로 처리하도록합니다. 마지막 인수는 각 차원의 크기를 포함하는 런타임 변수 목록입니다 (8seq
은 목록을 작성하고 8
은 C 변수 이름을 다시 인용 함).
STARS
의 첫 번째 예제와 마찬가지로 쉽게 액세스 할 수 있도록 일반 사전 처리기 매크로에서 ndim_init
의 호출을 패키지화 할 수 있습니다. 단일 호출 선언과 초기화를 방출하는, 이런 식으로 쉽게 선언자 매크로와 결합 할 수 있습니다
#define NDIM(NAME, TYPE, ...) ORDER_PP (\
8lets((8D, 8((__VA_ARGS__))) \
(8C, 8tuple_size(8D)), \
8do(\
8print((TYPE) 8stars(8C) (NAME; {)), \
8ndim_init(8(NAME), 8(TYPE), 8C, 8(_ITER), 8tuple_to_seq(8D)), \
8print((})) \
)) \
)
NDIM(nda, int, n1, n2, n3) // emits declaration and init block for int ***nda
More Order examples이 (가) 위의 모든 간단한 것 같지 않은 경우 .. 그래서 사람들은 당신이 그것을해서는 안된다고 말합니다. (그랬다면, 당신에게 좋은, 아무도 당신의 코드를 읽을 수있을 것입니다.)
, 유형 이름의 이용은 무엇 런타임에? – Jiminion
여기 뭔가가 간접 참조의 n 레벨에 대한 포인터를 선언하지 않는다는 것을 알려줍니다. 오히려 처음부터이 작업을 수행하려는 이유가 *있는 것 같습니다. – WhozCraig
혼란을 가져 주어서 죄송합니다. 질문을 변경했습니다. – user2690457