c ++宏参数化(重复)扩展
c++ macro parametrized (repetitive) expansion
我正在使用一个枚举集(c 风格)id_t
来表示不同的测试参数 T0、T1、……然后这些“参数”在两个数组中“重复”;一个 idsenum
保存值 T0、T1、...它们自己,另一个 idstxt
保存它们的文本表示“T0”、“T1”、...
#define enumsetmacro T0, T1, T2
enum id_t { enumsetmacro }; // enum proper
vector<id_t> idsenum { enumsetmacro }; // in array => so can interate over values
vector<string> idstxt { "T0", "T1", "T2" }; // textual repr. parallel to idsenum
我经常更改“参数”的数量,然后必须修改枚举集本身(通过宏 enumsetmacro
)和 idstxt
.
中的文本表示
问题:一些宏魔术可以做到这一点吗?例如。虚构代码:
#define Nparams 3;
#define enumsetmacroids macroexpand("T", Nparams)
#define enumsetmacroidstxt macroexpand("\"T\"", Nparams)
enum id_t { enumsetmacroids }; // enum proper
vector<id_t> idsenum { enumsetmacroids };
vector<string> idstxt { enumsetmacroidstxt };
在哪里
macroexpand("T", 3) => (string) T0, T1, T2
macroexpand("\"T\"", 3) => (string) "T0", "T1", "T2"
好吧,我知道这看起来很幼稚,可能不可能...?
使用boost.preprocessor:
#include <boost/preprocessor/seq.hpp>
#include <boost/preprocessor/for.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <string>
#include <vector>
#include <cassert>
#define DECL_ENUM_IDENTITY(a_r, a_dummy, a_elem) \
a_elem,
#define DECL_ENUM_STR(a_r, a_dummy, a_elem) \
BOOST_PP_STRINGIZE(a_elem),
#define DECL_ENUM_IMPL(a_seq) \
enum myid_t { BOOST_PP_SEQ_FOR_EACH(DECL_ENUM_IDENTITY, a_dummy, a_seq) }; \
::std::vector< myid_t > idsenum { BOOST_PP_SEQ_FOR_EACH(DECL_ENUM_IDENTITY, a_dummy, a_seq) }; \
::std::vector< ::std::string > idstxt { BOOST_PP_SEQ_FOR_EACH(DECL_ENUM_STR, a_dummy, a_seq) };
#define DECL_ELEMENT(a_r, a_index, a_name) \
( a_name ## a_index )
#define DECL_ENUM(a_name, a_count) \
DECL_ENUM_IMPL(BOOST_PP_REPEAT(a_count, DECL_ELEMENT, a_name))
DECL_ENUM(T, 3)
int main()
{
assert(3 == idsenum.size());
assert(myid_t::T0 == idsenum.front());
assert(myid_t::T2 == idsenum.back());
assert(3 == idstxt.size());
assert("T0" == idstxt.front());
assert("T2" == idstxt.back());
}
我正在使用一个枚举集(c 风格)id_t
来表示不同的测试参数 T0、T1、……然后这些“参数”在两个数组中“重复”;一个 idsenum
保存值 T0、T1、...它们自己,另一个 idstxt
保存它们的文本表示“T0”、“T1”、...
#define enumsetmacro T0, T1, T2
enum id_t { enumsetmacro }; // enum proper
vector<id_t> idsenum { enumsetmacro }; // in array => so can interate over values
vector<string> idstxt { "T0", "T1", "T2" }; // textual repr. parallel to idsenum
我经常更改“参数”的数量,然后必须修改枚举集本身(通过宏 enumsetmacro
)和 idstxt
.
问题:一些宏魔术可以做到这一点吗?例如。虚构代码:
#define Nparams 3;
#define enumsetmacroids macroexpand("T", Nparams)
#define enumsetmacroidstxt macroexpand("\"T\"", Nparams)
enum id_t { enumsetmacroids }; // enum proper
vector<id_t> idsenum { enumsetmacroids };
vector<string> idstxt { enumsetmacroidstxt };
在哪里
macroexpand("T", 3) => (string) T0, T1, T2
macroexpand("\"T\"", 3) => (string) "T0", "T1", "T2"
好吧,我知道这看起来很幼稚,可能不可能...?
使用boost.preprocessor:
#include <boost/preprocessor/seq.hpp>
#include <boost/preprocessor/for.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <string>
#include <vector>
#include <cassert>
#define DECL_ENUM_IDENTITY(a_r, a_dummy, a_elem) \
a_elem,
#define DECL_ENUM_STR(a_r, a_dummy, a_elem) \
BOOST_PP_STRINGIZE(a_elem),
#define DECL_ENUM_IMPL(a_seq) \
enum myid_t { BOOST_PP_SEQ_FOR_EACH(DECL_ENUM_IDENTITY, a_dummy, a_seq) }; \
::std::vector< myid_t > idsenum { BOOST_PP_SEQ_FOR_EACH(DECL_ENUM_IDENTITY, a_dummy, a_seq) }; \
::std::vector< ::std::string > idstxt { BOOST_PP_SEQ_FOR_EACH(DECL_ENUM_STR, a_dummy, a_seq) };
#define DECL_ELEMENT(a_r, a_index, a_name) \
( a_name ## a_index )
#define DECL_ENUM(a_name, a_count) \
DECL_ENUM_IMPL(BOOST_PP_REPEAT(a_count, DECL_ELEMENT, a_name))
DECL_ENUM(T, 3)
int main()
{
assert(3 == idsenum.size());
assert(myid_t::T0 == idsenum.front());
assert(myid_t::T2 == idsenum.back());
assert(3 == idstxt.size());
assert("T0" == idstxt.front());
assert("T2" == idstxt.back());
}