2017-02-10 115 views
6

Przy pomocy preprocesora C można uzyskać makra wysokopoziomowe. Coś takiego:Zagnieżdżona iteracja makra za pomocą preprocesora C

#define ABC(f) f(a) f(b) f(c) 
#define XY(f) f(x) f(y) 

#define CODE(x) foo_ ## x 
ABC(CODE) 
#undef CODE 

#define CODE(x) bar_ ## x 
XY(CODE) 
#undef CODE 

Wyjście jest:

foo_a foo_b foo_c 
bar_x bar_y 

Czy jest jakiś trik do gniazdowania takich iteracji, aby zrobić coś takiego?

#define CODE(x) foo_ ## x 
NEST(ABC, XY, CODE) 
#undef CODE 

więc wyjście byłoby:

foo_ax foo_ay foo_bx foo_by foo_cx foo_cy 

W szczególności chciałbym mieć definicje ABC i XY niezależne od siebie, tak, że mogę nadal korzystać ABC stand-alone a może nawet zrobić coś takiego:

#define CODE(x) foo_ ## x 
NEST(XY, KLMN, ABC, CODE) 
#undef CODE 

Dla przypomnienia, tutaj rozwiązanie:

#include <boost/preprocessor/seq.hpp> 

#define ABC (a) (b) (c) 
#define XY (x) (y) 

#define CODE(r, prod) BOOST_PP_CAT(foo_, BOOST_PP_SEQ_CAT(prod)) 
BOOST_PP_SEQ_FOR_EACH_PRODUCT(CODE, (ABC) (XY)) 

Plony:

foo_ax foo_ay foo_bx foo_by foo_cx foo_cy 
+1

Z doświadczenia mogę powiedzieć, że gdy jesteś głęboko w meta-programowanie makr, jesteś prawie na pewno stworzenie słaby projekt programu i prawie na pewno jest to niewłaściwe rozwiązanie problemu. "Makra X" i ich różne odpady należy traktować jako ostatnią deskę ratunku. Jaki jest faktyczny problem, który próbujesz rozwiązać? – Lundin

Odpowiedz

3

Boost Preprocessor Library oferuje kilka makr, że może to zrobić po wyjęciu z pudełka.

będzie iterować na kartezjańskich produktach z dwóch lub więcej list zakodowanych w formie (x) (y) (z) (które są znane jako sekwencja jest biblioteki).

BOOST_PP_LIST_FOR_EACH_PRODUCT zrobi to samo dla list zakodowanych jako (x, (y, (z, NIL))).

To trywialne do konwersji X macro iteracji do „sekwencji”, jak to:

#define LIST_TO_SEQ(X) (X) 
ABC(LIST_TO_SEQ)