构建一组对象并将它们放入一个元组中
Build a set of objects and place them into a tuple
基本上我需要做的是这样的:
int a = 1;
float q = 3.3;
char g = 'e';
// ... other useful variables...
auto my_tuple = std::make_tuple(a, q, g/*, ... and so on... */);
现在,我总是担心忘记将我的变量添加到 my_tuple,每次我需要添加一个新变量时,既要添加一个变量又要将变量添加到元组中是很无聊的。
所以我想知道是否有任何方法可以用宏来做这样的事情。作为一个例子,我可以做
#define DECLARE_VARIABLE(t, n, v) t n = v;
但这只会创建变量。有没有办法添加类似
的东西
#define END_OF_VARIABLES .....
这样我就可以写了
DECLARE_VARIABLE(int, a, 1)
DECLARE_VARIABLE(float, q, 3.3)
DECLARE_VARIABLE(char, g, 'e')
// ...
END_OF_VARIABLES
my_tuple 是自动构建的吗?
我也可以接受导致相同结果的类似解决方案,例如
DECLARE_ALL_VARIABLES_AND_BUILD_MY_TUPLE(int, a, 1, float, q, 3.3, char, g, 'e'/*...*/)
也可以。
有没有可能做这样的事情?
我认为这不是解决问题的最佳方式。底部有一个直接的解决方案,但在我们开始之前:我会考虑的事情:
- 使用 struct/class 而不是元组
- 使用枚举使元组元素更易读
- 使用访问器 class 将元组元素映射到有意义的命名 getter 函数
- 使用接受元组作为参数的有意义命名的访问器函数
如果您仍然确定要使用预处理器执行此操作:存在 Boost.Preprocessor,有了它,各种或多或少疯狂的预处理器技巧成为可能。你可以像这样做你想做的事:
#include <boost/preprocessor.hpp>
#define DECLARE_VARIABLE(r, data, elem) BOOST_PP_TUPLE_ELEM(3, 0, elem) BOOST_PP_TUPLE_ELEM(3, 1, elem) = BOOST_PP_TUPLE_ELEM(3, 2, elem);
#define ISOLATE_VARNAME(r, data, elem) (BOOST_PP_TUPLE_ELEM(3, 1, elem))
#define VARSEQ ((int, x, 2)) ((char, g, 'a')) ((double, y, 2.0))
BOOST_PP_SEQ_FOR_EACH(DECLARE_VARIABLE, _, VARSEQ)
auto mytuple = std::make_tuple(BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(ISOLATE_VARNAME, _, VARSEQ)));
这里 VARSEQ
是 Boost.PP 所谓的 序列 的 元组 。序列是某种形式
(a)(b)(c)
元组是某种形式
(a, b, c)
我用的"functions"是
BOOST_PP_TUPLE_ELEM
从元组中提取一个元素
BOOST_PP_SEQ_FOR_EACH
将宏应用于序列的所有元素
BOOST_PP_SEQ_ENUM
列出序列中的所有元素,元素之间用逗号分隔
有关详细信息,请参阅上述文档的 link。
该实现是开源的,顺便说一句,如果您完全是疯子的话,这是一本有趣的读物;他们真的不得不使用预处理器给他们的东西。循环是用长级联的编号宏模拟的,其中一个扩展到它应该做的事情,级联中的下一个宏继续循环,以及一个文件是 #include
d 的 BOOST_PP_ITERATE
东西多次使用不同的流控制宏定义是我见过的在生产代码中从未使用过的最巧妙的技巧之一。
基本上我需要做的是这样的:
int a = 1;
float q = 3.3;
char g = 'e';
// ... other useful variables...
auto my_tuple = std::make_tuple(a, q, g/*, ... and so on... */);
现在,我总是担心忘记将我的变量添加到 my_tuple,每次我需要添加一个新变量时,既要添加一个变量又要将变量添加到元组中是很无聊的。
所以我想知道是否有任何方法可以用宏来做这样的事情。作为一个例子,我可以做
#define DECLARE_VARIABLE(t, n, v) t n = v;
但这只会创建变量。有没有办法添加类似
的东西#define END_OF_VARIABLES .....
这样我就可以写了
DECLARE_VARIABLE(int, a, 1)
DECLARE_VARIABLE(float, q, 3.3)
DECLARE_VARIABLE(char, g, 'e')
// ...
END_OF_VARIABLES
my_tuple 是自动构建的吗? 我也可以接受导致相同结果的类似解决方案,例如
DECLARE_ALL_VARIABLES_AND_BUILD_MY_TUPLE(int, a, 1, float, q, 3.3, char, g, 'e'/*...*/)
也可以。
有没有可能做这样的事情?
我认为这不是解决问题的最佳方式。底部有一个直接的解决方案,但在我们开始之前:我会考虑的事情:
- 使用 struct/class 而不是元组
- 使用枚举使元组元素更易读
- 使用访问器 class 将元组元素映射到有意义的命名 getter 函数
- 使用接受元组作为参数的有意义命名的访问器函数
如果您仍然确定要使用预处理器执行此操作:存在 Boost.Preprocessor,有了它,各种或多或少疯狂的预处理器技巧成为可能。你可以像这样做你想做的事:
#include <boost/preprocessor.hpp>
#define DECLARE_VARIABLE(r, data, elem) BOOST_PP_TUPLE_ELEM(3, 0, elem) BOOST_PP_TUPLE_ELEM(3, 1, elem) = BOOST_PP_TUPLE_ELEM(3, 2, elem);
#define ISOLATE_VARNAME(r, data, elem) (BOOST_PP_TUPLE_ELEM(3, 1, elem))
#define VARSEQ ((int, x, 2)) ((char, g, 'a')) ((double, y, 2.0))
BOOST_PP_SEQ_FOR_EACH(DECLARE_VARIABLE, _, VARSEQ)
auto mytuple = std::make_tuple(BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(ISOLATE_VARNAME, _, VARSEQ)));
这里 VARSEQ
是 Boost.PP 所谓的 序列 的 元组 。序列是某种形式
(a)(b)(c)
元组是某种形式
(a, b, c)
我用的"functions"是
BOOST_PP_TUPLE_ELEM
从元组中提取一个元素BOOST_PP_SEQ_FOR_EACH
将宏应用于序列的所有元素BOOST_PP_SEQ_ENUM
列出序列中的所有元素,元素之间用逗号分隔
有关详细信息,请参阅上述文档的 link。
该实现是开源的,顺便说一句,如果您完全是疯子的话,这是一本有趣的读物;他们真的不得不使用预处理器给他们的东西。循环是用长级联的编号宏模拟的,其中一个扩展到它应该做的事情,级联中的下一个宏继续循环,以及一个文件是 #include
d 的 BOOST_PP_ITERATE
东西多次使用不同的流控制宏定义是我见过的在生产代码中从未使用过的最巧妙的技巧之一。