I am trying to #stringify each token in a __VA_ARGS__
from a variadic macro.
The idea is to use these tokens as entries in an enum
and also push them (stringified) to a std::vector<std::string>
. Assuming the enum
entries have default values, they would then map as indices in the vector.
Example:
#include <vector>
#include <string>
#define MAKE_ENUM_AND_STRINGS(...)\
enum test_enum{ __VA_ARGS__ };\
std::vector<std::string> test_vector{ /*bad*/__VA_ARGS__/*bad*/ }
void foo() {
MAKE_ENUM_AND_STRINGS(a, b, c, d);
}
I have already read many posts about it and can't find a satisfying solution (I don't want to define 20+ macros to "parse" __VA_ARGS__
) - I wonder if something new in C++20 or C++23 would make this possible ?
EDIT: I am now looking for a solution using boost/preprocessor
.
Overload the macro on number of arguments.
#include <vector>
#include <string>
#include <iostream>
#define FOREACH_STRINGIFY_1(a) #a
#define FOREACH_STRINGIFY_2(a, ...) #a, FOREACH_STRINGIFY_1(__VA_ARGS__)
#define FOREACH_STRINGIFY_3(a, ...) #a, FOREACH_STRINGIFY_2(__VA_ARGS__)
#define FOREACH_STRINGIFY_4(a, ...) #a, FOREACH_STRINGIFY_3(__VA_ARGS__)
#define FOREACH_STRINGIFY_N(_4,_3,_2,_1,N,...) \
FOREACH_STRINGIFY##N
#define FOREACH_STRINGIFY(...) \
FOREACH_STRINGIFY_N(__VA_ARGS__,_4,_3,_2,_1) \
(__VA_ARGS__)
#define MAKE_ENUM_AND_STRINGS(...) \
enum test_enum{ __VA_ARGS__ }; \
std::vector<std::string> test_vector{ \
FOREACH_STRINGIFY(__VA_ARGS__) \
}
int main() {
MAKE_ENUM_AND_STRINGS(a, b, c, d);
for (auto&& i : test_vector) {
std::cout << i << '\n';
}
}
I think this is an unusual way to have a way to stringify enums. I think usually X macros method is used. Consider using an existing stringifing enum library, instead of reinventing the wheel, there are so many of them, like How to convert an enum to a string in modern C++ .
I am now looking for a solution using boost/preprocessor tho
#include <vector>
#include <string>
#include <iostream>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/list/for_each.hpp>
#include <boost/preprocessor/variadic/to_list.hpp>
#define MAKE_ENUM_AND_STRINGS_CALLBACK(r, data, elem) \
BOOST_PP_STRINGIZE(elem),
#define MAKE_ENUM_AND_STRINGS(...) \
enum test_enum { __VA_ARGS__ }; \
std::vector<std::string> test_vector{ \
BOOST_PP_LIST_FOR_EACH( \
MAKE_ENUM_AND_STRINGS_CALLBACK, \
_, \
BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__) \
) \
}
int main() {
MAKE_ENUM_AND_STRINGS(a, b, c, d);
for (auto&& i : test_vector) {
std::cout << i << '\n';
}
}