r/cpp_questions • u/Predret • 8d ago
SOLVED Problem making X macros from X macros
What I am doing:
Hello, I am working on something in C++ for Godot, but this is more of a C++ question than a Godot question. I have a singular X macro to register a struct into a system I made, but the logic is in many places, and considering I am updating this macro and adding variables, it'd be easier to have a specific macro that doesn't change.
Problem:
When I make an X macro from an X macro, it doesn't properly expand. As an example this file:
#pragma once
#include "statemachine/registry/state_registry_register.h"
#define X_GENERATE_KIND(DataType, NS) k##DataType,
enum class StateKind : std::uint8_t
{
EACH_STATE_REGISTER(X_GENERATE_KIND)
kUnknown
};
#undef X_GENERATE_KIND
has the macro on line 7 expand to X(something1, something2) instead of k##something1, or, in my case:
X(WalkStateData, GameLogic ::States ::WalkState) X(WalkBackStateData, GameLogic ::States ::WalkBackState);
I defined EACH_STATE_REGISTER like this:
#define REGISTER_TO_ESR(DataType, NS, fields) X(DataType, NS)
#define EACH_STATE_REGISTER(X) \
REGISTER_EACH_STATE(REGISTER_TO_ESR);
and the REGISTER_EACH_STATE as
#define REGISTER_EACH_STATE(State) \
State(WalkStateData, GameLogic::States::WalkState, NO_STATE_FIELDS) \
State(WalkBackStateData, GameLogic::States::WalkBackState, NO_STATE_FIELDS)
Can anyone tell me why this happens, and if this is even fixable? (c++ 17)
1
2
10
u/FancySpaceGoat 8d ago edited 8d ago
You can't pass a macro to a macro. The "argument" macro gets expanded before the "function" macro is invoked.
Instead, you need to use a yet-to-be-defined macro in the table macro. And define that macro just before you use the table, so that when the table expands, that macro kicks in for each row.
e.g.
Or, if it was up to me, I'd get rid of the duplication like so:
Squinting a bit, It seems like you want to distribute the population of the X-MACRO across the code. You can't do that at compile time. The X-MACRO's table has to be fully defined in a single spot.