Cómo expandir una macro recursiva a través de __VA_OPT__ en un contexto anidado
He leído este artículo, el cual ilustra cómo la función macro __VA_OPT__
puede ser utilizada para expandir de forma recursiva una macro. Me gustaría implementar algo similar, pero con la diferencia de que la macro se expande en un contexto anidado.
La entrada:
cpp
NEST_RECURSIVE(A, B, C)
debería producir (el orden no importa):
cpp
((( | C) | B) | A)
Mi enfoque es ligeramente generalizado a partir del artículo:
“`cpp
<h1>define PARENS ()</h1>
<h1>define EXPAND(…) EXPAND4(EXPAND4(EXPAND4(EXPAND4(<strong>VA_ARGS</strong>))))</h1>
<h1>define EXPAND4(…) EXPAND3(EXPAND3(EXPAND3(EXPAND3(<strong>VA_ARGS</strong>))))</h1>
<h1>define EXPAND3(…) EXPAND2(EXPAND2(EXPAND2(EXPAND2(<strong>VA_ARGS</strong>))))</h1>
<h1>define EXPAND2(…) EXPAND1(EXPAND1(EXPAND1(EXPAND1(<strong>VA_ARGS</strong>))))</h1>
<h1>define EXPAND1(…) <strong>VA_ARGS</strong></h1>
<h1>define FOR<em>EACH</em>R(func, …) <strong>VA<em>OPT</em></strong>(EXPAND(FOREACH<em>HELPER</em>R(func, <strong>VA_ARGS</strong>)))</h1>
<h1>define FOR<em>EACH</em>HELPER<em>R(func, sub, …) func(<strong>VA</strong></em>OPT(FOR<em>EACH</em>AGAIN<em>R PARENS (func, <strong>VA</strong></em>ARGS)), sub)</h1>
<h1>define FOR<em>EACH</em>AGAIN<em>R() FOR</em>EACH<em>HELPER</em>R</h1>
<h1>define MY_FUNC(nested, var) (nested | var)</h1>
<h1>define NEST<em>RECURSIVE(…) FOR</em>EACH<em>R(MY</em>FUNC, <strong>VA_ARGS</strong>)</h1>
“`
El código actual produce la siguiente salida:
cpp
(FOR_EACH_HELPER_R (MY_FUNC, B, C) | A)
Como se puede ver, la expansión no ocurre más allá del primer nivel.
Imagino que tendría que utilizar EXPAND
en algún otro lugar, sin embargo, no puedo averiguar dónde.
Es completamente posible que lo que estoy intentando hacer sea imposible, sin embargo, el método de expansión recursiva de macro pre-C++20 (utilizando PP_NARG
) funciona con anidamiento, así que espero que el nuevo y más limpio enfoque también funcione con él.
davy.ai
Después de analizar tu código, he encontrado que tu macro
FOR_EACH_R
no está aplicando el mismo enfoque recursivo utilizado en el artículo que leíste, lo cual causa que no se expanda más allá del primer nivel.Para solucionar esto, necesitas modificar tu macro
FOR_EACH_R
para aplicar el enfoque recursivo como se muestra en el artículo. La implementación actualizada es la siguiente:Esto modifica la macro
FOR_EACH_R
para primeroEXPANDIR
los argumentos de entrada, y luego aplicar un enfoque de expansión recursiva de dos pasos:FOR_EACH_HELPER_R1
aplica la lógica recursiva para el nivel actual, mientras queFOR_EACH_HELPER_R2
verifica si hay más niveles para expandir y continúa la recursión en caso afirmativo.Con este cambio, tu macro
NEST_RECURSIVE
producirá la salida deseada:¡Espero que esto te ayude! Avísame si tienes alguna pregunta adicional.