没有好办法。
使用一些繁重的宏,您可以实现F(a = ARG(a)) 之类的语法(其中F 和ARG 是宏),它会有点工作,但有很大的限制(见下文) .
这是一个依赖于 libfmt 的示例实现:
#define F(...) F_LOW( (str, __VA_ARGS__ ) )
#define ARG(...) )(expr, __VA_ARGS__ )(str,
#define F_LOW(...) ::fmt::format(F_END(F_STR_LOOP_A __VA_ARGS__) F_END(F_ARG_LOOP_A __VA_ARGS__))
#define F_END(...) F_END_(__VA_ARGS__)
#define F_END_(...) __VA_ARGS__##_END
#define F_CAT(a, b) F_CAT_(a, b)
#define F_CAT_(a, b) a##b
#define F_STR_LOOP_A(...) F_STR_LOOP_BODY(__VA_ARGS__) F_STR_LOOP_B
#define F_STR_LOOP_B(...) F_STR_LOOP_BODY(__VA_ARGS__) F_STR_LOOP_A
#define F_STR_LOOP_A_END
#define F_STR_LOOP_B_END
#define F_STR_LOOP_BODY(tag, ...) F_CAT(F_STR_LOOP_BODY_, tag)(__VA_ARGS__)
#define F_STR_LOOP_BODY_str(...) #__VA_ARGS__
#define F_STR_LOOP_BODY_expr(...) "{}"
#define F_ARG_LOOP_A(...) F_ARG_LOOP_BODY(__VA_ARGS__) F_ARG_LOOP_B
#define F_ARG_LOOP_B(...) F_ARG_LOOP_BODY(__VA_ARGS__) F_ARG_LOOP_A
#define F_ARG_LOOP_A_END
#define F_ARG_LOOP_B_END
#define F_ARG_LOOP_BODY(tag, ...) F_CAT(F_ARG_LOOP_BODY_, tag)(__VA_ARGS__)
#define F_ARG_LOOP_BODY_str(...)
#define F_ARG_LOOP_BODY_expr(...) , __VA_ARGS__
例如,使用这些宏 F(a=ARG(a), b=ARG(b)) 将等同于 pythonic f"a={a}, b={b}",并将扩展为
::fmt::format("a=" "{}" ", b=" "{}" "", a, b)
相当于
::fmt::format("a={}, b={}", a, b)
目前看起来不错?它甚至可以处理转义序列(以某种方式)!
这里是提到的主要缺点:
-
任何空白字符序列都将替换为单个空格。
- 此外,所有前导和尾随空格以及
ARG 周围的所有空格都将被删除。
-
字符串中的所有宏都被展开。
-
字符串不能包含不平衡的括号。
-
ARG(...) 不能出现在括号内。
IMO,这使得它无法用于除调试输出之外的任何内容。
可能的解决方法包括:
奖励:使用正确的标志(或#pragmas),大多数编译器都允许您在宏名称中包含$。这意味着您可以使用$(expr) 而不是ARG(expr),如果您愿意...